4
* Description: This module contains routines related to
5
* the environment, such as storing connection handles,
6
* and returning errors.
8
* Classes: EnvironmentClass (Functions prefix: "EN_")
10
* API functions: SQLAllocEnv, SQLFreeEnv, SQLError
12
* Comments: See "notice.txt" for copyright and license information.
18
#include "connection.h"
19
#include "dlg_specific.h"
20
#include "statement.h"
23
#include "pgapifunc.h"
29
extern GLOBAL_VALUES globals;
31
/* The one instance of the handles */
32
static int conns_count = 0;
33
static ConnectionClass **conns = NULL;
35
#if defined(WIN_MULTITHREAD_SUPPORT)
36
CRITICAL_SECTION conns_cs;
37
CRITICAL_SECTION common_cs; /* commonly used for short term blocking */
38
CRITICAL_SECTION common_lcs; /* commonly used for not necessarily short term blocking */
39
#elif defined(POSIX_MULTITHREAD_SUPPORT)
40
pthread_mutex_t conns_cs;
41
pthread_mutex_t common_cs;
42
pthread_mutex_t common_lcs;
43
#endif /* WIN_MULTITHREAD_SUPPORT */
45
void shortterm_common_lock()
49
void shortterm_common_unlock()
58
ConnectionClass * const *getConnList()
64
PGAPI_AllocEnv(HENV FAR * phenv)
66
CSTR func = "PGAPI_AllocEnv";
67
SQLRETURN ret = SQL_SUCCESS;
69
mylog("**** in %s ** \n", func);
72
* Hack for systems on which none of the constructor-making techniques
73
* in psqlodbc.c work: if globals appears not to have been
74
* initialized, then cause it to be initialized. Since this should be
75
* the first function called in this shared library, doing it here
78
if (globals.socket_buffersize <= 0)
80
initialize_global_cs();
81
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
84
*phenv = (HENV) EN_Constructor();
87
*phenv = SQL_NULL_HENV;
88
EN_log_error(func, "Error allocating environment", NULL);
92
mylog("** exit %s: phenv = %p **\n", func, *phenv);
98
PGAPI_FreeEnv(HENV henv)
100
CSTR func = "PGAPI_FreeEnv";
101
SQLRETURN ret = SQL_SUCCESS;
102
EnvironmentClass *env = (EnvironmentClass *) henv;
104
mylog("**** in PGAPI_FreeEnv: env = %p ** \n", env);
106
if (env && EN_Destructor(env))
108
#ifdef _HANDLE_ENLIST_IN_DTC_
110
#endif /* _HANDLE_ENLIST_IN_DTC_ */
117
EN_log_error(func, "Error freeing environment", env);
124
pg_sqlstate_set(const EnvironmentClass *env, UCHAR *szSqlState, const UCHAR *ver3str, const UCHAR *ver2str)
126
strcpy(szSqlState, EN_is_odbc3(env) ? ver3str : ver2str);
129
PG_ErrorInfo *ER_Constructor(SDWORD errnumber, const char *msg)
132
ssize_t aladd, errsize;
134
if (DESC_OK == errnumber)
138
errsize = strlen(msg);
146
error = (PG_ErrorInfo *) malloc(sizeof(PG_ErrorInfo) + aladd);
149
memset(error, 0, sizeof(PG_ErrorInfo));
150
error->status = errnumber;
151
error->errorsize = (Int4) errsize;
153
memcpy(error->__error_message, msg, errsize);
154
error->__error_message[aladd] = '\0';
161
ER_Destructor(PG_ErrorInfo *self)
166
PG_ErrorInfo *ER_Dup(const PG_ErrorInfo *self)
173
alsize = sizeof(PG_ErrorInfo);
174
if (self->errorsize > 0)
175
alsize += self->errorsize;
176
new = (PG_ErrorInfo *) malloc(alsize);
177
memcpy(new, self, alsize);
182
#define DRVMNGRDIV 511
183
/* Returns the next SQL error information. */
185
ER_ReturnError(PG_ErrorInfo **pgerror,
186
SQLSMALLINT RecNumber,
187
SQLCHAR FAR * szSqlState,
188
SQLINTEGER FAR * pfNativeError,
189
SQLCHAR FAR * szErrorMsg,
190
SQLSMALLINT cbErrorMsgMax,
191
SQLSMALLINT FAR * pcbErrorMsg,
194
CSTR func = "ER_ReturnError";
195
/* CC: return an error of a hstmt */
197
BOOL partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),
198
clear_str = ((flag & PODBC_ERROR_CLEAR) != 0);
200
SWORD msglen, stapos, wrtlen, pcblen;
202
if (!pgerror || !*pgerror)
203
return SQL_NO_DATA_FOUND;
205
msg = error->__error_message;
206
mylog("%s: status = %d, msg = #%s#\n", func, error->status, msg);
207
msglen = (SQLSMALLINT) strlen(msg);
209
* Even though an application specifies a larger error message
210
* buffer, the driver manager changes it silently.
211
* Therefore we divide the error message into ...
213
if (error->recsize < 0)
215
if (cbErrorMsgMax > 0)
216
error->recsize = cbErrorMsgMax - 1; /* apply the first request */
218
error->recsize = DRVMNGRDIV;
222
if (0 == error->errorpos)
225
RecNumber = 2 + (error->errorpos - 1) / error->recsize;
227
stapos = (RecNumber - 1) * error->recsize;
229
return SQL_NO_DATA_FOUND;
230
pcblen = wrtlen = msglen - stapos;
231
if (pcblen > error->recsize)
232
pcblen = error->recsize;
233
if (0 == cbErrorMsgMax)
235
else if (wrtlen >= cbErrorMsgMax)
238
wrtlen = cbErrorMsgMax - 1;
239
else if (cbErrorMsgMax <= error->recsize)
242
wrtlen = error->recsize;
246
if (NULL != pcbErrorMsg)
247
*pcbErrorMsg = pcblen;
249
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
251
memcpy(szErrorMsg, msg + stapos, wrtlen);
252
szErrorMsg[wrtlen] = '\0';
255
if (NULL != pfNativeError)
256
*pfNativeError = error->status;
258
if (NULL != szSqlState)
259
strncpy_null(szSqlState, error->sqlstate, 6);
261
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);
264
error->errorpos = stapos + wrtlen;
265
if (error->errorpos >= msglen)
267
ER_Destructor(error);
272
return SQL_SUCCESS_WITH_INFO;
279
PGAPI_ConnectError( HDBC hdbc,
280
SQLSMALLINT RecNumber,
281
SQLCHAR FAR * szSqlState,
282
SQLINTEGER FAR * pfNativeError,
283
SQLCHAR FAR * szErrorMsg,
284
SQLSMALLINT cbErrorMsgMax,
285
SQLSMALLINT FAR * pcbErrorMsg,
288
ConnectionClass *conn = (ConnectionClass *) hdbc;
289
EnvironmentClass *env = (EnvironmentClass *) conn->henv;
292
BOOL once_again = FALSE;
295
mylog("**** PGAPI_ConnectError: hdbc=%p <%d>\n", hdbc, cbErrorMsgMax);
296
if (RecNumber != 1 && RecNumber != -1)
297
return SQL_NO_DATA_FOUND;
298
if (cbErrorMsgMax < 0)
300
if (CONN_EXECUTING == conn->status || !CC_get_error(conn, &status, &msg) || NULL == msg)
302
mylog("CC_Get_error returned nothing.\n");
303
if (NULL != szSqlState)
304
strcpy(szSqlState, "00000");
305
if (NULL != pcbErrorMsg)
307
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
308
szErrorMsg[0] = '\0';
310
return SQL_NO_DATA_FOUND;
312
mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
314
msglen = strlen(msg);
315
if (NULL != pcbErrorMsg)
317
*pcbErrorMsg = (SQLSMALLINT) msglen;
318
if (cbErrorMsgMax == 0)
320
else if (msglen >= cbErrorMsgMax)
321
*pcbErrorMsg = cbErrorMsgMax - 1;
323
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
324
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
325
if (NULL != pfNativeError)
326
*pfNativeError = status;
328
if (NULL != szSqlState)
330
if (conn->sqlstate[0])
331
strcpy(szSqlState, conn->sqlstate);
335
case CONN_OPTION_VALUE_CHANGED:
336
pg_sqlstate_set(env, szSqlState, "01S02", "01S02");
339
pg_sqlstate_set(env, szSqlState, "01004", "01004");
342
case CONN_INIREAD_ERROR:
343
pg_sqlstate_set(env, szSqlState, "IM002", "IM002");
344
/* data source not found */
346
case CONNECTION_SERVER_NOT_REACHED:
347
case CONN_OPENDB_ERROR:
348
pg_sqlstate_set(env, szSqlState, "08001", "08001");
349
/* unable to connect to data source */
351
case CONN_INVALID_AUTHENTICATION:
352
case CONN_AUTH_TYPE_UNSUPPORTED:
353
pg_sqlstate_set(env, szSqlState, "28000", "28000");
355
case CONN_STMT_ALLOC_ERROR:
356
pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
357
/* memory allocation failure */
360
pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
363
case CONN_UNSUPPORTED_OPTION:
364
pg_sqlstate_set(env, szSqlState, "HYC00", "IM001");
365
/* driver does not support this function */
367
case CONN_INVALID_ARGUMENT_NO:
368
pg_sqlstate_set(env, szSqlState, "HY009", "S1009");
369
/* invalid argument value */
371
case CONN_TRANSACT_IN_PROGRES:
372
pg_sqlstate_set(env, szSqlState, "HY010", "S1010");
375
* when the user tries to switch commit mode in a
378
/* -> function sequence error */
380
case CONN_NO_MEMORY_ERROR:
381
pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
383
case CONN_NOT_IMPLEMENTED_ERROR:
384
pg_sqlstate_set(env, szSqlState, "HYC00", "S1C00");
386
case CONN_VALUE_OUT_OF_RANGE:
387
pg_sqlstate_set(env, szSqlState, "HY019", "22003");
389
case CONNECTION_COULD_NOT_SEND:
390
case CONNECTION_COULD_NOT_RECEIVE:
391
case CONNECTION_COMMUNICATION_ERROR:
392
case CONNECTION_NO_RESPONSE:
393
pg_sqlstate_set(env, szSqlState, "08S01", "08S01");
396
pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
402
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState ? (char *) szSqlState : PRINT_NULL, msglen, szErrorMsg ? (char *) szErrorMsg : PRINT_NULL);
405
CC_set_errornumber(conn, status);
406
return SQL_SUCCESS_WITH_INFO;
413
PGAPI_EnvError( HENV henv,
414
SQLSMALLINT RecNumber,
415
SQLCHAR FAR * szSqlState,
416
SQLINTEGER FAR * pfNativeError,
417
SQLCHAR FAR * szErrorMsg,
418
SQLSMALLINT cbErrorMsgMax,
419
SQLSMALLINT FAR * pcbErrorMsg,
422
EnvironmentClass *env = (EnvironmentClass *) henv;
426
mylog("**** PGAPI_EnvError: henv=%p <%d>\n", henv, cbErrorMsgMax);
427
if (RecNumber != 1 && RecNumber != -1)
428
return SQL_NO_DATA_FOUND;
429
if (cbErrorMsgMax < 0)
431
if (!EN_get_error(env, &status, &msg) || NULL == msg)
433
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
435
if (NULL != szSqlState)
436
pg_sqlstate_set(env, szSqlState, "00000", "00000");
437
if (NULL != pcbErrorMsg)
439
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
440
szErrorMsg[0] = '\0';
442
return SQL_NO_DATA_FOUND;
444
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
446
if (NULL != pcbErrorMsg)
447
*pcbErrorMsg = (SQLSMALLINT) strlen(msg);
448
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
449
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
450
if (NULL != pfNativeError)
451
*pfNativeError = status;
457
case ENV_ALLOC_ERROR:
458
/* memory allocation failure */
459
pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
462
pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
472
/* Returns the next SQL error information. */
478
SQLCHAR FAR * szSqlState,
479
SQLINTEGER FAR * pfNativeError,
480
SQLCHAR FAR * szErrorMsg,
481
SQLSMALLINT cbErrorMsgMax,
482
SQLSMALLINT FAR * pcbErrorMsg)
485
UWORD flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR;
487
mylog("**** PGAPI_Error: henv=%p, hdbc=%p hstmt=%d\n", henv, hdbc, hstmt);
489
if (cbErrorMsgMax < 0)
491
if (SQL_NULL_HSTMT != hstmt)
492
ret = PGAPI_StmtError(hstmt, -1, szSqlState, pfNativeError,
493
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
494
else if (SQL_NULL_HDBC != hdbc)
495
ret = PGAPI_ConnectError(hdbc, -1, szSqlState, pfNativeError,
496
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
497
else if (SQL_NULL_HENV != henv)
498
ret = PGAPI_EnvError(henv, -1, szSqlState, pfNativeError,
499
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
502
if (NULL != szSqlState)
503
strcpy(szSqlState, "00000");
504
if (NULL != pcbErrorMsg)
506
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
507
szErrorMsg[0] = '\0';
509
ret = SQL_NO_DATA_FOUND;
511
mylog("**** PGAPI_Error exit code=%d\n", ret);
516
* EnvironmentClass implementation
521
EnvironmentClass *rv = NULL;
523
WORD wVersionRequested;
525
const int major = 2, minor = 2;
527
/* Load the WinSock Library */
528
wVersionRequested = MAKEWORD(major, minor);
530
if (WSAStartup(wVersionRequested, &wsaData))
532
mylog("%s: WSAStartup error\n", __FUNCTION__);
535
/* Verify that this is the minimum version of WinSock */
536
if (LOBYTE(wsaData.wVersion) >= 1 &&
537
(LOBYTE(wsaData.wVersion) >= 2 ||
538
HIBYTE(wsaData.wVersion) >= 1))
542
mylog("%s: WSAStartup version=(%d,%d)\n", __FUNCTION__,
543
LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
548
rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass));
551
mylog("%s: malloc error\n", __FUNCTION__);
571
EN_Destructor(EnvironmentClass *self)
576
mylog("in EN_Destructor, self=%p\n", self);
581
* the error messages are static strings distributed throughout the
582
* source--they should not be freed
585
/* Free any connections belonging to this environment */
586
for (lf = 0, nullcnt = 0; lf < conns_count; lf++)
588
if (NULL == conns[lf])
590
else if (conns[lf]->henv == self)
592
if (CC_Destructor(conns[lf]))
599
if (conns && nullcnt >= conns_count)
601
mylog("clearing conns count=%d\n", conns_count);
612
mylog("exit EN_Destructor: rv = %d\n", rv);
613
#ifdef _MEMORY_DEBUG_
614
debug_memory_check();
615
#endif /* _MEMORY_DEBUG_ */
621
EN_get_error(EnvironmentClass *self, int *number, char **message)
623
if (self && self->errormsg && self->errornumber)
625
*message = self->errormsg;
626
*number = self->errornumber;
628
self->errornumber = 0;
635
#define INIT_CONN_COUNT 128
638
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
641
ConnectionClass **newa;
644
mylog("EN_add_connection: self = %p, conn = %p\n", self, conn);
647
for (i = 0; i < conns_count; i++)
654
mylog(" added at i=%d, conn->henv = %p, conns[i]->henv = %p\n", i, conn->henv, conns[i]->henv);
659
alloc = 2 * conns_count;
661
alloc = INIT_CONN_COUNT;
662
if (newa = (ConnectionClass **) realloc(conns, alloc * sizeof(ConnectionClass *)), NULL == newa)
665
newa[conns_count] = conn;
668
mylog(" added at %d, conn->henv = %p, conns[%d]->henv = %p\n", conns_count, conn->henv, conns_count, conns[conns_count]->henv);
669
for (i = conns_count + 1; i < alloc; i++)
679
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
683
for (i = 0; i < conns_count; i++)
684
if (conns[i] == conn && conns[i]->status != CONN_EXECUTING)
697
EN_log_error(const char *func, char *desc, EnvironmentClass *self)
700
qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
702
qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
4
* Description: This module contains routines related to
5
* the environment, such as storing connection handles,
6
* and returning errors.
8
* Classes: EnvironmentClass (Functions prefix: "EN_")
10
* API functions: SQLAllocEnv, SQLFreeEnv, SQLError
12
* Comments: See "readme.txt" for copyright and license information.
18
#include "connection.h"
19
#include "dlg_specific.h"
20
#include "statement.h"
23
#include "pgapifunc.h"
29
extern GLOBAL_VALUES globals;
31
/* The one instance of the handles */
32
static int conns_count = 0;
33
static ConnectionClass **conns = NULL;
35
#if defined(WIN_MULTITHREAD_SUPPORT)
36
CRITICAL_SECTION conns_cs;
37
CRITICAL_SECTION common_cs; /* commonly used for short term blocking */
38
CRITICAL_SECTION common_lcs; /* commonly used for not necessarily short term blocking */
39
#elif defined(POSIX_MULTITHREAD_SUPPORT)
40
pthread_mutex_t conns_cs;
41
pthread_mutex_t common_cs;
42
pthread_mutex_t common_lcs;
43
#endif /* WIN_MULTITHREAD_SUPPORT */
45
void shortterm_common_lock()
49
void shortterm_common_unlock()
58
ConnectionClass * const *getConnList()
64
PGAPI_AllocEnv(HENV FAR * phenv)
66
CSTR func = "PGAPI_AllocEnv";
67
SQLRETURN ret = SQL_SUCCESS;
69
mylog("**** in %s ** \n", func);
72
* Hack for systems on which none of the constructor-making techniques
73
* in psqlodbc.c work: if globals appears not to have been
74
* initialized, then cause it to be initialized. Since this should be
75
* the first function called in this shared library, doing it here
78
if (globals.socket_buffersize <= 0)
80
initialize_global_cs();
81
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
84
*phenv = (HENV) EN_Constructor();
87
*phenv = SQL_NULL_HENV;
88
EN_log_error(func, "Error allocating environment", NULL);
92
mylog("** exit %s: phenv = %p **\n", func, *phenv);
98
PGAPI_FreeEnv(HENV henv)
100
CSTR func = "PGAPI_FreeEnv";
101
SQLRETURN ret = SQL_SUCCESS;
102
EnvironmentClass *env = (EnvironmentClass *) henv;
104
mylog("**** in PGAPI_FreeEnv: env = %p ** \n", env);
106
if (env && EN_Destructor(env))
108
#ifdef _HANDLE_ENLIST_IN_DTC_
110
#endif /* _HANDLE_ENLIST_IN_DTC_ */
117
EN_log_error(func, "Error freeing environment", env);
124
pg_sqlstate_set(const EnvironmentClass *env, UCHAR *szSqlState, const UCHAR *ver3str, const UCHAR *ver2str)
126
strcpy(szSqlState, EN_is_odbc3(env) ? ver3str : ver2str);
129
PG_ErrorInfo *ER_Constructor(SDWORD errnumber, const char *msg)
132
ssize_t aladd, errsize;
134
if (DESC_OK == errnumber)
138
errsize = strlen(msg);
146
error = (PG_ErrorInfo *) malloc(sizeof(PG_ErrorInfo) + aladd);
149
memset(error, 0, sizeof(PG_ErrorInfo));
150
error->status = errnumber;
151
error->errorsize = (Int4) errsize;
153
memcpy(error->__error_message, msg, errsize);
154
error->__error_message[aladd] = '\0';
161
ER_Destructor(PG_ErrorInfo *self)
166
PG_ErrorInfo *ER_Dup(const PG_ErrorInfo *self)
173
alsize = sizeof(PG_ErrorInfo);
174
if (self->errorsize > 0)
175
alsize += self->errorsize;
176
new = (PG_ErrorInfo *) malloc(alsize);
177
memcpy(new, self, alsize);
182
#define DRVMNGRDIV 511
183
/* Returns the next SQL error information. */
185
ER_ReturnError(PG_ErrorInfo **pgerror,
186
SQLSMALLINT RecNumber,
187
SQLCHAR FAR * szSqlState,
188
SQLINTEGER FAR * pfNativeError,
189
SQLCHAR FAR * szErrorMsg,
190
SQLSMALLINT cbErrorMsgMax,
191
SQLSMALLINT FAR * pcbErrorMsg,
194
CSTR func = "ER_ReturnError";
195
/* CC: return an error of a hstmt */
197
BOOL partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),
198
clear_str = ((flag & PODBC_ERROR_CLEAR) != 0);
200
SWORD msglen, stapos, wrtlen, pcblen;
202
if (!pgerror || !*pgerror)
203
return SQL_NO_DATA_FOUND;
205
msg = error->__error_message;
206
mylog("%s: status = %d, msg = #%s#\n", func, error->status, msg);
207
msglen = (SQLSMALLINT) strlen(msg);
209
* Even though an application specifies a larger error message
210
* buffer, the driver manager changes it silently.
211
* Therefore we divide the error message into ...
213
if (error->recsize < 0)
215
if (cbErrorMsgMax > 0)
216
error->recsize = cbErrorMsgMax - 1; /* apply the first request */
218
error->recsize = DRVMNGRDIV;
222
if (0 == error->errorpos)
225
RecNumber = 2 + (error->errorpos - 1) / error->recsize;
227
stapos = (RecNumber - 1) * error->recsize;
229
return SQL_NO_DATA_FOUND;
230
pcblen = wrtlen = msglen - stapos;
231
if (pcblen > error->recsize)
232
pcblen = error->recsize;
233
if (0 == cbErrorMsgMax)
235
else if (wrtlen >= cbErrorMsgMax)
238
wrtlen = cbErrorMsgMax - 1;
239
else if (cbErrorMsgMax <= error->recsize)
242
wrtlen = error->recsize;
246
if (NULL != pcbErrorMsg)
247
*pcbErrorMsg = pcblen;
249
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
251
memcpy(szErrorMsg, msg + stapos, wrtlen);
252
szErrorMsg[wrtlen] = '\0';
255
if (NULL != pfNativeError)
256
*pfNativeError = error->status;
258
if (NULL != szSqlState)
259
strncpy_null(szSqlState, error->sqlstate, 6);
261
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);
264
error->errorpos = stapos + wrtlen;
265
if (error->errorpos >= msglen)
267
ER_Destructor(error);
272
return SQL_SUCCESS_WITH_INFO;
279
PGAPI_ConnectError( HDBC hdbc,
280
SQLSMALLINT RecNumber,
281
SQLCHAR FAR * szSqlState,
282
SQLINTEGER FAR * pfNativeError,
283
SQLCHAR FAR * szErrorMsg,
284
SQLSMALLINT cbErrorMsgMax,
285
SQLSMALLINT FAR * pcbErrorMsg,
288
ConnectionClass *conn = (ConnectionClass *) hdbc;
289
EnvironmentClass *env = (EnvironmentClass *) conn->henv;
292
BOOL once_again = FALSE;
295
mylog("**** PGAPI_ConnectError: hdbc=%p <%d>\n", hdbc, cbErrorMsgMax);
296
if (RecNumber != 1 && RecNumber != -1)
297
return SQL_NO_DATA_FOUND;
298
if (cbErrorMsgMax < 0)
300
if (CONN_EXECUTING == conn->status || !CC_get_error(conn, &status, &msg) || NULL == msg)
302
mylog("CC_Get_error returned nothing.\n");
303
if (NULL != szSqlState)
304
strcpy(szSqlState, "00000");
305
if (NULL != pcbErrorMsg)
307
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
308
szErrorMsg[0] = '\0';
310
return SQL_NO_DATA_FOUND;
312
mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
314
msglen = strlen(msg);
315
if (NULL != pcbErrorMsg)
317
*pcbErrorMsg = (SQLSMALLINT) msglen;
318
if (cbErrorMsgMax == 0)
320
else if (msglen >= cbErrorMsgMax)
321
*pcbErrorMsg = cbErrorMsgMax - 1;
323
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
324
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
325
if (NULL != pfNativeError)
326
*pfNativeError = status;
328
if (NULL != szSqlState)
330
if (conn->sqlstate[0])
331
strcpy(szSqlState, conn->sqlstate);
335
case CONN_OPTION_VALUE_CHANGED:
336
pg_sqlstate_set(env, szSqlState, "01S02", "01S02");
339
pg_sqlstate_set(env, szSqlState, "01004", "01004");
342
case CONN_INIREAD_ERROR:
343
pg_sqlstate_set(env, szSqlState, "IM002", "IM002");
344
/* data source not found */
346
case CONNECTION_SERVER_NOT_REACHED:
347
case CONN_OPENDB_ERROR:
348
pg_sqlstate_set(env, szSqlState, "08001", "08001");
349
/* unable to connect to data source */
351
case CONN_INVALID_AUTHENTICATION:
352
case CONN_AUTH_TYPE_UNSUPPORTED:
353
pg_sqlstate_set(env, szSqlState, "28000", "28000");
355
case CONN_STMT_ALLOC_ERROR:
356
pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
357
/* memory allocation failure */
360
pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
363
case CONN_UNSUPPORTED_OPTION:
364
pg_sqlstate_set(env, szSqlState, "HYC00", "IM001");
365
/* driver does not support this function */
367
case CONN_INVALID_ARGUMENT_NO:
368
pg_sqlstate_set(env, szSqlState, "HY009", "S1009");
369
/* invalid argument value */
371
case CONN_TRANSACT_IN_PROGRES:
372
pg_sqlstate_set(env, szSqlState, "HY010", "S1010");
375
* when the user tries to switch commit mode in a
378
/* -> function sequence error */
380
case CONN_NO_MEMORY_ERROR:
381
pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
383
case CONN_NOT_IMPLEMENTED_ERROR:
384
pg_sqlstate_set(env, szSqlState, "HYC00", "S1C00");
386
case CONN_VALUE_OUT_OF_RANGE:
387
pg_sqlstate_set(env, szSqlState, "HY019", "22003");
389
case CONNECTION_COULD_NOT_SEND:
390
case CONNECTION_COULD_NOT_RECEIVE:
391
case CONNECTION_COMMUNICATION_ERROR:
392
case CONNECTION_NO_RESPONSE:
393
pg_sqlstate_set(env, szSqlState, "08S01", "08S01");
396
pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
402
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState ? (char *) szSqlState : PRINT_NULL, msglen, szErrorMsg ? (char *) szErrorMsg : PRINT_NULL);
405
CC_set_errornumber(conn, status);
406
return SQL_SUCCESS_WITH_INFO;
413
PGAPI_EnvError( HENV henv,
414
SQLSMALLINT RecNumber,
415
SQLCHAR FAR * szSqlState,
416
SQLINTEGER FAR * pfNativeError,
417
SQLCHAR FAR * szErrorMsg,
418
SQLSMALLINT cbErrorMsgMax,
419
SQLSMALLINT FAR * pcbErrorMsg,
422
EnvironmentClass *env = (EnvironmentClass *) henv;
426
mylog("**** PGAPI_EnvError: henv=%p <%d>\n", henv, cbErrorMsgMax);
427
if (RecNumber != 1 && RecNumber != -1)
428
return SQL_NO_DATA_FOUND;
429
if (cbErrorMsgMax < 0)
431
if (!EN_get_error(env, &status, &msg) || NULL == msg)
433
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
435
if (NULL != szSqlState)
436
pg_sqlstate_set(env, szSqlState, "00000", "00000");
437
if (NULL != pcbErrorMsg)
439
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
440
szErrorMsg[0] = '\0';
442
return SQL_NO_DATA_FOUND;
444
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
446
if (NULL != pcbErrorMsg)
447
*pcbErrorMsg = (SQLSMALLINT) strlen(msg);
448
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
449
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
450
if (NULL != pfNativeError)
451
*pfNativeError = status;
457
case ENV_ALLOC_ERROR:
458
/* memory allocation failure */
459
pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
462
pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
472
/* Returns the next SQL error information. */
478
SQLCHAR FAR * szSqlState,
479
SQLINTEGER FAR * pfNativeError,
480
SQLCHAR FAR * szErrorMsg,
481
SQLSMALLINT cbErrorMsgMax,
482
SQLSMALLINT FAR * pcbErrorMsg)
485
UWORD flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR;
487
mylog("**** PGAPI_Error: henv=%p, hdbc=%p hstmt=%d\n", henv, hdbc, hstmt);
489
if (cbErrorMsgMax < 0)
491
if (SQL_NULL_HSTMT != hstmt)
492
ret = PGAPI_StmtError(hstmt, -1, szSqlState, pfNativeError,
493
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
494
else if (SQL_NULL_HDBC != hdbc)
495
ret = PGAPI_ConnectError(hdbc, -1, szSqlState, pfNativeError,
496
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
497
else if (SQL_NULL_HENV != henv)
498
ret = PGAPI_EnvError(henv, -1, szSqlState, pfNativeError,
499
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
502
if (NULL != szSqlState)
503
strcpy(szSqlState, "00000");
504
if (NULL != pcbErrorMsg)
506
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
507
szErrorMsg[0] = '\0';
509
ret = SQL_NO_DATA_FOUND;
511
mylog("**** PGAPI_Error exit code=%d\n", ret);
516
* EnvironmentClass implementation
521
EnvironmentClass *rv = NULL;
523
WORD wVersionRequested;
525
const int major = 2, minor = 2;
527
/* Load the WinSock Library */
528
wVersionRequested = MAKEWORD(major, minor);
530
if (WSAStartup(wVersionRequested, &wsaData))
532
mylog("%s: WSAStartup error\n", __FUNCTION__);
535
/* Verify that this is the minimum version of WinSock */
536
if (LOBYTE(wsaData.wVersion) >= 1 &&
537
(LOBYTE(wsaData.wVersion) >= 2 ||
538
HIBYTE(wsaData.wVersion) >= 1))
542
mylog("%s: WSAStartup version=(%d,%d)\n", __FUNCTION__,
543
LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
548
rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass));
551
mylog("%s: malloc error\n", __FUNCTION__);
571
EN_Destructor(EnvironmentClass *self)
576
mylog("in EN_Destructor, self=%p\n", self);
581
* the error messages are static strings distributed throughout the
582
* source--they should not be freed
585
/* Free any connections belonging to this environment */
587
for (lf = 0, nullcnt = 0; lf < conns_count; lf++)
589
if (NULL == conns[lf])
591
else if (conns[lf]->henv == self)
593
if (CC_Destructor(conns[lf]))
600
if (conns && nullcnt >= conns_count)
602
mylog("clearing conns count=%d\n", conns_count);
614
mylog("exit EN_Destructor: rv = %d\n", rv);
615
#ifdef _MEMORY_DEBUG_
616
debug_memory_check();
617
#endif /* _MEMORY_DEBUG_ */
623
EN_get_error(EnvironmentClass *self, int *number, char **message)
625
if (self && self->errormsg && self->errornumber)
627
*message = self->errormsg;
628
*number = self->errornumber;
630
self->errornumber = 0;
637
#define INIT_CONN_COUNT 128
640
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
643
ConnectionClass **newa;
646
mylog("EN_add_connection: self = %p, conn = %p\n", self, conn);
649
for (i = 0; i < conns_count; i++)
656
mylog(" added at i=%d, conn->henv = %p, conns[i]->henv = %p\n", i, conn->henv, conns[i]->henv);
661
alloc = 2 * conns_count;
663
alloc = INIT_CONN_COUNT;
664
if (newa = (ConnectionClass **) realloc(conns, alloc * sizeof(ConnectionClass *)), NULL == newa)
667
newa[conns_count] = conn;
670
mylog(" added at %d, conn->henv = %p, conns[%d]->henv = %p\n", conns_count, conn->henv, conns_count, conns[conns_count]->henv);
671
for (i = conns_count + 1; i < alloc; i++)
681
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
685
for (i = 0; i < conns_count; i++)
686
if (conns[i] == conn && conns[i]->status != CONN_EXECUTING)
699
EN_log_error(const char *func, char *desc, EnvironmentClass *self)
702
qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
704
qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc);