From: Hiroshi Inoue Date: Fri, 7 Sep 2001 06:02:24 +0000 (+0000) Subject: 1) Most driver options could be set per DSN. X-Git-Tag: REL7_2_BETA1~504 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=377d131b6c351e0db1bed9cc393cdba3c1eaea56;p=postgresql 1) Most driver options could be set per DSN. 2) Keep FE/BE protocol more precisely. 3) Improve procedure calls. 4) A trial to avoid PREMATURE execution(#ifdef'd now). Hiroshi Inoue --- diff --git a/src/interfaces/odbc/bind.c b/src/interfaces/odbc/bind.c index 2fc340907a..ce17236548 100644 --- a/src/interfaces/odbc/bind.c +++ b/src/interfaces/odbc/bind.c @@ -335,8 +335,14 @@ PGAPI_ParamOptions( static char *func = "PGAPI_ParamOptions"; StatementClass *stmt = (StatementClass *) hstmt; - mylog("%s: entering...\n", func); + mylog("%s: entering... %d %x\n", func, crow, pirow); + if (crow == 1) /* temporary solution and must be rewritten later */ + { + if (pirow) + *pirow = 1; + return SQL_SUCCESS; + } stmt->errornumber = CONN_UNSUPPORTED_OPTION; stmt->errormsg = "Function not implemented"; SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c index d0373a11bd..9ae6a223a9 100644 --- a/src/interfaces/odbc/connection.c +++ b/src/interfaces/odbc/connection.c @@ -110,6 +110,7 @@ PGAPI_Connect( /* get the values for the DSN from the registry */ getDSNinfo(ci, CONN_OVERWRITE); + logs_on_off(1, ci->drivers.debug, ci->drivers.commlog); /* initialize pg_version from connInfo.protocol */ CC_initialize_pg_version(conn); @@ -182,6 +183,7 @@ PGAPI_Disconnect( return SQL_ERROR; } + logs_on_off(-1, conn->connInfo.drivers.debug, conn->connInfo.drivers.commlog); mylog("%s: about to CC_cleanup\n", func); /* Close the connection and free statements */ @@ -249,8 +251,8 @@ CC_Constructor() rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */ memset(&rv->connInfo, 0, sizeof(ConnInfo)); - - rv->sock = SOCK_Constructor(); +memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals)); + rv->sock = SOCK_Constructor(rv); if (!rv->sock) return NULL; @@ -519,31 +521,31 @@ CC_connect(ConnectionClass *self, char do_password) { qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n", POSTGRESDRIVERVERSION, - globals.fetch_max, - globals.socket_buffersize, - globals.unknown_sizes, - globals.max_varchar_size, - globals.max_longvarchar_size); + ci->drivers.fetch_max, + ci->drivers.socket_buffersize, + ci->drivers.unknown_sizes, + ci->drivers.max_varchar_size, + ci->drivers.max_longvarchar_size); qlog(" disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n", - globals.disable_optimizer, - globals.ksqo, - globals.unique_index, - globals.use_declarefetch); + ci->drivers.disable_optimizer, + ci->drivers.ksqo, + ci->drivers.unique_index, + ci->drivers.use_declarefetch); qlog(" text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d\n", - globals.text_as_longvarchar, - globals.unknowns_as_longvarchar, - globals.bools_as_char); + ci->drivers.text_as_longvarchar, + ci->drivers.unknowns_as_longvarchar, + ci->drivers.bools_as_char); #ifdef MULTIBYTE - check_client_encoding(globals.conn_settings); + check_client_encoding(ci->drivers.conn_settings); qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n", - globals.extra_systable_prefixes, - globals.conn_settings, - check_client_encoding(globals.conn_settings)); + ci->drivers.extra_systable_prefixes, + ci->drivers.conn_settings, + check_client_encoding(ci->drivers.conn_settings)); #else qlog(" extra_systable_prefixes='%s', conn_settings='%s'\n", - globals.extra_systable_prefixes, - globals.conn_settings); + ci->drivers.extra_systable_prefixes, + ci->drivers.conn_settings); #endif if (self->status != CONN_NOT_CONNECTED) @@ -568,7 +570,7 @@ CC_connect(ConnectionClass *self, char do_password) */ if (!self->sock) { - self->sock = SOCK_Constructor(); + self->sock = SOCK_Constructor(self); if (!self->sock) { self->errornumber = CONNECTION_SERVER_NOT_REACHED; @@ -646,17 +648,21 @@ CC_connect(ConnectionClass *self, char do_password) */ if (!PROTOCOL_62(ci)) + { + BOOL before_64 = PG_VERSION_LT(self, 6.4), ReadyForQuery = FALSE; do { if (do_password) beresp = 'R'; else + { beresp = SOCK_get_char(sock); + mylog("auth got '%c'\n", beresp); + } switch (beresp) { case 'E': - mylog("auth got 'E'\n"); SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); self->errornumber = CONN_INVALID_AUTHENTICATION; @@ -673,7 +679,6 @@ CC_connect(ConnectionClass *self, char do_password) } else { - mylog("auth got 'R'\n"); areq = SOCK_get_int(sock, 4); if (areq == AUTH_REQ_MD5) @@ -734,13 +739,28 @@ CC_connect(ConnectionClass *self, char do_password) return 0; } break; + case 'K': /* Secret key (6.4 protocol) */ + (void) SOCK_get_int(sock, 4); /* pid */ + (void) SOCK_get_int(sock, 4); /* key */ + + break; + case 'Z': /* Backend is ready for new query (6.4) */ + ReadyForQuery = TRUE; + break; default: self->errormsg = "Unexpected protocol character during authentication"; self->errornumber = CONN_INVALID_AUTHENTICATION; return 0; } - } while (areq != AUTH_REQ_OK); + /* + * There were no ReadyForQuery responce + * before 6.4. + */ + if (before_64 && areq == AUTH_REQ_OK) + ReadyForQuery = TRUE; + } while (!ReadyForQuery); + } CC_clear_error(self); /* clear any password error */ @@ -917,13 +937,14 @@ CC_get_error(ConnectionClass *self, int *number, char **message) QResultClass * CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) { - QResultClass *result_in, - *res = NULL; + QResultClass *result_in = NULL, *res = NULL, *retres = NULL; char swallow; int id; SocketClass *sock = self->sock; - int maxlen; - BOOL msg_truncated; + int maxlen, empty_reqs; + BOOL msg_truncated, ReadyToReturn, + tuples_return = FALSE, query_completed = FALSE, + before_64 = PG_VERSION_LT(self, 6.4); /* ERROR_MSG_LENGTH is suffcient */ static char msgbuffer[ERROR_MSG_LENGTH + 1]; @@ -976,7 +997,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) mylog("send_query: done sending query\n"); - while (1) + ReadyToReturn = FALSE; + empty_reqs = 0; + if (strcmp(query, " ") == 0) + empty_reqs = 1; + while (!ReadyToReturn) { /* what type of message is coming now ? */ id = SOCK_get_char(sock); @@ -985,12 +1010,12 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) { self->errornumber = CONNECTION_NO_RESPONSE; self->errormsg = "No response from the backend"; - if (res) - QR_Destructor(res); mylog("send_query: 'id' - %s\n", self->errormsg); CC_set_no_trans(self); - return NULL; + ReadyToReturn = TRUE; + retres = NULL; + break; } mylog("send_query: got id = '%c'\n", id); @@ -1012,9 +1037,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) self->errormsg = "No response from backend while receiving a portal query command"; mylog("send_query: 'C' - %s\n", self->errormsg); CC_set_no_trans(self); - if (res) - QR_Destructor(res); - return NULL; + ReadyToReturn = TRUE; + retres = NULL; + break; } else { @@ -1031,7 +1056,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) if (QR_command_successful(res)) QR_set_status(res, PGRES_COMMAND_OK); QR_set_command(res, cmdbuffer); - + query_completed = TRUE; + if (!before_64) + break; /* * (Quotation from the original comments) since * backend may produce more than one result for some @@ -1041,8 +1068,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) */ - SOCK_put_string(sock, "Q "); - SOCK_flush_output(sock); + if (empty_reqs == 0) + { + SOCK_put_string(sock, "Q "); + SOCK_flush_output(sock); + empty_reqs++; + } + break; while (!clear) { @@ -1071,7 +1103,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) break; case 'E': msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); -mylog("ERROR from backend during clear: '%s'\n", msgbuffer); + mylog("ERROR from backend during clear: '%s'\n", msgbuffer); qlog("ERROR from backend during clear: '%s'\n", msgbuffer); /* @@ -1098,14 +1130,21 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer); } mylog("send_query: returning res = %u\n", res); - return res; + break; } - case 'K': /* Secret key (6.4 protocol) */ - (void) SOCK_get_int(sock, 4); /* pid */ - (void) SOCK_get_int(sock, 4); /* key */ - - break; case 'Z': /* Backend is ready for new query (6.4) */ + if (empty_reqs == 0) + { + ReadyToReturn = TRUE; + if (res && QR_get_aborted(res)) + retres = res; + else if (tuples_return) + retres = result_in; + else if (query_completed) + retres = res; + else + ReadyToReturn = FALSE; + } break; case 'N': /* NOTICE: */ msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); @@ -1126,22 +1165,26 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer); case 'I': /* The server sends an empty query */ /* There is a closing '\0' following the 'I', so we eat it */ swallow = SOCK_get_char(sock); + if (!res) + res = QR_Constructor(); if ((swallow != '\0') || SOCK_get_errcode(sock) != 0) { self->errornumber = CONNECTION_BACKEND_CRAZY; self->errormsg = "Unexpected protocol character from backend (send_query - I)"; - if (!res) - res = QR_Constructor(); QR_set_status(res, PGRES_FATAL_ERROR); - return res; + ReadyToReturn = TRUE; + retres = res; + break; } else { /* We return the empty query */ - if (!res) - res = QR_Constructor(); QR_set_status(res, PGRES_EMPTY_QUERY); - return res; + } + if (empty_reqs > 0) + { + if (--empty_reqs == 0) + query_completed = TRUE; } break; case 'E': @@ -1174,7 +1217,8 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer); while (msg_truncated) msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); - return res; /* instead of NULL. Zoltan */ + query_completed = TRUE; + break; case 'P': /* get the Portal name */ SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); @@ -1190,7 +1234,9 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer); { self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errormsg = "Could not create result info in send_query."; - return NULL; + ReadyToReturn = TRUE; + retres = NULL; + break; } if (qi) @@ -1200,43 +1246,87 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer); { self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errormsg = QR_get_message(result_in); - return NULL; + ReadyToReturn = TRUE; + retres = NULL; + break; } } else { /* next fetch, so reuse an existing result */ + /* + * called from QR_next_tuple + * and must return immediately. + */ + ReadyToReturn = TRUE; if (!QR_fetch_tuples(result_in, NULL, NULL)) { self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errormsg = QR_get_message(result_in); - return NULL; + retres = NULL; + break; } + retres = result_in; } - return result_in; + tuples_return = TRUE; + break; case 'D': /* Copy in command began successfully */ if (!res) res = QR_Constructor(); if (QR_command_successful(res)) QR_set_status(res, PGRES_COPY_IN); - return res; + ReadyToReturn = TRUE; + retres = res; + break; case 'B': /* Copy out command began successfully */ if (!res) res = QR_Constructor(); if (QR_command_successful(res)) QR_set_status(res, PGRES_COPY_OUT); - return res; + ReadyToReturn = TRUE; + retres = res; + break; default: self->errornumber = CONNECTION_BACKEND_CRAZY; self->errormsg = "Unexpected protocol character from backend (send_query)"; CC_set_no_trans(self); mylog("send_query: error - %s\n", self->errormsg); - if (res) - QR_Destructor(res); - return NULL; + ReadyToReturn = TRUE; + retres = NULL; + break; + } + /* + * There were no ReadyForQuery response before 6.4. + */ + if (before_64) + { + if (empty_reqs == 0 && (query_completed || tuples_return)) + break; } } + /* + * set notice message to result_in. + */ + if (result_in && res && retres == result_in) + { + if (QR_command_successful(result_in)) + QR_set_status(result_in, QR_get_status(res)); + QR_set_notice(result_in, QR_get_notice(res)); + } + /* + * Cleanup garbage results before returning. + */ + if (res && retres != res) + QR_Destructor(res); + if (result_in && retres != result_in) + { + if (qi && qi->result_in) + ; + else + QR_Destructor(result_in); + } + return retres; } @@ -1430,7 +1520,7 @@ CC_send_settings(ConnectionClass *self) mylog("%s: result %d, status %d from set DateStyle\n", func, result, status); /* Disable genetic optimizer based on global flag */ - if (globals.disable_optimizer) + if (ci->drivers.disable_optimizer) { result = PGAPI_ExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) @@ -1441,7 +1531,7 @@ CC_send_settings(ConnectionClass *self) } /* KSQO */ - if (globals.ksqo) + if (ci->drivers.ksqo) { result = PGAPI_ExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) @@ -1452,9 +1542,9 @@ CC_send_settings(ConnectionClass *self) } /* Global settings */ - if (globals.conn_settings[0] != '\0') + if (ci->drivers.conn_settings[0] != '\0') { - cs = strdup(globals.conn_settings); + cs = strdup(ci->drivers.conn_settings); ptr = strtok(cs, ";"); while (ptr) { diff --git a/src/interfaces/odbc/connection.h b/src/interfaces/odbc/connection.h index 4da6a7b7a8..902480896f 100644 --- a/src/interfaces/odbc/connection.h +++ b/src/interfaces/odbc/connection.h @@ -159,6 +159,7 @@ typedef struct char translation_dll[MEDIUM_REGISTRY_LEN]; char translation_option[SMALL_REGISTRY_LEN]; char focus_password; + GLOBAL_VALUES drivers; /* moved from driver's option */ } ConnInfo; /* Macro to determine is the connection using 6.2 protocol? */ diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c index 799b8c5b77..d0abad249e 100644 --- a/src/interfaces/odbc/convert.c +++ b/src/interfaces/odbc/convert.c @@ -58,7 +58,6 @@ typedef signed char SCHAR; #endif #endif -extern GLOBAL_VALUES globals; /* * How to map ODBC scalar functions {fn func(args)} to Postgres. @@ -132,10 +131,10 @@ char *mapFuncs[][2] = { {0, 0} }; -char *mapFunction(char *func); -unsigned int conv_from_octal(unsigned char *s); -unsigned int conv_from_hex(unsigned char *s); -char *conv_to_octal(unsigned char val); +static char *mapFunction(const char *func); +static unsigned int conv_from_octal(const unsigned char *s); +static unsigned int conv_from_hex(const unsigned char *s); +static char *conv_to_octal(unsigned char val); /*--------- * A Guide for date/time/timestamp conversions @@ -180,14 +179,16 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 struct tm *tim; int pcbValueOffset, rgbValueOffset; - char *rgbValueBindRow, - *ptr; + char *rgbValueBindRow; + const char *ptr; int bind_row = stmt->bind_row; int bind_size = stmt->options.bind_size; int result = COPY_OK; BOOL changed; static char *tempBuf= NULL; static unsigned int tempBuflen = 0; + const char *neutstr = value; + char midtemp[16]; if (!tempBuf) tempBuflen = 0; @@ -298,11 +299,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 This is bad ;) */ - - if (s[0] == 'T' || s[0] == 't' || s[0] == '1') - s[0] = '1'; + + strcpy(midtemp, value); + if (s[0] == 'f' || s[0] == 'F' || s[0] == 'n' || s[0] == 'N' || s[0] == '0') + midtemp[0] = '0'; else - s[0] = '0'; + midtemp[0] = '1'; + neutstr = midtemp; } break; @@ -312,7 +315,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 { int nval, i; - char *vp; + const char *vp; /* this is an array of eight integers */ short *short_array = (short *) ((char *) rgbValue + rgbValueOffset); @@ -423,7 +426,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 len = 1; if (cbValueMax > len) { - strcpy(rgbValueBindRow, value); + strcpy(rgbValueBindRow, neutstr); mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow); } break; @@ -607,13 +610,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 case SQL_C_BIT: len = 1; if (bind_size > 0) - *(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value); + *(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neutstr); else - *((UCHAR *) rgbValue + bind_row) = atoi(value); + *((UCHAR *) rgbValue + bind_row) = atoi(neutstr); /* - * mylog("SQL_C_BIT: val = %d, cb = %d, rgb=%d\n", - * atoi(value), cbValueMax, *((UCHAR *)rgbValue)); + * mylog("SQL_C_BIT: bind_row = %d val = %d, cb = %d, rgb=%d\n", + * bind_row, atoi(neutstr), cbValueMax, *((UCHAR *)rgbValue)); */ break; @@ -966,10 +969,17 @@ copy_statement_with_parameters(StatementClass *stmt) int lobj_fd, retval; BOOL check_select_into = FALSE; /* select into check */ + BOOL proc_no_param = TRUE; unsigned int declare_pos; + ConnectionClass *conn = SC_get_conn(stmt); + ConnInfo *ci = &(conn->connInfo); + BOOL prepare_dummy_cursor = FALSE; #ifdef DRIVER_CURSOR_IMPLEMENT BOOL ins_ctrl = FALSE; #endif /* DRIVER_CURSOR_IMPLEMENT */ +#ifdef PREPARE_TRIAL + prepare_dummy_cursor = stmt->pre_executing; +#endif /* PREPARE_TRIAL */ if (!old_statement) @@ -986,22 +996,6 @@ copy_statement_with_parameters(StatementClass *stmt) st.d = tim->tm_mday; st.y = tim->tm_year + 1900; - /* If the application hasn't set a cursor name, then generate one */ - if (stmt->cursor_name[0] == '\0') - sprintf(stmt->cursor_name, "SQL_CUR%p", stmt); - - oldstmtlen = strlen(old_statement); - CVT_INIT(oldstmtlen); - /* For selects, prepend a declare cursor to the statement */ - if (stmt->statement_type == STMT_TYPE_SELECT && globals.use_declarefetch) - { - sprintf(new_statement, "declare %s cursor for ", stmt->cursor_name); - npos = strlen(new_statement); - check_select_into = TRUE; - declare_pos = npos; - } - param_number = -1; - #ifdef DRIVER_CURSOR_IMPLEMENT if (stmt->statement_type != STMT_TYPE_SELECT) { @@ -1021,6 +1015,34 @@ copy_statement_with_parameters(StatementClass *stmt) else ins_ctrl = TRUE; } #endif /* DRIVER_CURSOR_IMPLEMENT */ + + /* If the application hasn't set a cursor name, then generate one */ + if (stmt->cursor_name[0] == '\0') + sprintf(stmt->cursor_name, "SQL_CUR%p", stmt); + oldstmtlen = strlen(old_statement); + CVT_INIT(oldstmtlen); + stmt->miscinfo = 0; + /* For selects, prepend a declare cursor to the statement */ + if (stmt->statement_type == STMT_TYPE_SELECT) + { + SC_set_pre_executable(stmt); + if (prepare_dummy_cursor || ci->drivers.use_declarefetch) + { + if (prepare_dummy_cursor) + { + if (!CC_is_in_trans(conn)) + strcpy(new_statement, "begin;"); + } + else if (ci->drivers.use_declarefetch) + SC_set_fetchcursor(stmt); + sprintf(new_statement, "%s declare %s cursor for ", + new_statement, stmt->cursor_name); + npos = strlen(new_statement); + check_select_into = TRUE; + declare_pos = npos; + } + } + param_number = -1; #ifdef MULTIBYTE multibyte_init(); #endif @@ -1087,7 +1109,9 @@ copy_statement_with_parameters(StatementClass *stmt) /* procedure calls */ if (stmt->statement_type == STMT_TYPE_PROCCALL) { + int lit_call_len = 4; while (isspace((unsigned char) old_statement[++opos])); + /* '=?' to accept return values exists ? */ if (old_statement[opos] == '?') { param_number++; @@ -1099,13 +1123,16 @@ copy_statement_with_parameters(StatementClass *stmt) } while (isspace((unsigned char) old_statement[++opos])); } - if (strnicmp(&old_statement[opos], "call", 4)) + if (strnicmp(&old_statement[opos], "call", lit_call_len) || + !isspace(old_statement[opos + lit_call_len])) { opos--; continue; } - opos += (4 - 1); - CVT_APPEND_STR("SELECT"); + opos += lit_call_len; + CVT_APPEND_STR("SELECT "); + if (strchr(&old_statement[opos], '(')) + proc_no_param = FALSE; continue; } *end = '\0'; @@ -1128,7 +1155,11 @@ copy_statement_with_parameters(StatementClass *stmt) } /* End of a procedure call */ else if (oldchar == '}' && stmt->statement_type == STMT_TYPE_PROCCALL) + { + if (proc_no_param) + CVT_APPEND_STR("()"); continue; + } /* * Can you have parameter markers inside of quotes? I dont think @@ -1151,6 +1182,8 @@ copy_statement_with_parameters(StatementClass *stmt) into_table_from(&old_statement[opos])) { stmt->statement_type = STMT_TYPE_CREATE; + SC_no_pre_executable(stmt); + SC_no_fetchcursor(stmt); stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; memmove(new_statement, new_statement + declare_pos, npos - declare_pos); npos -= declare_pos; @@ -1446,12 +1479,12 @@ copy_statement_with_parameters(StatementClass *stmt) else { /* begin transaction if needed */ - if (!CC_is_in_trans(stmt->hdbc)) + if (!CC_is_in_trans(conn)) { QResultClass *res; char ok; - res = CC_send_query(stmt->hdbc, "BEGIN", NULL); + res = CC_send_query(conn, "BEGIN", NULL); if (!res) { stmt->errormsg = "Could not begin (in-line) a transaction"; @@ -1469,11 +1502,11 @@ copy_statement_with_parameters(StatementClass *stmt) return SQL_ERROR; } - CC_set_in_trans(stmt->hdbc); + CC_set_in_trans(conn); } /* store the oid */ - lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); + lobj_oid = lo_creat(conn, INV_READ | INV_WRITE); if (lobj_oid == 0) { stmt->errornumber = STMT_EXEC_ERROR; @@ -1483,7 +1516,7 @@ copy_statement_with_parameters(StatementClass *stmt) } /* store the fd */ - lobj_fd = lo_open(stmt->hdbc, lobj_oid, INV_WRITE); + lobj_fd = lo_open(conn, lobj_oid, INV_WRITE); if (lobj_fd < 0) { stmt->errornumber = STMT_EXEC_ERROR; @@ -1492,17 +1525,17 @@ copy_statement_with_parameters(StatementClass *stmt) return SQL_ERROR; } - retval = lo_write(stmt->hdbc, lobj_fd, buffer, used); + retval = lo_write(conn, lobj_fd, buffer, used); - lo_close(stmt->hdbc, lobj_fd); + lo_close(conn, lobj_fd); /* commit transaction if needed */ - if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) + if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn)) { QResultClass *res; char ok; - res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + res = CC_send_query(conn, "COMMIT", NULL); if (!res) { stmt->errormsg = "Could not commit (in-line) a transaction"; @@ -1520,7 +1553,7 @@ copy_statement_with_parameters(StatementClass *stmt) return SQL_ERROR; } - CC_set_no_trans(stmt->hdbc); + CC_set_no_trans(conn); } } @@ -1589,11 +1622,11 @@ copy_statement_with_parameters(StatementClass *stmt) /* make sure new_statement is always null-terminated */ CVT_TERMINATE - if (stmt->hdbc->DriverToDataSource != NULL) + if (conn->DriverToDataSource != NULL) { int length = strlen(new_statement); - stmt->hdbc->DriverToDataSource(stmt->hdbc->translation_option, + conn->DriverToDataSource(conn->translation_option, SQL_CHAR, new_statement, length, new_statement, length, NULL, @@ -1604,12 +1637,25 @@ copy_statement_with_parameters(StatementClass *stmt) if (ins_ctrl) stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; #endif /* DRIVER_CURSOR_IMPLEMENT */ +#ifdef PREPARE_TRIAL + if (prepare_dummy_cursor && SC_is_pre_executable(stmt)) + { + char fetchstr[128]; + sprintf(fetchstr, ";fetch backward in %s;close %s;", + stmt->cursor_name, stmt->cursor_name); + if (!CC_is_in_trans(conn)) + strcat(fetchstr, "commit;"); + CVT_APPEND_STR(fetchstr); + stmt->inaccurate_result = TRUE; + } +#endif /* PREPARE_TRIAL */ + return SQL_SUCCESS; } char * -mapFunction(char *func) +mapFunction(const char *func) { int i; @@ -1850,7 +1896,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed) * Plus, escape any special characters. */ int -convert_special_chars(char *si, char *dst, int used) +convert_special_chars(const char *si, char *dst, int used) { size_t i = 0, out = 0, @@ -1904,7 +1950,7 @@ convert_special_chars(char *si, char *dst, int used) /* !!! Need to implement this function !!! */ int -convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax) +convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax) { mylog("convert_pgbinary_to_char: value = '%s'\n", value); @@ -1914,7 +1960,7 @@ convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax) unsigned int -conv_from_octal(unsigned char *s) +conv_from_octal(const unsigned char *s) { int i, y = 0; @@ -1928,7 +1974,7 @@ conv_from_octal(unsigned char *s) unsigned int -conv_from_hex(unsigned char *s) +conv_from_hex(const unsigned char *s) { int i, y = 0, @@ -1952,7 +1998,7 @@ conv_from_hex(unsigned char *s) /* convert octal escapes to bytes */ int -convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax) +convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax) { size_t i, ilen = strlen(value); int o = 0; @@ -2007,7 +2053,7 @@ conv_to_octal(unsigned char val) /* convert non-ascii bytes to octal escape sequences */ int -convert_to_pgbinary(unsigned char *in, char *out, int len) +convert_to_pgbinary(const unsigned char *in, char *out, int len) { int i, o = 0; @@ -2031,7 +2077,7 @@ convert_to_pgbinary(unsigned char *in, char *out, int len) void -encode(char *in, char *out) +encode(const char *in, char *out) { unsigned int i, ilen = strlen(in), o = 0; @@ -2058,7 +2104,7 @@ encode(char *in, char *out) void -decode(char *in, char *out) +decode(const char *in, char *out) { unsigned int i, ilen = strlen(in), o = 0; @@ -2104,7 +2150,8 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, result, left = -1; BindInfoClass *bindInfo = NULL; - + ConnectionClass *conn = SC_get_conn(stmt); + ConnInfo *ci = &(conn->connInfo); /* If using SQLGetData, then current_col will be set */ if (stmt->current_col >= 0) @@ -2121,12 +2168,12 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, if (!bindInfo || bindInfo->data_left == -1) { /* begin transaction if needed */ - if (!CC_is_in_trans(stmt->hdbc)) + if (!CC_is_in_trans(conn)) { QResultClass *res; char ok; - res = CC_send_query(stmt->hdbc, "BEGIN", NULL); + res = CC_send_query(conn, "BEGIN", NULL); if (!res) { stmt->errormsg = "Could not begin (in-line) a transaction"; @@ -2142,11 +2189,11 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, return COPY_GENERAL_ERROR; } - CC_set_in_trans(stmt->hdbc); + CC_set_in_trans(conn); } oid = atoi(value); - stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ); + stmt->lobj_fd = lo_open(conn, oid, INV_READ); if (stmt->lobj_fd < 0) { stmt->errornumber = STMT_EXEC_ERROR; @@ -2155,15 +2202,15 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, } /* Get the size */ - retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END); + retval = lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_END); if (retval >= 0) { - left = lo_tell(stmt->hdbc, stmt->lobj_fd); + left = lo_tell(conn, stmt->lobj_fd); if (bindInfo) bindInfo->data_left = left; /* return to beginning */ - lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_SET); + lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET); } } @@ -2177,18 +2224,18 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, return COPY_GENERAL_ERROR; } - retval = lo_read(stmt->hdbc, stmt->lobj_fd, (char *) rgbValue, cbValueMax); + retval = lo_read(conn, stmt->lobj_fd, (char *) rgbValue, cbValueMax); if (retval < 0) { - lo_close(stmt->hdbc, stmt->lobj_fd); + lo_close(conn, stmt->lobj_fd); /* commit transaction if needed */ - if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) + if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn)) { QResultClass *res; char ok; - res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + res = CC_send_query(conn, "COMMIT", NULL); if (!res) { stmt->errormsg = "Could not commit (in-line) a transaction"; @@ -2204,7 +2251,7 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, return COPY_GENERAL_ERROR; } - CC_set_no_trans(stmt->hdbc); + CC_set_no_trans(conn); } stmt->lobj_fd = -1; @@ -2227,15 +2274,15 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, if (!bindInfo || bindInfo->data_left == 0) { - lo_close(stmt->hdbc, stmt->lobj_fd); + lo_close(conn, stmt->lobj_fd); /* commit transaction if needed */ - if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) + if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn)) { QResultClass *res; char ok; - res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + res = CC_send_query(conn, "COMMIT", NULL); if (!res) { stmt->errormsg = "Could not commit (in-line) a transaction"; @@ -2251,7 +2298,7 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, return COPY_GENERAL_ERROR; } - CC_set_no_trans(stmt->hdbc); + CC_set_no_trans(conn); } stmt->lobj_fd = -1; /* prevent further reading */ diff --git a/src/interfaces/odbc/convert.h b/src/interfaces/odbc/convert.h index 8a7d15e5d4..aaf1518344 100644 --- a/src/interfaces/odbc/convert.h +++ b/src/interfaces/odbc/convert.h @@ -29,8 +29,8 @@ typedef struct int ss; } SIMPLE_TIME; -int copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col); -int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType, +int copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, const void *value, int col); +int copy_and_convert_field(StatementClass *stmt, Int4 field_type, const void *value, Int2 fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue); int copy_statement_with_parameters(StatementClass *stmt); @@ -38,14 +38,14 @@ char *convert_escape(char *value); char *convert_money(char *s); char parse_datetime(char *buf, SIMPLE_TIME *st); int convert_linefeeds(const char *s, char *dst, size_t max, BOOL *changed); -int convert_special_chars(char *si, char *dst, int used); - -int convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax); -int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax); -int convert_to_pgbinary(unsigned char *in, char *out, int len); -void encode(char *in, char *out); -void decode(char *in, char *out); -int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, +int convert_special_chars(const char *si, char *dst, int used); + +int convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax); +int convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax); +int convert_to_pgbinary(const unsigned char *in, char *out, int len); +void encode(const char *in, char *out); +void decode(const char *in, char *out); +int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue); #endif diff --git a/src/interfaces/odbc/dlg_specific.c b/src/interfaces/odbc/dlg_specific.c index d28fcf966c..facf77dd09 100644 --- a/src/interfaces/odbc/dlg_specific.c +++ b/src/interfaces/odbc/dlg_specific.c @@ -49,11 +49,15 @@ #endif extern GLOBAL_VALUES globals; - +#ifdef WIN32 +static int driver_optionsDraw(HWND, const ConnInfo *, int src, BOOL enable); +static int driver_options_update(HWND hdlg, ConnInfo *ci, BOOL); +#endif +static void updateCommons(const ConnInfo *ci); #ifdef WIN32 void -SetDlgStuff(HWND hdlg, ConnInfo *ci) +SetDlgStuff(HWND hdlg, const ConnInfo *ci) { /* @@ -87,145 +91,204 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci) } -int CALLBACK -driver_optionsProc(HWND hdlg, - WORD wMsg, - WPARAM wParam, - LPARAM lParam) +static int +driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable) { - switch (wMsg) + const GLOBAL_VALUES *comval; + static BOOL defset = FALSE; + static GLOBAL_VALUES defval; + + switch (src) { - case WM_INITDIALOG: - - CheckDlgButton(hdlg, DRV_COMMLOG, globals.commlog); - CheckDlgButton(hdlg, DRV_OPTIMIZER, globals.disable_optimizer); - CheckDlgButton(hdlg, DRV_KSQO, globals.ksqo); - CheckDlgButton(hdlg, DRV_UNIQUEINDEX, globals.unique_index); - CheckDlgButton(hdlg, DRV_READONLY, globals.onlyread); - CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, globals.use_declarefetch); - - /* Unknown (Default) Data Type sizes */ - switch (globals.unknown_sizes) + case 0: /* driver common */ + comval = &globals; + break; + case 1: /* dsn specific */ + comval = &(ci->drivers); + break; + case 2: /* default */ + if (!defset) { - case UNKNOWNS_AS_DONTKNOW: - CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1); - break; - case UNKNOWNS_AS_LONGEST: - CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1); - break; - case UNKNOWNS_AS_MAX: - default: - CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1); - break; + defval.commlog = DEFAULT_COMMLOG; + defval.disable_optimizer = DEFAULT_OPTIMIZER; + defval.ksqo = DEFAULT_KSQO; + defval.unique_index = DEFAULT_UNIQUEINDEX; + defval.onlyread = DEFAULT_READONLY; + defval.use_declarefetch = DEFAULT_USEDECLAREFETCH; + + defval.parse = DEFAULT_PARSE; + defval.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; + defval.debug = DEFAULT_DEBUG; + + /* Unknown Sizes */ + defval.unknown_sizes = DEFAULT_UNKNOWNSIZES; + defval.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR; + defval.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR; + defval.bools_as_char = DEFAULT_BOOLSASCHAR; } + defset = TRUE; + comval = &defval; + break; + } - CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, globals.text_as_longvarchar); - CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, globals.unknowns_as_longvarchar); - CheckDlgButton(hdlg, DRV_BOOLS_CHAR, globals.bools_as_char); + CheckDlgButton(hdlg, DRV_COMMLOG, comval->commlog); + CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer); + CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo); + CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index); + EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable); + CheckDlgButton(hdlg, DRV_READONLY, comval->onlyread); + EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable); + CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch); + + /* Unknown Sizes clear */ + CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0); + CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0); + CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0); + /* Unknown (Default) Data Type sizes */ + switch (comval->unknown_sizes) + { + case UNKNOWNS_AS_DONTKNOW: + CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1); + break; + case UNKNOWNS_AS_LONGEST: + CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1); + break; + case UNKNOWNS_AS_MAX: + default: + CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1); + break; + } - CheckDlgButton(hdlg, DRV_PARSE, globals.parse); + CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, comval->text_as_longvarchar); + CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, comval->unknowns_as_longvarchar); + CheckDlgButton(hdlg, DRV_BOOLS_CHAR, comval->bools_as_char); + CheckDlgButton(hdlg, DRV_PARSE, comval->parse); + CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, comval->cancel_as_freestmt); + CheckDlgButton(hdlg, DRV_DEBUG, comval->debug); + SetDlgItemInt(hdlg, DRV_CACHE_SIZE, comval->fetch_max, FALSE); + SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, comval->max_varchar_size, FALSE); + SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, comval->max_longvarchar_size, TRUE); + SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes); + + /* Driver Connection Settings */ + SetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings); + EnableWindow(GetDlgItem(hdlg, DRV_CONNSETTINGS), enable); + return 0; +} +static int +driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile) +{ + GLOBAL_VALUES *comval; + + if (ci) + comval = &(ci->drivers); + else + comval = &globals; + comval->commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG); + comval->disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER); + comval->ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO); + if (!ci) + { + comval->unique_index = IsDlgButtonChecked(hdlg, DRV_UNIQUEINDEX); + comval->onlyread = IsDlgButtonChecked(hdlg, DRV_READONLY); + } + comval->use_declarefetch = IsDlgButtonChecked(hdlg, DRV_USEDECLAREFETCH); + + /* Unknown (Default) Data Type sizes */ + if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_MAX)) + comval->unknown_sizes = UNKNOWNS_AS_MAX; + else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_DONTKNOW)) + comval->unknown_sizes = UNKNOWNS_AS_DONTKNOW; + else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_LONGEST)) + comval->unknown_sizes = UNKNOWNS_AS_LONGEST; + else + comval->unknown_sizes = UNKNOWNS_AS_MAX; + + comval->text_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_TEXT_LONGVARCHAR); + comval->unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR); + comval->bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR); + + comval->parse = IsDlgButtonChecked(hdlg, DRV_PARSE); + + comval->cancel_as_freestmt = IsDlgButtonChecked(hdlg, DRV_CANCELASFREESTMT); + comval->debug = IsDlgButtonChecked(hdlg, DRV_DEBUG); + + comval->fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE); + comval->max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE); + comval->max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for + * SQL_NO_TOTAL */ - CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, globals.cancel_as_freestmt); + GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, sizeof(comval->extra_systable_prefixes)); - SetDlgItemInt(hdlg, DRV_CACHE_SIZE, globals.fetch_max, FALSE); - SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, globals.max_varchar_size, FALSE); - SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, globals.max_longvarchar_size, TRUE); + /* Driver Connection Settings */ + if (!ci) + GetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings, sizeof(comval->conn_settings)); - SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes); + if (updateProfile) + updateCommons(ci); - /* Driver Connection Settings */ - SetDlgItemText(hdlg, DRV_CONNSETTINGS, globals.conn_settings); + /* fall through */ + return 0; +} +int CALLBACK +driver_optionsProc(HWND hdlg, + WORD wMsg, + WPARAM wParam, + LPARAM lParam) +{ + ConnInfo *ci; + switch (wMsg) + { + case WM_INITDIALOG: + SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK etc */ + ci = (ConnInfo *) lParam; + if (ci && ci->dsn && ci->dsn[0]) + { + driver_optionsDraw(hdlg, NULL, 0, TRUE); + } + else + { + CheckDlgButton(hdlg, DRV_OR_DSN, 1); + ShowWindow(GetDlgItem(hdlg, DRV_OR_DSN), SW_HIDE); + driver_optionsDraw(hdlg, ci, 1, FALSE); + } break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: - globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG); - globals.disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER); - globals.ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO); - globals.unique_index = IsDlgButtonChecked(hdlg, DRV_UNIQUEINDEX); - globals.onlyread = IsDlgButtonChecked(hdlg, DRV_READONLY); - globals.use_declarefetch = IsDlgButtonChecked(hdlg, DRV_USEDECLAREFETCH); - - /* Unknown (Default) Data Type sizes */ - if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_MAX)) - globals.unknown_sizes = UNKNOWNS_AS_MAX; - else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_DONTKNOW)) - globals.unknown_sizes = UNKNOWNS_AS_DONTKNOW; - else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_LONGEST)) - globals.unknown_sizes = UNKNOWNS_AS_LONGEST; - else - globals.unknown_sizes = UNKNOWNS_AS_MAX; - - globals.text_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_TEXT_LONGVARCHAR); - globals.unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR); - globals.bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR); - - globals.parse = IsDlgButtonChecked(hdlg, DRV_PARSE); - - globals.cancel_as_freestmt = IsDlgButtonChecked(hdlg, DRV_CANCELASFREESTMT); - - globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE); - globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE); - globals.max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for - * SQL_NO_TOTAL */ - - GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, sizeof(globals.extra_systable_prefixes)); - - /* Driver Connection Settings */ - GetDlgItemText(hdlg, DRV_CONNSETTINGS, globals.conn_settings, sizeof(globals.conn_settings)); - - updateGlobals(); - - /* fall through */ + ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); + driver_options_update(hdlg, IsDlgButtonChecked(hdlg, DRV_OR_DSN) ? ci : NULL, + ci && ci->dsn && ci->dsn[0]); case IDCANCEL: EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); return TRUE; case IDDEFAULTS: - CheckDlgButton(hdlg, DRV_COMMLOG, DEFAULT_COMMLOG); - CheckDlgButton(hdlg, DRV_OPTIMIZER, DEFAULT_OPTIMIZER); - CheckDlgButton(hdlg, DRV_KSQO, DEFAULT_KSQO); - CheckDlgButton(hdlg, DRV_UNIQUEINDEX, DEFAULT_UNIQUEINDEX); - CheckDlgButton(hdlg, DRV_READONLY, DEFAULT_READONLY); - CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, DEFAULT_USEDECLAREFETCH); - - CheckDlgButton(hdlg, DRV_PARSE, DEFAULT_PARSE); - CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, DEFAULT_CANCELASFREESTMT); - - /* Unknown Sizes */ - CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0); - CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0); - CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0); - switch (DEFAULT_UNKNOWNSIZES) + if (IsDlgButtonChecked(hdlg, DRV_OR_DSN)) { - case UNKNOWNS_AS_DONTKNOW: - CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1); - break; - case UNKNOWNS_AS_LONGEST: - CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1); - break; - case UNKNOWNS_AS_MAX: - CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1); - break; + ConnInfo *ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); + driver_optionsDraw(hdlg, ci, 0, FALSE); } + else + driver_optionsDraw(hdlg, NULL, 2, TRUE); + break; - CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, DEFAULT_TEXTASLONGVARCHAR); - CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, DEFAULT_UNKNOWNSASLONGVARCHAR); - CheckDlgButton(hdlg, DRV_BOOLS_CHAR, DEFAULT_BOOLSASCHAR); - - SetDlgItemInt(hdlg, DRV_CACHE_SIZE, FETCH_MAX, FALSE); - SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, MAX_VARCHAR_SIZE, FALSE); - SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, TEXT_FIELD_SIZE, TRUE); - - SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, DEFAULT_EXTRASYSTABLEPREFIXES); - - /* Driver Connection Settings */ - SetDlgItemText(hdlg, DRV_CONNSETTINGS, ""); - + case DRV_OR_DSN: + if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED) + { + mylog("DRV_OR_DSN clicked\n"); + if (IsDlgButtonChecked(hdlg, DRV_OR_DSN)) + { + ConnInfo *ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); + driver_optionsDraw(hdlg, ci, ci ? 1 : 0, ci == NULL); + } + else + driver_optionsDraw(hdlg, NULL, 0, TRUE); + } break; } } @@ -331,10 +394,11 @@ ds_optionsProc(HWND hdlg, void -makeConnectString(char *connect_string, ConnInfo *ci) +makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len) { char got_dsn = (ci->dsn[0] != '\0'); char encoded_conn_settings[LARGE_REGISTRY_LEN]; + UWORD hlen; /* fundamental info */ sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s", @@ -349,20 +413,64 @@ makeConnectString(char *connect_string, ConnInfo *ci) encode(ci->conn_settings, encoded_conn_settings); /* extra info */ - sprintf(&connect_string[strlen(connect_string)], - ";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s", + hlen = strlen(connect_string), + sprintf(&connect_string[hlen], + ";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s;FETCH=%d;SOCKET=%d;UNKNOWNSIZES=%d;MAXVARCHARSIZE=%d;MAXLONGVARCHARSIZE=%d;DEBUG=%d;COMMLOG=%d;OPTIMIZER=%d;KSQO=%d;USEDECLAREFETCH=%d;TEXTASLONGVARCHAR=%d;UNKNOWNSASLONGVARCHAR=%d;BOOLSASCHAR=%d;PARSE=%d;CANCELASFREESTMT=%d;EXTRASYSTABLEPREFIXES=%s", + ci->onlyread, + ci->protocol, + ci->fake_oid_index, + ci->show_oid_column, + ci->row_versioning, + ci->show_system_tables, + encoded_conn_settings, + ci->drivers.fetch_max, + ci->drivers.socket_buffersize, + ci->drivers.unknown_sizes, + ci->drivers.max_varchar_size, + ci->drivers.max_longvarchar_size, + ci->drivers.debug, + ci->drivers.commlog, + ci->drivers.disable_optimizer, + ci->drivers.ksqo, + ci->drivers.use_declarefetch, + ci->drivers.text_as_longvarchar, + ci->drivers.unknowns_as_longvarchar, + ci->drivers.bools_as_char, + ci->drivers.parse, + ci->drivers.cancel_as_freestmt, + ci->drivers.extra_systable_prefixes); + /* Abbrebiation is needed ? */ + if (strlen(connect_string) >= len) + sprintf(&connect_string[hlen], + ";A0=%s;A1=%s;A2=%s;A3=%s;A4=%s;A5=%s;A6=%s;A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s", ci->onlyread, ci->protocol, ci->fake_oid_index, ci->show_oid_column, ci->row_versioning, ci->show_system_tables, - encoded_conn_settings); + encoded_conn_settings, + ci->drivers.fetch_max, + ci->drivers.socket_buffersize, + ci->drivers.unknown_sizes, + ci->drivers.max_varchar_size, + ci->drivers.max_longvarchar_size, + ci->drivers.debug, + ci->drivers.commlog, + ci->drivers.disable_optimizer, + ci->drivers.ksqo, + ci->drivers.use_declarefetch, + ci->drivers.text_as_longvarchar, + ci->drivers.unknowns_as_longvarchar, + ci->drivers.bools_as_char, + ci->drivers.parse, + ci->drivers.cancel_as_freestmt, + ci->drivers.extra_systable_prefixes); } void -copyAttributes(ConnInfo *ci, char *attribute, char *value) +copyAttributes(ConnInfo *ci, const char *attribute, const char *value) { if (stricmp(attribute, "DSN") == 0) strcpy(ci->dsn, value); @@ -385,25 +493,25 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value) else if (stricmp(attribute, INI_PORT) == 0) strcpy(ci->port, value); - else if (stricmp(attribute, INI_READONLY) == 0) + else if (stricmp(attribute, INI_READONLY) == 0 || stricmp(attribute, "A0") == 0) strcpy(ci->onlyread, value); - else if (stricmp(attribute, INI_PROTOCOL) == 0) + else if (stricmp(attribute, INI_PROTOCOL) == 0 || stricmp(attribute, "A1") == 0) strcpy(ci->protocol, value); - else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0) + else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0 || stricmp(attribute, "A3") == 0) strcpy(ci->show_oid_column, value); - else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0) + else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0 || stricmp(attribute, "A2") == 0) strcpy(ci->fake_oid_index, value); - else if (stricmp(attribute, INI_ROWVERSIONING) == 0) + else if (stricmp(attribute, INI_ROWVERSIONING) == 0 || stricmp(attribute, "A4") == 0) strcpy(ci->row_versioning, value); - else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0) + else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0 || stricmp(attribute, "A5") == 0) strcpy(ci->show_system_tables, value); - else if (stricmp(attribute, INI_CONNSETTINGS) == 0) + else if (stricmp(attribute, INI_CONNSETTINGS) == 0 || stricmp(attribute, "A6") == 0) { decode(value, ci->conn_settings); /* strcpy(ci->conn_settings, value); */ @@ -412,6 +520,66 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value) mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings); } +void +copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value) +{ + if (stricmp(attribute, INI_FETCH) == 0 || stricmp(attribute, "A7") == 0) + ci->drivers.fetch_max = atoi(value); + else if (stricmp(attribute, INI_SOCKET) == 0 || stricmp(attribute, "A8") == 0) + ci->drivers.socket_buffersize = atoi(value); + else if (stricmp(attribute, INI_DEBUG) == 0 || stricmp(attribute, "B2") == 0) + ci->drivers.debug = atoi(value); + else if (stricmp(attribute, INI_COMMLOG) == 0 || stricmp(attribute, "B3") == 0) + ci->drivers.commlog = atoi(value); + else if (stricmp(attribute, INI_OPTIMIZER) == 0 || stricmp(attribute, "B4") == 0) + ci->drivers.disable_optimizer = atoi(value); + else if (stricmp(attribute, INI_KSQO) == 0 || stricmp(attribute, "B5") == 0) + ci->drivers.ksqo = atoi(value); + /* + else if (stricmp(attribute, INI_UNIQUEINDEX) == 0 || stricmp(attribute, "UIX") == 0) + ci->drivers.unique_index = atoi(value); + */ + else if (stricmp(attribute, INI_UNKNOWNSIZES) == 0 || stricmp(attribute, "A9") == 0) + ci->drivers.unknown_sizes = atoi(value); + else if (stricmp(attribute, INI_LIE) == 0) + ci->drivers.lie = atoi(value); + else if (stricmp(attribute, INI_PARSE) == 0 || stricmp(attribute, "C0") == 0) + ci->drivers.parse = atoi(value); + else if (stricmp(attribute, INI_CANCELASFREESTMT) == 0 || stricmp(attribute, "C1") == 0) + ci->drivers.cancel_as_freestmt = atoi(value); + else if (stricmp(attribute, INI_USEDECLAREFETCH) == 0 || stricmp(attribute, "B6") == 0) + ci->drivers.use_declarefetch = atoi(value); + else if (stricmp(attribute, INI_MAXVARCHARSIZE) == 0 || stricmp(attribute, "B0") == 0) + ci->drivers.max_varchar_size = atoi(value); + else if (stricmp(attribute, INI_MAXLONGVARCHARSIZE) == 0 || stricmp(attribute, "B1") == 0) + ci->drivers.max_longvarchar_size = atoi(value); + else if (stricmp(attribute, INI_TEXTASLONGVARCHAR) == 0 || stricmp(attribute, "B7") == 0) + ci->drivers.text_as_longvarchar = atoi(value); + else if (stricmp(attribute, INI_UNKNOWNSASLONGVARCHAR) == 0 || stricmp(attribute, "B8") == 0) + ci->drivers.unknowns_as_longvarchar = atoi(value); + else if (stricmp(attribute, INI_BOOLSASCHAR) == 0 || stricmp(attribute, "B9") == 0) + ci->drivers.bools_as_char = atoi(value); + else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, "C2") == 0) + strcpy(ci->drivers.extra_systable_prefixes, value); + mylog("CopyCommonAttributes: A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s", + ci->drivers.fetch_max, + ci->drivers.socket_buffersize, + ci->drivers.unknown_sizes, + ci->drivers.max_varchar_size, + ci->drivers.max_longvarchar_size, + ci->drivers.debug, + ci->drivers.commlog, + ci->drivers.disable_optimizer, + ci->drivers.ksqo, + ci->drivers.use_declarefetch, + ci->drivers.text_as_longvarchar, + ci->drivers.unknowns_as_longvarchar, + ci->drivers.bools_as_char, + ci->drivers.parse, + ci->drivers.cancel_as_freestmt, + ci->drivers.extra_systable_prefixes); +} + void getDSNdefaults(ConnInfo *ci) @@ -449,6 +617,7 @@ getDSNinfo(ConnInfo *ci, char overwrite) * If a driver keyword was present, then dont use a DSN and return. * If DSN is null and no driver, then use the default datasource. */ + memcpy(&ci->drivers, &globals, sizeof(globals)); if (DSN[0] == '\0') { if (ci->driver[0] != '\0') @@ -512,7 +681,8 @@ getDSNinfo(ConnInfo *ci, char overwrite) SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI); /* Allow override of odbcinst.ini parameters here */ - getGlobalDefaults(DSN, ODBC_INI, TRUE); + /* getGlobalDefaults(DSN, ODBC_INI, TRUE); */ + getCommonDefaults(DSN, ODBC_INI, ci); qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n", DSN, @@ -546,9 +716,9 @@ getDSNinfo(ConnInfo *ci, char overwrite) /* This is for datasource based options only */ void -writeDSNinfo(ConnInfo *ci) +writeDSNinfo(const ConnInfo *ci) { - char *DSN = ci->dsn; + const char *DSN = ci->dsn; char encoded_conn_settings[LARGE_REGISTRY_LEN]; encode(ci->conn_settings, encoded_conn_settings); @@ -625,152 +795,159 @@ writeDSNinfo(ConnInfo *ci) * the registry and gets any driver defaults. */ void -getGlobalDefaults(char *section, char *filename, char override) +getCommonDefaults(const char *section, const char *filename, ConnInfo *ci) { char temp[256]; + GLOBAL_VALUES *comval; + if (ci) + comval = &(ci->drivers); + else + comval = &globals; /* Fetch Count is stored in driver section */ SQLGetPrivateProfileString(section, INI_FETCH, "", temp, sizeof(temp), filename); if (temp[0]) { - globals.fetch_max = atoi(temp); + comval->fetch_max = atoi(temp); /* sanity check if using cursors */ - if (globals.fetch_max <= 0) - globals.fetch_max = FETCH_MAX; + if (comval->fetch_max <= 0) + comval->fetch_max = FETCH_MAX; } - else if (!override) - globals.fetch_max = FETCH_MAX; + else if (!ci) + comval->fetch_max = FETCH_MAX; /* Socket Buffersize is stored in driver section */ SQLGetPrivateProfileString(section, INI_SOCKET, "", temp, sizeof(temp), filename); if (temp[0]) - globals.socket_buffersize = atoi(temp); - else if (!override) - globals.socket_buffersize = SOCK_BUFFER_SIZE; + comval->socket_buffersize = atoi(temp); + else if (!ci) + comval->socket_buffersize = SOCK_BUFFER_SIZE; /* Debug is stored in the driver section */ SQLGetPrivateProfileString(section, INI_DEBUG, "", temp, sizeof(temp), filename); if (temp[0]) - globals.debug = atoi(temp); - else if (!override) - globals.debug = DEFAULT_DEBUG; + comval->debug = atoi(temp); + else if (!ci) + comval->debug = DEFAULT_DEBUG; /* CommLog is stored in the driver section */ SQLGetPrivateProfileString(section, INI_COMMLOG, "", temp, sizeof(temp), filename); if (temp[0]) - globals.commlog = atoi(temp); - else if (!override) - globals.commlog = DEFAULT_COMMLOG; + comval->commlog = atoi(temp); + else if (!ci) + comval->commlog = DEFAULT_COMMLOG; + if (!ci) + logs_on_off(0, 0, 0); /* Optimizer is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_OPTIMIZER, "", temp, sizeof(temp), filename); if (temp[0]) - globals.disable_optimizer = atoi(temp); - else if (!override) - globals.disable_optimizer = DEFAULT_OPTIMIZER; + comval->disable_optimizer = atoi(temp); + else if (!ci) + comval->disable_optimizer = DEFAULT_OPTIMIZER; /* KSQO is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_KSQO, "", temp, sizeof(temp), filename); if (temp[0]) - globals.ksqo = atoi(temp); - else if (!override) - globals.ksqo = DEFAULT_KSQO; + comval->ksqo = atoi(temp); + else if (!ci) + comval->ksqo = DEFAULT_KSQO; /* Recognize Unique Index is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, "", temp, sizeof(temp), filename); if (temp[0]) - globals.unique_index = atoi(temp); - else if (!override) - globals.unique_index = DEFAULT_UNIQUEINDEX; + comval->unique_index = atoi(temp); + else if (!ci) + comval->unique_index = DEFAULT_UNIQUEINDEX; /* Unknown Sizes is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, "", temp, sizeof(temp), filename); if (temp[0]) - globals.unknown_sizes = atoi(temp); - else if (!override) - globals.unknown_sizes = DEFAULT_UNKNOWNSIZES; + comval->unknown_sizes = atoi(temp); + else if (!ci) + comval->unknown_sizes = DEFAULT_UNKNOWNSIZES; /* Lie about supported functions? */ SQLGetPrivateProfileString(section, INI_LIE, "", temp, sizeof(temp), filename); if (temp[0]) - globals.lie = atoi(temp); - else if (!override) - globals.lie = DEFAULT_LIE; + comval->lie = atoi(temp); + else if (!ci) + comval->lie = DEFAULT_LIE; /* Parse statements */ SQLGetPrivateProfileString(section, INI_PARSE, "", temp, sizeof(temp), filename); if (temp[0]) - globals.parse = atoi(temp); - else if (!override) - globals.parse = DEFAULT_PARSE; + comval->parse = atoi(temp); + else if (!ci) + comval->parse = DEFAULT_PARSE; /* SQLCancel calls SQLFreeStmt in Driver Manager */ SQLGetPrivateProfileString(section, INI_CANCELASFREESTMT, "", temp, sizeof(temp), filename); if (temp[0]) - globals.cancel_as_freestmt = atoi(temp); - else if (!override) - globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; + comval->cancel_as_freestmt = atoi(temp); + else if (!ci) + comval->cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; /* UseDeclareFetch is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "", temp, sizeof(temp), filename); if (temp[0]) - globals.use_declarefetch = atoi(temp); - else if (!override) - globals.use_declarefetch = DEFAULT_USEDECLAREFETCH; + comval->use_declarefetch = atoi(temp); + else if (!ci) + comval->use_declarefetch = DEFAULT_USEDECLAREFETCH; /* Max Varchar Size */ SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "", temp, sizeof(temp), filename); if (temp[0]) - globals.max_varchar_size = atoi(temp); - else if (!override) - globals.max_varchar_size = MAX_VARCHAR_SIZE; + comval->max_varchar_size = atoi(temp); + else if (!ci) + comval->max_varchar_size = MAX_VARCHAR_SIZE; /* Max TextField Size */ SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, "", temp, sizeof(temp), filename); if (temp[0]) - globals.max_longvarchar_size = atoi(temp); - else if (!override) - globals.max_longvarchar_size = TEXT_FIELD_SIZE; + comval->max_longvarchar_size = atoi(temp); + else if (!ci) + comval->max_longvarchar_size = TEXT_FIELD_SIZE; /* Text As LongVarchar */ SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, "", temp, sizeof(temp), filename); if (temp[0]) - globals.text_as_longvarchar = atoi(temp); - else if (!override) - globals.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR; + comval->text_as_longvarchar = atoi(temp); + else if (!ci) + comval->text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR; /* Unknowns As LongVarchar */ SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, "", temp, sizeof(temp), filename); if (temp[0]) - globals.unknowns_as_longvarchar = atoi(temp); - else if (!override) - globals.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR; + comval->unknowns_as_longvarchar = atoi(temp); + else if (!ci) + comval->unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR; /* Bools As Char */ SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, "", temp, sizeof(temp), filename); if (temp[0]) - globals.bools_as_char = atoi(temp); - else if (!override) - globals.bools_as_char = DEFAULT_BOOLSASCHAR; + comval->bools_as_char = atoi(temp); + else if (!ci) + comval->bools_as_char = DEFAULT_BOOLSASCHAR; /* Extra Systable prefixes */ @@ -781,15 +958,15 @@ getGlobalDefaults(char *section, char *filename, char override) SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, "@@@", temp, sizeof(temp), filename); if (strcmp(temp, "@@@")) - strcpy(globals.extra_systable_prefixes, temp); - else if (!override) - strcpy(globals.extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES); + strcpy(comval->extra_systable_prefixes, temp); + else if (!ci) + strcpy(comval->extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES); - mylog("globals.extra_systable_prefixes = '%s'\n", globals.extra_systable_prefixes); + mylog("globals.extra_systable_prefixes = '%s'\n", comval->extra_systable_prefixes); /* Dont allow override of an override! */ - if (!override) + if (!ci) { /* @@ -797,15 +974,15 @@ getGlobalDefaults(char *section, char *filename, char override) * for override */ SQLGetPrivateProfileString(section, INI_CONNSETTINGS, "", - globals.conn_settings, sizeof(globals.conn_settings), filename); + comval->conn_settings, sizeof(comval->conn_settings), filename); /* Default state for future DSN's Readonly attribute */ SQLGetPrivateProfileString(section, INI_READONLY, "", temp, sizeof(temp), filename); if (temp[0]) - globals.onlyread = atoi(temp); + comval->onlyread = atoi(temp); else - globals.onlyread = DEFAULT_READONLY; + comval->onlyread = DEFAULT_READONLY; /* * Default state for future DSN's protocol attribute This isn't a @@ -815,85 +992,113 @@ getGlobalDefaults(char *section, char *filename, char override) SQLGetPrivateProfileString(section, INI_PROTOCOL, "@@@", temp, sizeof(temp), filename); if (strcmp(temp, "@@@")) - strcpy(globals.protocol, temp); + strcpy(comval->protocol, temp); else - strcpy(globals.protocol, DEFAULT_PROTOCOL); + strcpy(comval->protocol, DEFAULT_PROTOCOL); } } - /* * This function writes any global parameters (that can be manipulated) * to the ODBCINST.INI portion of the registry */ -void -updateGlobals(void) +static void +updateCommons(const ConnInfo *ci) { + const char *sectionName; + const char *fileName; + const GLOBAL_VALUES *comval; char tmp[128]; - sprintf(tmp, "%d", globals.fetch_max); - SQLWritePrivateProfileString(DBMS_NAME, - INI_FETCH, tmp, ODBCINST_INI); + if (ci) + if (ci->dsn && ci->dsn[0]) + { + mylog("DSN=%s updating\n", ci->dsn); + comval = &(ci->drivers); + sectionName = ci->dsn; + fileName = ODBC_INI; + } + else + { + mylog("ci but dsn==NULL\n"); + return; + } + else + { + mylog("drivers updating\n"); + comval = &globals; + sectionName = DBMS_NAME; + fileName = ODBCINST_INI; + } + sprintf(tmp, "%d", comval->fetch_max); + SQLWritePrivateProfileString(sectionName, + INI_FETCH, tmp, fileName); + + sprintf(tmp, "%d", comval->commlog); + SQLWritePrivateProfileString(sectionName, + INI_COMMLOG, tmp, fileName); - sprintf(tmp, "%d", globals.commlog); - SQLWritePrivateProfileString(DBMS_NAME, - INI_COMMLOG, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->debug); + SQLWritePrivateProfileString(sectionName, + INI_DEBUG, tmp, fileName); - sprintf(tmp, "%d", globals.disable_optimizer); - SQLWritePrivateProfileString(DBMS_NAME, - INI_OPTIMIZER, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->disable_optimizer); + SQLWritePrivateProfileString(sectionName, + INI_OPTIMIZER, tmp, fileName); - sprintf(tmp, "%d", globals.ksqo); - SQLWritePrivateProfileString(DBMS_NAME, - INI_KSQO, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->ksqo); + SQLWritePrivateProfileString(sectionName, + INI_KSQO, tmp, fileName); - sprintf(tmp, "%d", globals.unique_index); - SQLWritePrivateProfileString(DBMS_NAME, - INI_UNIQUEINDEX, tmp, ODBCINST_INI); + /* Never update the onlyread, unique_index from this module + sprintf(tmp, "%d", comval->unique_index); + SQLWritePrivateProfileString(sectionName, + INI_UNIQUEINDEX, tmp, fileName); - sprintf(tmp, "%d", globals.onlyread); - SQLWritePrivateProfileString(DBMS_NAME, - INI_READONLY, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->onlyread); + SQLWritePrivateProfileString(sectionName, + INI_READONLY, tmp, fileName);*/ - sprintf(tmp, "%d", globals.use_declarefetch); - SQLWritePrivateProfileString(DBMS_NAME, - INI_USEDECLAREFETCH, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->use_declarefetch); + SQLWritePrivateProfileString(sectionName, + INI_USEDECLAREFETCH, tmp, fileName); - sprintf(tmp, "%d", globals.unknown_sizes); - SQLWritePrivateProfileString(DBMS_NAME, - INI_UNKNOWNSIZES, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->unknown_sizes); + SQLWritePrivateProfileString(sectionName, + INI_UNKNOWNSIZES, tmp, fileName); - sprintf(tmp, "%d", globals.text_as_longvarchar); - SQLWritePrivateProfileString(DBMS_NAME, - INI_TEXTASLONGVARCHAR, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->text_as_longvarchar); + SQLWritePrivateProfileString(sectionName, + INI_TEXTASLONGVARCHAR, tmp, fileName); - sprintf(tmp, "%d", globals.unknowns_as_longvarchar); - SQLWritePrivateProfileString(DBMS_NAME, - INI_UNKNOWNSASLONGVARCHAR, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->unknowns_as_longvarchar); + SQLWritePrivateProfileString(sectionName, + INI_UNKNOWNSASLONGVARCHAR, tmp, fileName); - sprintf(tmp, "%d", globals.bools_as_char); - SQLWritePrivateProfileString(DBMS_NAME, - INI_BOOLSASCHAR, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->bools_as_char); + SQLWritePrivateProfileString(sectionName, + INI_BOOLSASCHAR, tmp, fileName); - sprintf(tmp, "%d", globals.parse); - SQLWritePrivateProfileString(DBMS_NAME, - INI_PARSE, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->parse); + SQLWritePrivateProfileString(sectionName, + INI_PARSE, tmp, fileName); - sprintf(tmp, "%d", globals.cancel_as_freestmt); - SQLWritePrivateProfileString(DBMS_NAME, - INI_CANCELASFREESTMT, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->cancel_as_freestmt); + SQLWritePrivateProfileString(sectionName, + INI_CANCELASFREESTMT, tmp, fileName); - sprintf(tmp, "%d", globals.max_varchar_size); - SQLWritePrivateProfileString(DBMS_NAME, - INI_MAXVARCHARSIZE, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->max_varchar_size); + SQLWritePrivateProfileString(sectionName, + INI_MAXVARCHARSIZE, tmp, fileName); - sprintf(tmp, "%d", globals.max_longvarchar_size); - SQLWritePrivateProfileString(DBMS_NAME, - INI_MAXLONGVARCHARSIZE, tmp, ODBCINST_INI); + sprintf(tmp, "%d", comval->max_longvarchar_size); + SQLWritePrivateProfileString(sectionName, + INI_MAXLONGVARCHARSIZE, tmp, fileName); - SQLWritePrivateProfileString(DBMS_NAME, - INI_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, ODBCINST_INI); + SQLWritePrivateProfileString(sectionName, + INI_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, fileName); - SQLWritePrivateProfileString(DBMS_NAME, - INI_CONNSETTINGS, globals.conn_settings, ODBCINST_INI); + /* Never update the conn_setting from this module + SQLWritePrivateProfileString(sectionName, + INI_CONNSETTINGS, comval->conn_settings, fileName); */ } diff --git a/src/interfaces/odbc/dlg_specific.h b/src/interfaces/odbc/dlg_specific.h index 67f9944975..6d9885434f 100644 --- a/src/interfaces/odbc/dlg_specific.h +++ b/src/interfaces/odbc/dlg_specific.h @@ -126,10 +126,10 @@ #define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;" /* prototypes */ -void getGlobalDefaults(char *section, char *filename, char override); +void getCommonDefaults(const char *section, const char *filename, ConnInfo *ci); #ifdef WIN32 -void SetDlgStuff(HWND hdlg, ConnInfo *ci); +void SetDlgStuff(HWND hdlg, const ConnInfo *ci); void GetDlgStuff(HWND hdlg, ConnInfo *ci); int CALLBACK driver_optionsProc(HWND hdlg, @@ -144,11 +144,12 @@ int CALLBACK ds_optionsProc(HWND hdlg, #endif /* WIN32 */ void updateGlobals(void); -void writeDSNinfo(ConnInfo *ci); +void writeDSNinfo(const ConnInfo *ci); void getDSNdefaults(ConnInfo *ci); void getDSNinfo(ConnInfo *ci, char overwrite); -void makeConnectString(char *connect_string, ConnInfo *ci); -void copyAttributes(ConnInfo *ci, char *attribute, char *value); +void makeConnectString(char *connect_string, const ConnInfo *ci, UWORD); +void copyAttributes(ConnInfo *ci, const char *attribute, const char *value); +void copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value); #endif diff --git a/src/interfaces/odbc/drvconn.c b/src/interfaces/odbc/drvconn.c index e224cbda5e..e1eee25de5 100644 --- a/src/interfaces/odbc/drvconn.c +++ b/src/interfaces/odbc/drvconn.c @@ -51,7 +51,8 @@ #include "dlg_specific.h" /* prototypes */ -void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci); +void dconn_get_connect_attributes(const UCHAR FAR *connect_string, ConnInfo *ci); +static void dconn_get_common_attributes(const UCHAR FAR *connect_string, ConnInfo *ci); #ifdef WIN32 BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam); @@ -61,8 +62,6 @@ extern HINSTANCE NEAR s_hModule;/* Saved module handle. */ #endif -extern GLOBAL_VALUES globals; - RETCODE SQL_API PGAPI_DriverConnect( @@ -115,6 +114,8 @@ PGAPI_DriverConnect( * given -- if not, it does nothing!) */ getDSNinfo(ci, CONN_DONT_OVERWRITE); + dconn_get_common_attributes(connStrIn, ci); + logs_on_off(1, ci->drivers.debug, ci->drivers.commlog); /* Fill in any default parameters if they are not there. */ getDSNdefaults(ci); @@ -210,7 +211,7 @@ dialog: */ result = SQL_SUCCESS; - makeConnectString(connStrOut, ci); + makeConnectString(connStrOut, ci, cbConnStrOutMax); len = strlen(connStrOut); if (szConnStrOut) @@ -238,7 +239,7 @@ dialog: if (pcbConnStrOut) *pcbConnStrOut = len; - mylog("szConnStrOut = '%s'\n", szConnStrOut); + mylog("szConnStrOut = '%s' len=%d,%d\n", szConnStrOut, len, cbConnStrOutMax); qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut); @@ -323,8 +324,9 @@ dconn_FDriverConnectProc( return TRUE; case IDC_DRIVER: + ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), - hdlg, driver_optionsProc, (LPARAM) NULL); + hdlg, driver_optionsProc, (LPARAM) ci); break; case IDC_DATASOURCE: @@ -342,7 +344,7 @@ dconn_FDriverConnectProc( void -dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci) +dconn_get_connect_attributes(const UCHAR FAR *connect_string, ConnInfo *ci) { char *our_connect_string; char *pair, @@ -386,3 +388,47 @@ dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci) free(our_connect_string); } + +static void +dconn_get_common_attributes(const UCHAR FAR *connect_string, ConnInfo *ci) +{ + char *our_connect_string; + char *pair, + *attribute, + *value, + *equals; + char *strtok_arg; + + our_connect_string = strdup(connect_string); + strtok_arg = our_connect_string; + + mylog("our_connect_string = '%s'\n", our_connect_string); + + while (1) + { + pair = strtok(strtok_arg, ";"); + if (strtok_arg) + strtok_arg = 0; + if (!pair) + break; + + equals = strchr(pair, '='); + if (!equals) + continue; + + *equals = '\0'; + attribute = pair; /* ex. DSN */ + value = equals + 1; /* ex. 'CEO co1' */ + + mylog("attribute = '%s', value = '%s'\n", attribute, value); + + if (!attribute || !value) + continue; + + /* Copy the appropriate value to the conninfo */ + copyCommonAttributes(ci, attribute, value); + + } + + free(our_connect_string); +} diff --git a/src/interfaces/odbc/environ.c b/src/interfaces/odbc/environ.c index d21c0540ca..8e9156d2d0 100644 --- a/src/interfaces/odbc/environ.c +++ b/src/interfaces/odbc/environ.c @@ -43,7 +43,7 @@ PGAPI_AllocEnv(HENV FAR *phenv) * should work. */ if (globals.socket_buffersize <= 0) - getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE); + getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); *phenv = (HENV) EN_Constructor(); if (!*phenv) diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c index 374d700193..bd2600bd4f 100644 --- a/src/interfaces/odbc/execute.c +++ b/src/interfaces/odbc/execute.c @@ -34,7 +34,7 @@ #include "lobj.h" #include "pgapifunc.h" -extern GLOBAL_VALUES globals; +/*extern GLOBAL_VALUES globals;*/ /* Perform a Prepare on the SQL statement */ @@ -340,7 +340,32 @@ PGAPI_Execute( return retval; mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params); - +#ifdef PREPARE_TRIAL + if (stmt->inaccurate_result) + if (SC_is_pre_executable(stmt)) + { + BOOL in_trans = CC_is_in_trans(conn); + QResultClass *res; + CC_set_in_trans(conn); + stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL); + if (res && QR_aborted(res)) + { + CC_abort(conn); + stmt->errornumber = STMT_EXEC_ERROR; + stmt->errormsg = "Handle prepare error"; + return SQL_ERROR; + } + else + { + if (!in_trans) + CC_set_no_trans(conn); + stmt->status =STMT_FINISHED; + return SQL_SUCCESS; + } + } + else + return SQL_SUCCESS; +#endif /* PREPARE_TRIAL */ return SC_execute(stmt); } @@ -437,6 +462,7 @@ PGAPI_Cancel( #ifdef WIN32 HMODULE hmodule; FARPROC addr; + ConnInfo *ci; #endif @@ -448,6 +474,7 @@ PGAPI_Cancel( SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } + ci = &(SC_get_conn(stmt)->connInfo); /* * Not in the middle of SQLParamData/SQLPutData so cancel like a @@ -466,7 +493,7 @@ PGAPI_Cancel( */ #ifdef WIN32 - if (globals.cancel_as_freestmt) + if (ci->drivers.cancel_as_freestmt) { hmodule = GetModuleHandle("ODBC32"); addr = GetProcAddress(hmodule, "SQLFreeStmt"); @@ -569,6 +596,7 @@ PGAPI_ParamData( StatementClass *stmt = (StatementClass *) hstmt; int i, retval; + ConnInfo *ci; mylog("%s: entering...\n", func); @@ -577,6 +605,7 @@ PGAPI_ParamData( SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } + ci = &(SC_get_conn(stmt)->connInfo); mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated); @@ -602,7 +631,7 @@ PGAPI_ParamData( lo_close(stmt->hdbc, stmt->lobj_fd); /* commit transaction if needed */ - if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) + if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { QResultClass *res; char ok; diff --git a/src/interfaces/odbc/info.c b/src/interfaces/odbc/info.c index 1bc96ac888..2f5d4c88d0 100644 --- a/src/interfaces/odbc/info.c +++ b/src/interfaces/odbc/info.c @@ -54,7 +54,7 @@ #define TRIGGER_UPDATE 0x02 -extern GLOBAL_VALUES globals; +/* extern GLOBAL_VALUES globals; */ @@ -83,7 +83,7 @@ PGAPI_GetInfo( return SQL_INVALID_HANDLE; } - ci = &conn->connInfo; + ci = &(conn->connInfo); switch (fInfoType) { @@ -113,7 +113,7 @@ PGAPI_GetInfo( case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */ /* very simple bookmark support */ len = 4; - value = globals.use_declarefetch ? 0 : (SQL_BP_SCROLL); + value = ci->drivers.use_declarefetch ? 0 : (SQL_BP_SCROLL); break; case SQL_COLUMN_ALIAS: /* ODBC 2.0 */ @@ -167,7 +167,7 @@ PGAPI_GetInfo( len = 2; value = SQL_CB_CLOSE; #ifdef DRIVER_CURSOR_IMPLEMENT - if (!globals.use_declarefetch) + if (!ci->drivers.use_declarefetch) value = SQL_CB_PRESERVE; #endif /* DRIVER_CURSOR_IMPLEMENT */ break; @@ -176,7 +176,7 @@ PGAPI_GetInfo( len = 2; value = SQL_CB_CLOSE; #ifdef DRIVER_CURSOR_IMPLEMENT - if (!globals.use_declarefetch) + if (!ci->drivers.use_declarefetch) value = SQL_CB_PRESERVE; #endif /* DRIVER_CURSOR_IMPLEMENT */ break; @@ -261,7 +261,7 @@ PGAPI_GetInfo( case SQL_FETCH_DIRECTION: /* ODBC 1.0 */ len = 4; - value = globals.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT | + value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST | SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | @@ -315,7 +315,7 @@ PGAPI_GetInfo( case SQL_LOCK_TYPES: /* ODBC 2.0 */ len = 4; - value = globals.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE; + value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE; break; case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */ @@ -523,12 +523,12 @@ PGAPI_GetInfo( case SQL_POS_OPERATIONS: /* ODBC 2.0 */ len = 4; - value = globals.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH); + value = ci->drivers.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH); break; case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */ len = 4; - value = globals.lie ? (SQL_PS_POSITIONED_DELETE | + value = ci->drivers.lie ? (SQL_PS_POSITIONED_DELETE | SQL_PS_POSITIONED_UPDATE | SQL_PS_SELECT_FOR_UPDATE) : 0; break; @@ -571,12 +571,12 @@ PGAPI_GetInfo( * Driver doesn't support keyset-driven or mixed cursors, so * not much point in saying row updates are supported */ - p = globals.lie ? "Y" : "N"; + p = ci->drivers.lie ? "Y" : "N"; break; case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */ len = 4; - value = globals.lie ? (SQL_SCCO_READ_ONLY | + value = ci->drivers.lie ? (SQL_SCCO_READ_ONLY | SQL_SCCO_LOCK | SQL_SCCO_OPT_ROWVER | SQL_SCCO_OPT_VALUES) : (SQL_SCCO_READ_ONLY); @@ -584,11 +584,11 @@ PGAPI_GetInfo( case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */ len = 4; - value = globals.lie ? (SQL_SO_FORWARD_ONLY | + value = ci->drivers.lie ? (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC | SQL_SO_KEYSET_DRIVEN | SQL_SO_DYNAMIC | - SQL_SO_MIXED) : (globals.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC)); + SQL_SO_MIXED) : (ci->drivers.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC)); break; case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */ @@ -605,7 +605,7 @@ PGAPI_GetInfo( case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */ len = 4; - value = globals.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0; + value = ci->drivers.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0; break; case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */ @@ -782,7 +782,7 @@ PGAPI_GetTypeInfo( for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i]) { - pgType = sqltype_to_pgtype(sqlType); + pgType = sqltype_to_pgtype(stmt, sqlType); if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType) { @@ -833,12 +833,13 @@ PGAPI_GetFunctions( UWORD FAR *pfExists) { static char *func = "PGAPI_GetFunctions"; + ConnInfo *ci = &(((ConnectionClass *)hdbc)->connInfo); mylog("%s: entering...%u\n", func, fFunction); if (fFunction == SQL_API_ALL_FUNCTIONS) { - if (globals.lie) + if (ci->drivers.lie) { int i; @@ -923,7 +924,7 @@ PGAPI_GetFunctions( } else { - if (globals.lie) + if (ci->drivers.lie) *pfExists = TRUE; else { @@ -1156,8 +1157,8 @@ PGAPI_Tables( stmt->manual_result = TRUE; stmt->errormsg_created = TRUE; - conn = (ConnectionClass *) (stmt->hdbc); - ci = &stmt->hdbc->connInfo; + conn = SC_get_conn(stmt); + ci = &(conn->connInfo); result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) @@ -1188,7 +1189,7 @@ PGAPI_Tables( my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName); /* Parse the extra systable prefix */ - strcpy(prefixes, globals.extra_systable_prefixes); + strcpy(prefixes, ci->drivers.extra_systable_prefixes); i = 0; prefix[i] = strtok(prefixes, ";"); while (prefix[i] && i < 32) @@ -1477,8 +1478,8 @@ PGAPI_Columns( stmt->manual_result = TRUE; stmt->errormsg_created = TRUE; - conn = (ConnectionClass *) (stmt->hdbc); - ci = &stmt->hdbc->connInfo; + conn = SC_get_conn(stmt); + ci = &(conn->connInfo); /* * Create the query to find out the columns (Note: pre 6.3 did not @@ -1778,8 +1779,8 @@ PGAPI_Columns( if (mod_length >= 4) mod_length -= 4;/* the length is in atttypmod - 4 */ - if (mod_length > globals.max_varchar_size || mod_length <= 0) - mod_length = globals.max_varchar_size; + if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0) + mod_length = ci->drivers.max_varchar_size; mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length); @@ -1896,7 +1897,7 @@ PGAPI_SpecialColumns( SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } - ci = &stmt->hdbc->connInfo; + ci = &(SC_get_conn(stmt)->connInfo); stmt->manual_result = TRUE; @@ -2062,7 +2063,7 @@ PGAPI_Statistics( stmt->manual_result = TRUE; stmt->errormsg_created = TRUE; - ci = &stmt->hdbc->connInfo; + ci = &(SC_get_conn(stmt)->connInfo); stmt->result = QR_Constructor(); if (!stmt->result) @@ -2301,7 +2302,7 @@ PGAPI_Statistics( set_tuplefield_string(&row->tuple[2], table_name); /* non-unique index? */ - set_tuplefield_int2(&row->tuple[3], (Int2) (globals.unique_index ? FALSE : TRUE)); + set_tuplefield_int2(&row->tuple[3], (Int2) (ci->drivers.unique_index ? FALSE : TRUE)); /* no index qualifier */ set_tuplefield_string(&row->tuple[4], ""); @@ -2345,7 +2346,7 @@ PGAPI_Statistics( set_tuplefield_string(&row->tuple[2], table_name); /* non-unique index? */ - if (globals.unique_index) + if (ci->drivers.unique_index) set_tuplefield_int2(&row->tuple[3], (Int2) (atoi(isunique) ? FALSE : TRUE)); else set_tuplefield_int2(&row->tuple[3], TRUE); @@ -2556,7 +2557,7 @@ PGAPI_PrimaryKeys( return SQL_ERROR; } - conn = (ConnectionClass *) (stmt->hdbc); + conn = SC_get_conn(stmt); if (PG_VERSION_LE(conn, 6.4)) qstart = 2; else diff --git a/src/interfaces/odbc/misc.c b/src/interfaces/odbc/misc.c index 1bfb877cbf..87a4ee01ff 100644 --- a/src/interfaces/odbc/misc.c +++ b/src/interfaces/odbc/misc.c @@ -30,11 +30,11 @@ #endif extern GLOBAL_VALUES globals; -void generate_filename(char *, char *, char *); +void generate_filename(const char *, const char *, char *); void -generate_filename(char *dirname, char *prefix, char *filename) +generate_filename(const char *dirname, const char *prefix, char *filename) { int pid = 0; @@ -58,6 +58,33 @@ generate_filename(char *dirname, char *prefix, char *filename) return; } +static int mylog_on = 0, qlog_on = 0; +void logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff) +{ + static int mylog_on_count = 0, mylog_off_count = 0, + qlog_on_count = 0, qlog_off_count = 0; + + if (mylog_onoff) + mylog_on_count += cnopen; + else + mylog_off_count += cnopen; + if (mylog_on_count > 0) + mylog_on = 1; + else if (mylog_off_count > 0) + mylog_on = 0; + else + mylog_on = globals.debug; + if (qlog_onoff) + qlog_on_count += cnopen; + else + qlog_off_count += cnopen; + if (qlog_on_count > 0) + qlog_on = 1; + else if (qlog_off_count > 0) + qlog_on = 0; + else + qlog_on = globals.commlog; +} #ifdef MY_LOG void @@ -65,9 +92,9 @@ mylog(char *fmt,...) { va_list args; char filebuf[80]; - FILE *LOGFP = globals.mylogFP; + static FILE *LOGFP = NULL; - if (globals.debug) + if (mylog_on) { va_start(args, fmt); @@ -75,7 +102,6 @@ mylog(char *fmt,...) { generate_filename(MYLOGDIR, MYLOGFILE, filebuf); LOGFP = fopen(filebuf, PG_BINARY_W); - globals.mylogFP = LOGFP; setbuf(LOGFP, NULL); } @@ -95,9 +121,9 @@ qlog(char *fmt,...) { va_list args; char filebuf[80]; - FILE *LOGFP = globals.qlogFP; + static FILE *LOGFP = NULL; - if (globals.commlog) + if (qlog_on) { va_start(args, fmt); @@ -105,7 +131,6 @@ qlog(char *fmt,...) { generate_filename(QLOGDIR, QLOGFILE, filebuf); LOGFP = fopen(filebuf, PG_BINARY_W); - globals.qlogFP = LOGFP; setbuf(LOGFP, NULL); } @@ -139,7 +164,7 @@ qlog(char *fmt,...) * (not including null term) */ int -my_strcpy(char *dst, int dst_len, char *src, int src_len) +my_strcpy(char *dst, int dst_len, const char *src, int src_len) { if (dst_len <= 0) return STRCPY_FAIL; @@ -214,7 +239,7 @@ strncpy_null(char *dst, const char *src, int len) *------ */ char * -make_string(char *s, int len, char *buf) +make_string(const char *s, int len, char *buf) { int length; char *str; @@ -248,7 +273,7 @@ make_string(char *s, int len, char *buf) * This routine could be modified to use vsprintf() to handle multiple arguments. */ char * -my_strcat(char *buf, char *fmt, char *s, int len) +my_strcat(char *buf, const char *fmt, const char *s, int len) { if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) { diff --git a/src/interfaces/odbc/misc.h b/src/interfaces/odbc/misc.h index dc2ef0d5be..016b4b7a5e 100644 --- a/src/interfaces/odbc/misc.h +++ b/src/interfaces/odbc/misc.h @@ -89,8 +89,8 @@ extern void qlog(char *fmt,...); void remove_newlines(char *string); char *strncpy_null(char *dst, const char *src, int len); char *trim(char *string); -char *make_string(char *s, int len, char *buf); -char *my_strcat(char *buf, char *fmt, char *s, int len); +char *make_string(const char *s, int len, char *buf); +char *my_strcat(char *buf, const char *fmt, const char *s, int len); /* defines for return value of my_strcpy */ #define STRCPY_SUCCESS 1 @@ -98,6 +98,6 @@ char *my_strcat(char *buf, char *fmt, char *s, int len); #define STRCPY_TRUNCATED (-1) #define STRCPY_NULL (-2) -int my_strcpy(char *dst, int dst_len, char *src, int src_len); +int my_strcpy(char *dst, int dst_len, const char *src, int src_len); #endif diff --git a/src/interfaces/odbc/multibyte.c b/src/interfaces/odbc/multibyte.c index abc6b3d6eb..fa81f4775f 100644 --- a/src/interfaces/odbc/multibyte.c +++ b/src/interfaces/odbc/multibyte.c @@ -88,7 +88,7 @@ check_client_encoding(unsigned char *str) multibyte_client_encoding = BIG5; return ("BIG5"); } - return ("OHTER"); + return ("OTHER"); } diff --git a/src/interfaces/odbc/odbcapi.c b/src/interfaces/odbc/odbcapi.c index 60205c011b..dbb3142401 100644 --- a/src/interfaces/odbc/odbcapi.c +++ b/src/interfaces/odbc/odbcapi.c @@ -254,7 +254,7 @@ RETCODE SQL_API SQLGetData(HSTMT StatementHandle, RETCODE SQL_API SQLGetFunctions(HDBC ConnectionHandle, SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported) { - mylog("[SQLGetFunctions"); + mylog("[SQLGetFunctions]"); #if (ODBCVER >= 0x3000) if (FunctionId == SQL_API_ODBC3_ALL_FUNCTIONS) return PGAPI_GetFunctions30(ConnectionHandle, FunctionId, Supported); @@ -270,10 +270,12 @@ RETCODE SQL_API SQLGetInfo(HDBC ConnectionHandle, mylog("[SQLGetInfo(30)]"); if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, BufferLength, StringLength)) == SQL_ERROR) - return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue, - BufferLength, StringLength); - else - return ret; + { + if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x3000) + return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue, + BufferLength, StringLength); + } + return ret; #else mylog("[SQLGetInfo]"); return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, diff --git a/src/interfaces/odbc/odbcapi30.c b/src/interfaces/odbc/odbcapi30.c index cee57934df..e657595c03 100644 --- a/src/interfaces/odbc/odbcapi30.c +++ b/src/interfaces/odbc/odbcapi30.c @@ -395,7 +395,7 @@ RETCODE SQL_API SQLSetEnvAttr(HENV EnvironmentHandle, /* *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; */ return SQL_SUCCESS; case SQL_ATTR_ODBC_VERSION: - if ((SQLUINTEGER) Value == SQL_OV_ODBC3) + if ((SQLUINTEGER) Value == SQL_OV_ODBC2) return SQL_SUCCESS; break; case SQL_ATTR_OUTPUT_NTS: diff --git a/src/interfaces/odbc/options.c b/src/interfaces/odbc/options.c index 77421b63eb..aa18bb1615 100644 --- a/src/interfaces/odbc/options.c +++ b/src/interfaces/odbc/options.c @@ -33,7 +33,6 @@ #include "pgapifunc.h" -extern GLOBAL_VALUES globals; RETCODE set_statement_option(ConnectionClass *conn, StatementClass *stmt, @@ -49,7 +48,12 @@ set_statement_option(ConnectionClass *conn, { static char *func = "set_statement_option"; char changed = FALSE; + ConnInfo *ci = NULL; + if (conn) + ci = &(conn->connInfo); + else if (stmt) + ci = &(SC_get_conn(stmt)->connInfo); switch (fOption) { case SQL_ASYNC_ENABLE: /* ignored */ @@ -70,7 +74,7 @@ set_statement_option(ConnectionClass *conn, * read-only */ mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam); - if (globals.lie || vParam == SQL_CONCUR_READ_ONLY || vParam == SQL_CONCUR_ROWVER) + if (ci->drivers.lie || vParam == SQL_CONCUR_READ_ONLY || vParam == SQL_CONCUR_ROWVER) { if (conn) conn->stmtOptions.scroll_concurrency = vParam; @@ -95,7 +99,7 @@ set_statement_option(ConnectionClass *conn, */ mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam); - if (globals.lie) + if (ci->drivers.lie) { if (conn) conn->stmtOptions.cursor_type = vParam; @@ -104,7 +108,7 @@ set_statement_option(ConnectionClass *conn, } else { - if (globals.use_declarefetch) + if (ci->drivers.use_declarefetch) { if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY; @@ -147,7 +151,7 @@ set_statement_option(ConnectionClass *conn, break; /*------- - * if (globals.lie) + * if (ci->drivers.lie) * stmt->keyset_size = vParam; * else * { @@ -433,6 +437,7 @@ PGAPI_GetConnectOption( { static char *func = "PGAPI_GetConnectOption"; ConnectionClass *conn = (ConnectionClass *) hdbc; + ConnInfo *ci = &(conn->connInfo); mylog("%s: entering...\n", func); @@ -464,7 +469,7 @@ PGAPI_GetConnectOption( break; case SQL_PACKET_SIZE: /* NOT SUPPORTED */ - *((UDWORD *) pvParam) = globals.socket_buffersize; + *((UDWORD *) pvParam) = ci->drivers.socket_buffersize; break; case SQL_QUIET_MODE: /* NOT SUPPORTED */ @@ -536,6 +541,7 @@ PGAPI_GetStmtOption( static char *func = "PGAPI_GetStmtOption"; StatementClass *stmt = (StatementClass *) hstmt; QResultClass *res; + ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); mylog("%s: entering...\n", func); @@ -557,7 +563,7 @@ PGAPI_GetStmtOption( res = stmt->result; - if (stmt->manual_result || !globals.use_declarefetch) + if (stmt->manual_result || !ci->drivers.use_declarefetch) { /* make sure we're positioned on a valid row */ if ((stmt->currTuple < 0) || diff --git a/src/interfaces/odbc/pgtypes.c b/src/interfaces/odbc/pgtypes.c index fdc38d62a1..f2b1853590 100644 --- a/src/interfaces/odbc/pgtypes.c +++ b/src/interfaces/odbc/pgtypes.c @@ -34,7 +34,6 @@ #endif -extern GLOBAL_VALUES globals; Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); @@ -105,9 +104,10 @@ Int2 sqlTypes[] = { Int4 -sqltype_to_pgtype(SWORD fSqlType) +sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) { Int4 pgType; + ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); switch (fSqlType) { @@ -120,7 +120,7 @@ sqltype_to_pgtype(SWORD fSqlType) break; case SQL_BIT: - pgType = globals.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL; + pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL; break; case SQL_DATE: @@ -150,7 +150,7 @@ sqltype_to_pgtype(SWORD fSqlType) break; case SQL_LONGVARCHAR: - pgType = globals.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; + pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; break; case SQL_REAL: @@ -202,6 +202,7 @@ sqltype_to_pgtype(SWORD fSqlType) Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) { + ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); switch (type) { case PG_TYPE_CHAR: @@ -218,7 +219,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) return SQL_VARCHAR; case PG_TYPE_TEXT: - return globals.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; + return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; case PG_TYPE_BYTEA: return SQL_VARBINARY; @@ -255,7 +256,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) case PG_TYPE_MONEY: return SQL_FLOAT; case PG_TYPE_BOOL: - return globals.bools_as_char ? SQL_CHAR : SQL_BIT; + return ci->drivers.bools_as_char ? SQL_CHAR : SQL_BIT; default: @@ -268,7 +269,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) if (type == stmt->hdbc->lobj_type) return SQL_LONGVARBINARY; - return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; + return ci->drivers.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; } } @@ -276,6 +277,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type) { + ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); switch (type) { case PG_TYPE_INT8: @@ -303,7 +305,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type) case PG_TYPE_MONEY: return SQL_C_FLOAT; case PG_TYPE_BOOL: - return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT; + return ci->drivers.bools_as_char ? SQL_C_CHAR : SQL_C_BIT; case PG_TYPE_BYTEA: return SQL_C_BINARY; @@ -470,6 +472,7 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si maxsize; QResultClass *result; ColumnInfoClass *flds; + ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as); @@ -477,22 +480,22 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si switch (type) { case PG_TYPE_TEXT: - if (globals.text_as_longvarchar) - maxsize = globals.max_longvarchar_size; + if (ci->drivers.text_as_longvarchar) + maxsize = ci->drivers.max_longvarchar_size; else - maxsize = globals.max_varchar_size; + maxsize = ci->drivers.max_varchar_size; break; case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: - maxsize = globals.max_varchar_size; + maxsize = ci->drivers.max_varchar_size; break; default: - if (globals.unknowns_as_longvarchar) - maxsize = globals.max_longvarchar_size; + if (ci->drivers.unknowns_as_longvarchar) + maxsize = ci->drivers.max_longvarchar_size; else - maxsize = globals.max_varchar_size; + maxsize = ci->drivers.max_varchar_size; break; } diff --git a/src/interfaces/odbc/pgtypes.h b/src/interfaces/odbc/pgtypes.h index 03cc2babd1..7bd33cf751 100644 --- a/src/interfaces/odbc/pgtypes.h +++ b/src/interfaces/odbc/pgtypes.h @@ -68,7 +68,7 @@ extern Int2 sqlTypes[]; /* Defines for pgtype_precision */ #define PG_STATIC (-1) -Int4 sqltype_to_pgtype(Int2 fSqlType); +Int4 sqltype_to_pgtype(StatementClass *stmt, Int2 fSqlType); Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type); Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type); diff --git a/src/interfaces/odbc/psqlodbc.c b/src/interfaces/odbc/psqlodbc.c index 9851af2ee6..ad156379d0 100644 --- a/src/interfaces/odbc/psqlodbc.c +++ b/src/interfaces/odbc/psqlodbc.c @@ -60,7 +60,7 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) return FALSE; } - getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE); + getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); break; case DLL_THREAD_ATTACH: @@ -99,7 +99,7 @@ static BOOL __attribute__((constructor)) init(void) { - getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE); + getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); return TRUE; } @@ -112,7 +112,7 @@ init(void) BOOL _init(void) { - getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE); + getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); return TRUE; } diff --git a/src/interfaces/odbc/psqlodbc.h b/src/interfaces/odbc/psqlodbc.h index 542fe7ff59..a6c5d9eda3 100644 --- a/src/interfaces/odbc/psqlodbc.h +++ b/src/interfaces/odbc/psqlodbc.h @@ -5,7 +5,7 @@ * * Comments: See "notice.txt" for copyright and license information. * - * $Id: psqlodbc.h,v 1.46 2001/08/24 14:07:50 petere Exp $ + * $Id: psqlodbc.h,v 1.47 2001/09/07 06:02:22 inoue Exp $ * */ @@ -145,10 +145,6 @@ typedef struct GlobalValues_ char extra_systable_prefixes[MEDIUM_REGISTRY_LEN]; char conn_settings[LARGE_REGISTRY_LEN]; char protocol[SMALL_REGISTRY_LEN]; - - - FILE *mylogFP; - FILE *qlogFP; } GLOBAL_VALUES; typedef struct StatementOptions_ @@ -176,6 +172,7 @@ typedef struct QueryInfo_ char *cursor; } QueryInfo; +void logs_on_off(int cnopen, int, int); #define PG_TYPE_LO (-999) /* hack until permanent * type available */ diff --git a/src/interfaces/odbc/psqlodbc.rc b/src/interfaces/odbc/psqlodbc.rc index 85bfcdb289..aa149ade93 100644 --- a/src/interfaces/odbc/psqlodbc.rc +++ b/src/interfaces/odbc/psqlodbc.rc @@ -83,7 +83,7 @@ BEGIN DRV_MSG_LABEL,25,4,238,10 END -DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 306, 213 +DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 306, 226 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Advanced Options (Driver)" FONT 10, "Terminal" @@ -104,34 +104,38 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,13,47,84,10 CONTROL "Cancel as FreeStmt (Exp)",DRV_CANCELASFREESTMT,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,164,50,112,10 - GROUPBOX "Unknown Sizes",IDC_STATIC,13,63,175,24 + CONTROL "Mylog(Debug ouput",DRV_DEBUG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,164,63,112,10 + GROUPBOX "Unknown Sizes",IDC_STATIC,13,76,175,24 CONTROL "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,21,71,44,10 + WS_GROUP | WS_TABSTOP,21,84,44,10 CONTROL "Don't Know",DRV_UNKNOWN_DONTKNOW,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,72,71,56,10 + BS_AUTORADIOBUTTON | WS_TABSTOP,72,84,56,10 CONTROL "Longest",DRV_UNKNOWN_LONGEST,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,135,71,44,10 - GROUPBOX "Data Type Options",IDC_STATIC,13,91,282,23 + BS_AUTORADIOBUTTON | WS_TABSTOP,135,84,44,10 + GROUPBOX "Data Type Options",IDC_STATIC,13,104,282,23 CONTROL "Text as LongVarChar",DRV_TEXT_LONGVARCHAR,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,102,92,10 + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,115,92,10 CONTROL "Unknowns as LongVarChar",DRV_UNKNOWNS_LONGVARCHAR, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,102,108,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,115,108,10 CONTROL "Bools as Char",DRV_BOOLS_CHAR,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,225,102,68,10 - LTEXT "&Cache Size:",IDC_STATIC,15,120,45,8 - EDITTEXT DRV_CACHE_SIZE,61,116,35,12,ES_AUTOHSCROLL - LTEXT "Max &Varchar:",IDC_STATIC,99,120,49,8 - EDITTEXT DRV_VARCHAR_SIZE,149,116,35,12,ES_AUTOHSCROLL - LTEXT "Max Lon&gVarChar:",IDC_STATIC,192,120,65,8 - EDITTEXT DRV_LONGVARCHAR_SIZE,259,116,35,12,ES_AUTOHSCROLL - LTEXT "SysTable &Prefixes:",IDC_STATIC,23,131,36,20 - EDITTEXT DRV_EXTRASYSTABLEPREFIXES,61,137,75,12,ES_AUTOHSCROLL - LTEXT "Connect &Settings:",IDC_STATIC,22,152,35,20 - EDITTEXT DRV_CONNSETTINGS,61,153,225,25,ES_MULTILINE | + WS_TABSTOP,225,115,68,10 + LTEXT "&Cache Size:",IDC_STATIC,15,133,45,8 + EDITTEXT DRV_CACHE_SIZE,61,129,35,12,ES_AUTOHSCROLL + LTEXT "Max &Varchar:",IDC_STATIC,99,133,49,8 + EDITTEXT DRV_VARCHAR_SIZE,149,129,35,12,ES_AUTOHSCROLL + LTEXT "Max Lon&gVarChar:",IDC_STATIC,192,133,65,8 + EDITTEXT DRV_LONGVARCHAR_SIZE,259,129,35,12,ES_AUTOHSCROLL + LTEXT "SysTable &Prefixes:",IDC_STATIC,23,144,36,20 + EDITTEXT DRV_EXTRASYSTABLEPREFIXES,61,153,75,12,ES_AUTOHSCROLL + LTEXT "Connect &Settings:",IDC_STATIC,22,165,35,20 + EDITTEXT DRV_CONNSETTINGS,61,165,225,25,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,59,188,50,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,129,188,50,14 - PUSHBUTTON "Defaults",IDDEFAULTS,199,188,50,15 + DEFPUSHBUTTON "OK",IDOK,59,201,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,129,201,50,14 + PUSHBUTTON "Defaults",IDDEFAULTS,199,201,50,15 + CONTROL "DSN",DRV_OR_DSN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | + BS_NOTIFY | WS_TABSTOP,243,208,30,10 END DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161 @@ -194,7 +198,7 @@ BEGIN DRV_MSG_LABEL,36,5,220,15 END -DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 287, 226 +DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 287, 241 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Advanced Options (Driver)" FONT 8, "MS Sans Serif" @@ -215,34 +219,38 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,15,50,80,10 CONTROL "Cancel as FreeStmt (Exp)",DRV_CANCELASFREESTMT,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,140,50,105,10 - GROUPBOX "Unknown Sizes",IDC_STATIC,10,65,175,25 + CONTROL "Mylog(Debug ouput)",DRV_DEBUG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,140,65,112,10 + GROUPBOX "Unknown Sizes",IDC_STATIC,10,80,175,25 CONTROL "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,15,76,45,10 + WS_GROUP | WS_TABSTOP,15,91,45,10 CONTROL "Don't Know",DRV_UNKNOWN_DONTKNOW,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,70,76,53,10 + BS_AUTORADIOBUTTON | WS_TABSTOP,70,91,53,10 CONTROL "Longest",DRV_UNKNOWN_LONGEST,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,130,76,50,10 - GROUPBOX "Data Type Options",IDC_STATIC,10,95,270,25 + BS_AUTORADIOBUTTON | WS_TABSTOP,130,91,50,10 + GROUPBOX "Data Type Options",IDC_STATIC,10,110,270,25 CONTROL "Text as LongVarChar",DRV_TEXT_LONGVARCHAR,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,105,80,10 + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,120,80,10 CONTROL "Unknowns as LongVarChar",DRV_UNKNOWNS_LONGVARCHAR, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,105,100,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,120,100,10 CONTROL "Bools as Char",DRV_BOOLS_CHAR,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,215,105,60,10 - LTEXT "&Cache Size:",IDC_STATIC,10,130,40,10 - EDITTEXT DRV_CACHE_SIZE,50,130,35,12,ES_AUTOHSCROLL - LTEXT "Max &Varchar:",IDC_STATIC,90,130,45,10 - EDITTEXT DRV_VARCHAR_SIZE,135,130,35,12,ES_AUTOHSCROLL - LTEXT "Max Lon&gVarChar:",IDC_STATIC,180,130,60,10 - EDITTEXT DRV_LONGVARCHAR_SIZE,240,130,35,12,ES_AUTOHSCROLL - LTEXT "SysTable &Prefixes:",IDC_STATIC,15,145,35,20 - EDITTEXT DRV_EXTRASYSTABLEPREFIXES,50,151,75,12,ES_AUTOHSCROLL - RTEXT "Connect &Settings:",IDC_STATIC,10,170,35,20 - EDITTEXT DRV_CONNSETTINGS,50,170,225,25,ES_MULTILINE | + WS_TABSTOP,215,120,60,10 + LTEXT "&Cache Size:",IDC_STATIC,10,145,40,10 + EDITTEXT DRV_CACHE_SIZE,50,145,35,12,ES_AUTOHSCROLL + LTEXT "Max &Varchar:",IDC_STATIC,90,145,45,10 + EDITTEXT DRV_VARCHAR_SIZE,135,145,35,12,ES_AUTOHSCROLL + LTEXT "Max Lon&gVarChar:",IDC_STATIC,180,145,60,10 + EDITTEXT DRV_LONGVARCHAR_SIZE,240,145,35,12,ES_AUTOHSCROLL + LTEXT "SysTable &Prefixes:",IDC_STATIC,15,160,35,20 + EDITTEXT DRV_EXTRASYSTABLEPREFIXES,50,166,75,12,ES_AUTOHSCROLL + RTEXT "Connect &Settings:",IDC_STATIC,10,185,35,20 + EDITTEXT DRV_CONNSETTINGS,50,185,225,25,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,45,205,50,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,115,205,50,14 - PUSHBUTTON "Defaults",IDDEFAULTS,185,205,50,15 + DEFPUSHBUTTON "OK",IDOK,45,220,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,115,220,50,14 + PUSHBUTTON "Defaults",IDDEFAULTS,185,220,50,15 + CONTROL "DSN",DRV_OR_DSN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | + BS_NOTIFY | WS_TABSTOP,243,224,30,10 END DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161 diff --git a/src/interfaces/odbc/qresult.c b/src/interfaces/odbc/qresult.c index 086f4b8752..e2d7541e36 100644 --- a/src/interfaces/odbc/qresult.c +++ b/src/interfaces/odbc/qresult.c @@ -86,7 +86,7 @@ QR_inc_base(QResultClass *self, int base_inc) * CLASS QResult */ QResultClass * -QR_Constructor(void) +QR_Constructor() { QResultClass *rv; @@ -239,6 +239,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor) */ if (conn != NULL) { + ConnInfo *ci = &(conn->connInfo); self->conn = conn; mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor == NULL) ? "" : cursor, self->cursor); @@ -246,7 +247,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor) if (self->cursor) free(self->cursor); - if (globals.use_declarefetch) + if (ci->drivers.use_declarefetch) { if (!cursor || cursor[0] == '\0') { @@ -276,13 +277,14 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor) mylog("QR_fetch_tuples: past CI_read_fields: num_fields = %d\n", self->num_fields); - if (globals.use_declarefetch) + if (ci->drivers.use_declarefetch) tuple_size = self->cache_size; else tuple_size = TUPLE_MALLOC_INC; /* allocate memory for the tuple cache */ mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size); + self->count_allocated = 0; self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size); if (!self->backend_tuples) { @@ -329,7 +331,7 @@ QR_close(QResultClass *self) { QResultClass *res; - if (globals.use_declarefetch && self->conn && self->cursor) + if (self->conn && self->cursor && self->conn->connInfo.drivers.use_declarefetch) { char buf[64]; @@ -399,6 +401,7 @@ QR_next_tuple(QResultClass *self) char cmdbuffer[ERROR_MSG_LENGTH + 1]; char fetch[128]; QueryInfo qi; + ConnInfo *ci = NULL; if (fetch_count < fcount) { @@ -430,7 +433,8 @@ QR_next_tuple(QResultClass *self) if (!self->inTuples) { - if (!globals.use_declarefetch) + ci = &(self->conn->connInfo); + if (!ci->drivers.use_declarefetch) { mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count); self->tupleField = NULL; @@ -442,10 +446,10 @@ QR_next_tuple(QResultClass *self) { /* not a correction */ /* Determine the optimum cache size. */ - if (globals.fetch_max % self->rowset_size == 0) - fetch_size = globals.fetch_max; - else if (self->rowset_size < globals.fetch_max) - fetch_size = (globals.fetch_max / self->rowset_size) * self->rowset_size; + if (ci->drivers.fetch_max % self->rowset_size == 0) + fetch_size = ci->drivers.fetch_max; + else if (self->rowset_size < ci->drivers.fetch_max) + fetch_size = (ci->drivers.fetch_max / self->rowset_size) * self->rowset_size; else fetch_size = self->rowset_size; @@ -465,13 +469,17 @@ QR_next_tuple(QResultClass *self) self->fetch_count++; } - if (self->cache_size > self->count_allocated) - self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size); - if (!self->backend_tuples) + if (!self->backend_tuples || self->cache_size > self->count_allocated) { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Out of memory while reading tuples."); - return FALSE; + self->count_allocated = 0; + self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size); + if (!self->backend_tuples) + { + self->status = PGRES_FATAL_ERROR; + QR_set_message(self, "Out of memory while reading tuples."); + return FALSE; + } + self->count_allocated = self->cache_size; } sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor); @@ -482,10 +490,12 @@ QR_next_tuple(QResultClass *self) qi.result_in = self; qi.cursor = NULL; res = CC_send_query(self->conn, fetch, &qi); - if (res == NULL) + if (res == NULL || QR_get_aborted(res)) { self->status = PGRES_FATAL_ERROR; QR_set_message(self, "Error fetching next group."); + if (res) + QR_Destructor(res); return FALSE; } self->inTuples = TRUE; @@ -511,6 +521,7 @@ QR_next_tuple(QResultClass *self) sock = CC_get_socket(self->conn); self->tupleField = NULL; + ci = &(self->conn->connInfo); for (;;) { @@ -526,7 +537,7 @@ QR_next_tuple(QResultClass *self) case 'B': /* Tuples in binary format */ case 'D': /* Tuples in ASCII format */ - if (!globals.use_declarefetch && self->fcount >= self->count_allocated) + if (!ci->drivers.use_declarefetch && self->fcount >= self->count_allocated) { int tuple_size = self->count_allocated; diff --git a/src/interfaces/odbc/resource.h b/src/interfaces/odbc/resource.h index 213f6f5d8c..5ac559c478 100644 --- a/src/interfaces/odbc/resource.h +++ b/src/interfaces/odbc/resource.h @@ -1,62 +1,64 @@ -/* {{NO_DEPENDENCIES}} */ -/* Microsoft Developer Studio generated include file. */ -/* Used by psqlodbc.rc */ - -#define IDS_BADDSN 1 -#define IDS_MSGTITLE 2 -#define DLG_OPTIONS_DRV 102 -#define DLG_OPTIONS_DS 103 -#define IDC_DSNAME 400 -#define IDC_DSNAMETEXT 401 -#define IDC_DESC 404 -#define IDC_SERVER 407 -#define IDC_DATABASE 408 -#define DLG_CONFIG 1001 -#define IDC_PORT 1002 -#define IDC_USER 1006 -#define IDC_PASSWORD 1009 -#define DS_READONLY 1011 -#define DS_SHOWOIDCOLUMN 1012 -#define DS_FAKEOIDINDEX 1013 -#define DRV_COMMLOG 1014 -#define DS_PG62 1016 -#define IDC_DATASOURCE 1018 -#define DRV_OPTIMIZER 1019 -#define DS_CONNSETTINGS 1020 -#define IDC_DRIVER 1021 -#define DRV_CONNSETTINGS 1031 -#define DRV_UNIQUEINDEX 1032 -#define DRV_UNKNOWN_MAX 1035 -#define DRV_UNKNOWN_DONTKNOW 1036 -#define DRV_READONLY 1037 -#define IDC_DESCTEXT 1039 -#define DRV_MSG_LABEL 1040 -#define DRV_UNKNOWN_LONGEST 1041 -#define DRV_TEXT_LONGVARCHAR 1043 -#define DRV_UNKNOWNS_LONGVARCHAR 1044 -#define DRV_CACHE_SIZE 1045 -#define DRV_VARCHAR_SIZE 1046 -#define DRV_LONGVARCHAR_SIZE 1047 -#define IDDEFAULTS 1048 -#define DRV_USEDECLAREFETCH 1049 -#define DRV_BOOLS_CHAR 1050 -#define DS_SHOWSYSTEMTABLES 1051 -#define DRV_EXTRASYSTABLEPREFIXES 1051 -#define DS_ROWVERSIONING 1052 -#define DRV_PARSE 1052 -#define DRV_CANCELASFREESTMT 1053 -#define IDC_OPTIONS 1054 -#define DRV_KSQO 1055 -#define DS_PG64 1057 -#define DS_PG63 1058 - -/* Next default values for new objects */ - -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 104 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1060 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by psqlodbc.rc +// +#define IDS_BADDSN 1 +#define IDS_MSGTITLE 2 +#define DLG_OPTIONS_DRV 102 +#define DLG_OPTIONS_DS 103 +#define IDC_DSNAME 400 +#define IDC_DSNAMETEXT 401 +#define IDC_DESC 404 +#define IDC_SERVER 407 +#define IDC_DATABASE 408 +#define DLG_CONFIG 1001 +#define IDC_PORT 1002 +#define IDC_USER 1006 +#define IDC_PASSWORD 1009 +#define DS_READONLY 1011 +#define DS_SHOWOIDCOLUMN 1012 +#define DS_FAKEOIDINDEX 1013 +#define DRV_COMMLOG 1014 +#define DS_PG62 1016 +#define IDC_DATASOURCE 1018 +#define DRV_OPTIMIZER 1019 +#define DS_CONNSETTINGS 1020 +#define IDC_DRIVER 1021 +#define DRV_CONNSETTINGS 1031 +#define DRV_UNIQUEINDEX 1032 +#define DRV_UNKNOWN_MAX 1035 +#define DRV_UNKNOWN_DONTKNOW 1036 +#define DRV_READONLY 1037 +#define IDC_DESCTEXT 1039 +#define DRV_MSG_LABEL 1040 +#define DRV_UNKNOWN_LONGEST 1041 +#define DRV_TEXT_LONGVARCHAR 1043 +#define DRV_UNKNOWNS_LONGVARCHAR 1044 +#define DRV_CACHE_SIZE 1045 +#define DRV_VARCHAR_SIZE 1046 +#define DRV_LONGVARCHAR_SIZE 1047 +#define IDDEFAULTS 1048 +#define DRV_USEDECLAREFETCH 1049 +#define DRV_BOOLS_CHAR 1050 +#define DS_SHOWSYSTEMTABLES 1051 +#define DRV_EXTRASYSTABLEPREFIXES 1051 +#define DS_ROWVERSIONING 1052 +#define DRV_PARSE 1052 +#define DRV_CANCELASFREESTMT 1053 +#define IDC_OPTIONS 1054 +#define DRV_KSQO 1055 +#define DS_PG64 1057 +#define DS_PG63 1058 +#define DRV_OR_DSN 1059 +#define DRV_DEBUG 1060 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1061 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/interfaces/odbc/results.c b/src/interfaces/odbc/results.c index bb1f2975df..b63a214b81 100644 --- a/src/interfaces/odbc/results.c +++ b/src/interfaces/odbc/results.c @@ -38,7 +38,6 @@ #endif #include "pgapifunc.h" -extern GLOBAL_VALUES globals; RETCODE SQL_API @@ -51,12 +50,14 @@ PGAPI_RowCount( QResultClass *res; char *msg, *ptr; + ConnInfo *ci; if (!stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } + ci = &(SC_get_conn(stmt)->connInfo); if (stmt->manual_result) { if (pcrow) @@ -72,7 +73,7 @@ PGAPI_RowCount( if (res && pcrow) { - *pcrow = globals.use_declarefetch ? -1 : QR_get_num_tuples(res); + *pcrow = ci->drivers.use_declarefetch ? -1 : QR_get_num_tuples(res); return SQL_SUCCESS; } } @@ -119,17 +120,19 @@ PGAPI_NumResultCols( StatementClass *stmt = (StatementClass *) hstmt; QResultClass *result; char parse_ok; + ConnInfo *ci; if (!stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } + ci = &(SC_get_conn(stmt)->connInfo); SC_clear_error(stmt); parse_ok = FALSE; - if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) + if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { @@ -211,7 +214,7 @@ PGAPI_DescribeCol( return SQL_INVALID_HANDLE; } - ci = &(stmt->hdbc->connInfo); + ci = &(SC_get_conn(stmt)->connInfo); SC_clear_error(stmt); @@ -223,7 +226,7 @@ PGAPI_DescribeCol( icol--; /* use zero based column numbers */ parse_ok = FALSE; - if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) + if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { @@ -288,7 +291,7 @@ PGAPI_DescribeCol( fieldtype = QR_get_field_type(res, icol); /* atoi(ci->unknown_sizes) */ - precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); + precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.unknown_sizes); } mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name); @@ -400,7 +403,7 @@ PGAPI_ColAttributes( return SQL_INVALID_HANDLE; } - ci = &(stmt->hdbc->connInfo); + ci = &(SC_get_conn(stmt)->connInfo); /* * Dont check for bookmark column. This is the responsibility of the @@ -411,14 +414,14 @@ PGAPI_ColAttributes( icol--; /* atoi(ci->unknown_sizes); */ - unknown_sizes = globals.unknown_sizes; + unknown_sizes = ci->drivers.unknown_sizes; /* not appropriate for SQLColAttributes() */ if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) unknown_sizes = UNKNOWNS_AS_MAX; parse_ok = FALSE; - if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) + if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { @@ -660,6 +663,7 @@ PGAPI_GetData( void *value = NULL; int result; char get_bookmark = FALSE; + ConnInfo *ci; mylog("PGAPI_GetData: enter, stmt=%u\n", stmt); @@ -668,6 +672,7 @@ PGAPI_GetData( SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } + ci = &(SC_get_conn(stmt)->connInfo); res = stmt->result; if (STMT_EXECUTING == stmt->status) @@ -723,7 +728,7 @@ PGAPI_GetData( } } - if (stmt->manual_result || !globals.use_declarefetch) + if (stmt->manual_result || !ci->drivers.use_declarefetch) { /* make sure we're positioned on a valid row */ num_rows = QR_get_num_tuples(res); @@ -913,6 +918,7 @@ PGAPI_ExtendedFetch( RETCODE result; char truncated, error; + ConnInfo *ci; mylog("PGAPI_ExtendedFetch: stmt=%u\n", stmt); @@ -921,8 +927,9 @@ PGAPI_ExtendedFetch( SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } + ci = &(SC_get_conn(stmt)->connInfo); - if (globals.use_declarefetch && !stmt->manual_result) + if (ci->drivers.use_declarefetch && !stmt->manual_result) { if (fFetchType != SQL_FETCH_NEXT) { @@ -1101,7 +1108,7 @@ PGAPI_ExtendedFetch( * Handle Declare Fetch style specially because the end is not really * the end... */ - if (globals.use_declarefetch && !stmt->manual_result) + if (ci->drivers.use_declarefetch && !stmt->manual_result) { if (QR_end_tuples(res)) return SQL_NO_DATA_FOUND; @@ -1183,7 +1190,7 @@ PGAPI_ExtendedFetch( stmt->currTuple = stmt->rowset_start; /* For declare/fetch, need to reset cursor to beginning of rowset */ - if (globals.use_declarefetch && !stmt->manual_result) + if (ci->drivers.use_declarefetch && !stmt->manual_result) QR_set_position(res, 0); /* Set the number of rows retrieved */ diff --git a/src/interfaces/odbc/setup.c b/src/interfaces/odbc/setup.c index 2a779b417f..65f3423cf1 100644 --- a/src/interfaces/odbc/setup.c +++ b/src/interfaces/odbc/setup.c @@ -27,7 +27,6 @@ #define INTFUNC __stdcall extern HINSTANCE NEAR s_hModule;/* Saved module handle. */ -extern GLOBAL_VALUES globals; /* Constants */ #define MIN(x,y) ((x) < (y) ? (x) : (y)) @@ -218,48 +217,48 @@ ConfigDlgProc(HWND hdlg, WPARAM wParam, LPARAM lParam) { + LPSETUPDLG lpsetupdlg; + ConnInfo *ci; switch (wMsg) { - /* Initialize the dialog */ - case WM_INITDIALOG: + /* Initialize the dialog */ + case WM_INITDIALOG: + lpsetupdlg = (LPSETUPDLG) lParam; + ci = &lpsetupdlg->ci; + + /* Hide the driver connect message */ + ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL), SW_HIDE); + + SetWindowLong(hdlg, DWL_USER, lParam); + CenterDialog(hdlg); /* Center dialog */ + + /* + * NOTE: Values supplied in the attribute string will + * always + */ + /* override settings in ODBC.INI */ + + /* Get the rest of the common attributes */ + getDSNinfo(ci, CONN_DONT_OVERWRITE); + + /* Fill in any defaults */ + getDSNdefaults(ci); + + /* Initialize dialog fields */ + SetDlgStuff(hdlg, ci); + + if (lpsetupdlg->fDefault) { - LPSETUPDLG lpsetupdlg = (LPSETUPDLG) lParam; - ConnInfo *ci = &lpsetupdlg->ci; - - /* Hide the driver connect message */ - ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL), SW_HIDE); - - SetWindowLong(hdlg, DWL_USER, lParam); - CenterDialog(hdlg); /* Center dialog */ - - /* - * NOTE: Values supplied in the attribute string will - * always - */ - /* override settings in ODBC.INI */ - - /* Get the rest of the common attributes */ - getDSNinfo(ci, CONN_DONT_OVERWRITE); - - /* Fill in any defaults */ - getDSNdefaults(ci); - - /* Initialize dialog fields */ - SetDlgStuff(hdlg, ci); - - if (lpsetupdlg->fDefault) - { - EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE); - EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE); - } - else - SendDlgItemMessage(hdlg, IDC_DSNAME, - EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L); - - SendDlgItemMessage(hdlg, IDC_DESC, - EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); - return TRUE; /* Focus was not set */ + EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE); + EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE); } + else + SendDlgItemMessage(hdlg, IDC_DSNAME, + EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L); + + SendDlgItemMessage(hdlg, IDC_DESC, + EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); + return TRUE; /* Focus was not set */ /* Process buttons */ case WM_COMMAND: @@ -286,21 +285,17 @@ ConfigDlgProc(HWND hdlg, /* Accept results */ case IDOK: - { - LPSETUPDLG lpsetupdlg; - - lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); - /* Retrieve dialog values */ - if (!lpsetupdlg->fDefault) - GetDlgItemText(hdlg, IDC_DSNAME, + lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); + /* Retrieve dialog values */ + if (!lpsetupdlg->fDefault) + GetDlgItemText(hdlg, IDC_DSNAME, lpsetupdlg->ci.dsn, sizeof(lpsetupdlg->ci.dsn)); - /* Get Dialog Values */ - GetDlgStuff(hdlg, &lpsetupdlg->ci); + /* Get Dialog Values */ + GetDlgStuff(hdlg, &lpsetupdlg->ci); - /* Update ODBC.INI */ - SetDSNAttributes(hdlg, lpsetupdlg); - } + /* Update ODBC.INI */ + SetDSNAttributes(hdlg, lpsetupdlg); /* Return to caller */ case IDCANCEL: @@ -308,22 +303,18 @@ ConfigDlgProc(HWND hdlg, return TRUE; case IDC_DRIVER: + lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), - hdlg, driver_optionsProc, (LPARAM) NULL); - + hdlg, driver_optionsProc, (LPARAM) &lpsetupdlg->ci); return TRUE; case IDC_DATASOURCE: - { - LPSETUPDLG lpsetupdlg; + lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); - lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); - - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS), + DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS), hdlg, ds_optionsProc, (LPARAM) &lpsetupdlg->ci); - return TRUE; - } + return TRUE; } break; } diff --git a/src/interfaces/odbc/socket.c b/src/interfaces/odbc/socket.c index ed3fd2913c..fbfb5ca929 100644 --- a/src/interfaces/odbc/socket.c +++ b/src/interfaces/odbc/socket.c @@ -13,6 +13,7 @@ */ #include "socket.h" +#include "connection.h" #ifndef WIN32 #include @@ -41,7 +42,7 @@ SOCK_clear_error(SocketClass *self) SocketClass * -SOCK_Constructor() +SOCK_Constructor(const ConnectionClass *conn) { SocketClass *rv; @@ -54,14 +55,18 @@ SOCK_Constructor() rv->buffer_filled_out = 0; rv->buffer_read_in = 0; - rv->buffer_in = (unsigned char *) malloc(globals.socket_buffersize); + if (rv) + rv->buffer_size = conn->connInfo.drivers.socket_buffersize; + else + rv->buffer_size = globals.socket_buffersize; + rv->buffer_in = (unsigned char *) malloc(rv->buffer_size); if (!rv->buffer_in) { free(rv); return NULL; } - rv->buffer_out = (unsigned char *) malloc(globals.socket_buffersize); + rv->buffer_out = (unsigned char *) malloc(rv->buffer_size); if (!rv->buffer_out) { free(rv->buffer_in); @@ -79,6 +84,7 @@ SOCK_Constructor() void SOCK_Destructor(SocketClass *self) { +mylog("SOCK_Destructor\n"); if (self->socket != -1) { SOCK_put_char(self, 'X'); @@ -305,9 +311,9 @@ SOCK_get_next_byte(SocketClass *self) * there are no more bytes left in the buffer so reload the buffer */ self->buffer_read_in = 0; - self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0); + self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, self->buffer_size, 0); - mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize); + mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size); if (self->buffer_filled_in < 0) { @@ -335,11 +341,11 @@ SOCK_put_next_byte(SocketClass *self, unsigned char next_byte) self->buffer_out[self->buffer_filled_out++] = next_byte; - if (self->buffer_filled_out == globals.socket_buffersize) + if (self->buffer_filled_out == self->buffer_size) { /* buffer is full, so write it out */ - bytes_sent = send(self->socket, (char *) self->buffer_out, globals.socket_buffersize, 0); - if (bytes_sent != globals.socket_buffersize) + bytes_sent = send(self->socket, (char *) self->buffer_out, self->buffer_size, 0); + if (bytes_sent != self->buffer_size) { self->errornumber = SOCKET_WRITE_ERROR; self->errormsg = "Error while writing to the socket."; diff --git a/src/interfaces/odbc/socket.h b/src/interfaces/odbc/socket.h index b24be9504d..f4c7b9e4e4 100644 --- a/src/interfaces/odbc/socket.h +++ b/src/interfaces/odbc/socket.h @@ -53,6 +53,7 @@ typedef unsigned int in_addr_t; struct SocketClass_ { + int buffer_size; int buffer_filled_in; int buffer_filled_out; int buffer_read_in; @@ -79,7 +80,7 @@ struct SocketClass_ /* Socket prototypes */ -SocketClass *SOCK_Constructor(void); +SocketClass *SOCK_Constructor(const ConnectionClass *conn); void SOCK_Destructor(SocketClass *self); char SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname); void SOCK_get_n_char(SocketClass *self, char *buffer, int len); diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c index 891f47df83..bb4fab9bcc 100644 --- a/src/interfaces/odbc/statement.c +++ b/src/interfaces/odbc/statement.c @@ -32,7 +32,6 @@ #endif #include "pgapifunc.h" -extern GLOBAL_VALUES globals; #ifndef WIN32 #ifndef HAVE_STRICMP @@ -291,6 +290,7 @@ SC_Constructor(void) rv->pre_executing = FALSE; rv->inaccurate_result = FALSE; + rv->miscinfo = 0; } return rv; } @@ -560,6 +560,7 @@ SC_pre_execute(StatementClass *self) { mylog(" preprocess: status = READY\n"); + self->miscinfo = 0; if (self->statement_type == STMT_TYPE_SELECT) { char old_pre_executing = self->pre_executing; @@ -577,7 +578,7 @@ SC_pre_execute(StatementClass *self) self->status = STMT_PREMATURE; } } - else + if (!SC_is_pre_executable(self)) { self->result = QR_Constructor(); QR_set_status(self->result, PGRES_TUPLES_OK); @@ -718,15 +719,16 @@ SC_fetch(StatementClass *self) lf; Oid type; char *value; - ColumnInfoClass *ci; + ColumnInfoClass *coli; /* TupleField *tupleField; */ + ConnInfo *ci = &(SC_get_conn(self)->connInfo); self->last_fetch_count = 0; - ci = QR_get_fields(res); /* the column info */ + coli = QR_get_fields(res); /* the column info */ - mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, globals.use_declarefetch); + mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, ci->drivers.use_declarefetch); - if (self->manual_result || !globals.use_declarefetch) + if (self->manual_result || !ci->drivers.use_declarefetch) { if (self->currTuple >= QR_get_num_tuples(res) - 1 || (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) @@ -807,7 +809,7 @@ SC_fetch(StatementClass *self) /* this column has a binding */ /* type = QR_get_field_type(res, lf); */ - type = CI_get_oid(ci, lf); /* speed things up */ + type = CI_get_oid(coli, lf); /* speed things up */ mylog("type = %d\n", type); @@ -816,7 +818,7 @@ SC_fetch(StatementClass *self) value = QR_get_value_manual(res, self->currTuple, lf); mylog("manual_result\n"); } - else if (globals.use_declarefetch) + else if (ci->drivers.use_declarefetch) value = QR_get_value_backend(res, lf); else value = QR_get_value_backend_row(res, self->currTuple, lf); @@ -895,9 +897,11 @@ SC_execute(StatementClass *self) Int2 oldstatus, numcols; QueryInfo qi; + ConnInfo *ci; conn = SC_get_conn(self); + ci = &(conn->connInfo); /* Begin a transaction if one is not already in progress */ @@ -910,7 +914,8 @@ SC_execute(StatementClass *self) * OTHER. */ if (!self->internal && !CC_is_in_trans(conn) && - ((globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER))) + ((ci->drivers.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || + (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER))) { mylog(" about to begin a transaction on statement = %u\n", self); res = CC_send_query(conn, "BEGIN", NULL); @@ -959,7 +964,7 @@ SC_execute(StatementClass *self) /* send the declare/select */ self->result = CC_send_query(conn, self->stmt_with_params, NULL); - if (globals.use_declarefetch && self->result != NULL && + if (ci->drivers.use_declarefetch && self->result != NULL && QR_command_successful(self->result)) { QR_Destructor(self->result); @@ -970,7 +975,7 @@ SC_execute(StatementClass *self) */ qi.result_in = NULL; qi.cursor = self->cursor_name; - qi.row_size = globals.fetch_max; + qi.row_size = ci->drivers.fetch_max; /* * Most likely the rowset size will not be set by the @@ -1075,21 +1080,21 @@ SC_execute(StatementClass *self) (self->errornumber == STMT_OK || self->errornumber == STMT_INFO_ONLY) && self->parameters && - self->parameters[0].buflen > 0 && + self->parameters[0].buffer && self->parameters[0].paramType == SQL_PARAM_OUTPUT) { /* get the return value of the procedure call */ RETCODE ret; HSTMT hstmt = (HSTMT) self; - ret = PGAPI_BindCol(hstmt, 1, self->parameters[0].CType, self->parameters[0].buffer, self->parameters[0].buflen, self->parameters[0].used); - if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) - SC_fetch(hstmt); - else - { - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "BindCol to Procedure return failed."; + ret = SC_fetch(hstmt); + if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) + { + ret = PGAPI_GetData(hstmt, 1, self->parameters[0].CType, self->parameters[0].buffer, self->parameters[0].buflen, self->parameters[0].used); + if (ret != SQL_SUCCESS) + { + self->errornumber = STMT_EXEC_ERROR; + self->errormsg = "GetData to Procedure return failed."; + } } - if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) - PGAPI_BindCol(hstmt, 1, self->parameters[0].CType, NULL, 0, NULL); else { self->errornumber = STMT_EXEC_ERROR; diff --git a/src/interfaces/odbc/statement.h b/src/interfaces/odbc/statement.h index 571d13edac..95ae1437a1 100644 --- a/src/interfaces/odbc/statement.h +++ b/src/interfaces/odbc/statement.h @@ -216,10 +216,10 @@ struct StatementClass_ int stmt_size_limit; char pre_executing; /* This statement is prematurely executing */ - char inaccurate_result; /* Current status is PREMATURE but - * result is inaccurate */ - char errormsg_malloced; /* Current status is PREMATURE but + char inaccurate_result; /* Current status is PREMATURE but * result is inaccurate */ + char errormsg_malloced; /* Current error message is malloed (not in a static variable) ? */ + char miscinfo; }; #define SC_get_conn(a) (a->hdbc) @@ -229,6 +229,14 @@ struct StatementClass_ #define STMT_FREE_PARAMS_ALL 0 #define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1 +/* misc info */ +#define SC_set_pre_executable(a) (a->miscinfo |= 1L) +#define SC_no_pre_executable(a) (a->miscinfo &= ~1L) +#define SC_is_pre_executable(a) (a->miscinfo & 1L != 0) +#define SC_set_fetchcursor(a) (a->miscinfo |= 2L) +#define SC_no_fetchcursor(a) (a->miscinfo &= ~2L) +#define SC_is_fetchcursor(a) (a->miscinfo & 2L != 0) + /* Statement prototypes */ StatementClass *SC_Constructor(void); void InitializeStatementOptions(StatementOptions *opt);