Index: src/interfaces/odbc/bind.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/bind.c,v retrieving revision 1.23 diff -c -r1.23 bind.c *** src/interfaces/odbc/bind.c 2001/03/27 04:00:53 1.23 --- src/interfaces/odbc/bind.c 2001/03/28 16:53:12 *************** *** 1,4 **** ! /* Module: bind.c * * Description: This module contains routines related to binding * columns and parameters. --- 1,5 ---- ! /*------- ! * Module: bind.c * * Description: This module contains routines related to binding * columns and parameters. *************** *** 9,15 **** * SQLParamOptions(NI) * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 10,16 ---- * SQLParamOptions(NI) * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #ifdef HAVE_CONFIG_H *************** *** 112,119 **** } } ! ipar--; /* use zero based column numbers for the ! * below part */ /* store the given info */ stmt->parameters[ipar].buflen = cbValueMax; --- 113,120 ---- } } ! /* use zero based column numbers for the below part */ ! ipar--; /* store the given info */ stmt->parameters[ipar].buflen = cbValueMax; *************** *** 152,161 **** return SQL_SUCCESS; } - - /* - - - - - - - - - */ ! /* Associate a user-supplied buffer with a database column. */ RETCODE SQL_API SQLBindCol( HSTMT hstmt, --- 153,160 ---- return SQL_SUCCESS; } ! /* Associate a user-supplied buffer with a database column. */ RETCODE SQL_API SQLBindCol( HSTMT hstmt, *************** *** 192,198 **** /* If the bookmark column is being bound, then just save it */ if (icol == 0) { - if (rgbValue == NULL) { stmt->bookmark.buffer = NULL; --- 191,196 ---- *************** *** 215,224 **** return SQL_SUCCESS; } ! /* allocate enough bindings if not already done */ ! /* Most likely, execution of a statement would have setup the */ ! /* necessary bindings. But some apps call BindCol before any */ ! /* statement is executed. */ if (icol > stmt->bindings_allocated) extend_bindings(stmt, icol); --- 213,224 ---- return SQL_SUCCESS; } ! /* ! * Allocate enough bindings if not already done. ! * Most likely, execution of a statement would have setup the ! * necessary bindings. But some apps call BindCol before any ! * statement is executed. ! */ if (icol > stmt->bindings_allocated) extend_bindings(stmt, icol); *************** *** 231,238 **** return SQL_ERROR; } ! icol--; /* use zero based col numbers from here ! * out */ /* Reset for SQLGetData */ stmt->bindings[icol].data_left = -1; --- 231,238 ---- return SQL_ERROR; } ! /* use zero based col numbers from here out */ ! icol--; /* Reset for SQLGetData */ stmt->bindings[icol].data_left = -1; *************** *** 259,272 **** return SQL_SUCCESS; } - /* - - - - - - - - - */ ! /* Returns the description of a parameter marker. */ ! /* This function is listed as not being supported by SQLGetFunctions() because it is */ ! /* used to describe "parameter markers" (not bound parameters), in which case, */ ! /* the dbms should return info on the markers. Since Postgres doesn't support that, */ ! /* it is best to say this function is not supported and let the application assume a */ ! /* data type (most likely varchar). */ RETCODE SQL_API SQLDescribeParam( --- 259,273 ---- return SQL_SUCCESS; } ! /* ! * Returns the description of a parameter marker. ! * This function is listed as not being supported by SQLGetFunctions() because it is ! * used to describe "parameter markers" (not bound parameters), in which case, ! * the dbms should return info on the markers. Since Postgres doesn't support that, ! * it is best to say this function is not supported and let the application assume a ! * data type (most likely varchar). ! */ RETCODE SQL_API SQLDescribeParam( *************** *** 318,327 **** return SQL_SUCCESS; } ! /* - - - - - - - - - */ - /* Sets multiple values (arrays) for the set of parameter markers. */ - RETCODE SQL_API SQLParamOptions( HSTMT hstmt, --- 319,326 ---- return SQL_SUCCESS; } ! /* Sets multiple values (arrays) for the set of parameter markers. */ RETCODE SQL_API SQLParamOptions( HSTMT hstmt, *************** *** 336,350 **** return SQL_ERROR; } - /* - - - - - - - - - */ ! /* This function should really talk to the dbms to determine the number of */ ! /* "parameter markers" (not bound parameters) in the statement. But, since */ ! /* Postgres doesn't support that, the driver should just count the number of markers */ ! /* and return that. The reason the driver just can't say this function is unsupported */ ! /* like it does for SQLDescribeParam is that some applications don't care and try */ ! /* to call it anyway. */ ! /* If the statement does not have parameters, it should just return 0. */ RETCODE SQL_API SQLNumParams( HSTMT hstmt, --- 335,350 ---- return SQL_ERROR; } ! /* ! * This function should really talk to the dbms to determine the number of ! * "parameter markers" (not bound parameters) in the statement. But, since ! * Postgres doesn't support that, the driver should just count the number of markers ! * and return that. The reason the driver just can't say this function is unsupported ! * like it does for SQLDescribeParam is that some applications don't care and try ! * to call it anyway. ! * If the statement does not have parameters, it should just return 0. ! */ RETCODE SQL_API SQLNumParams( HSTMT hstmt, *************** *** 382,391 **** } else { - for (i = 0; i < strlen(stmt->statement); i++) { - if (stmt->statement[i] == '?' && !in_quote) (*pcpar)++; else --- 382,389 ---- *************** *** 394,405 **** in_quote = (in_quote ? FALSE : TRUE); } } - return SQL_SUCCESS; } } ! /******************************************************************** * Bindings Implementation */ BindInfoClass * --- 392,402 ---- in_quote = (in_quote ? FALSE : TRUE); } } return SQL_SUCCESS; } } ! /* * Bindings Implementation */ BindInfoClass * *************** *** 432,442 **** mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns); ! /* if we have too few, allocate room for more, and copy the old */ ! /* entries into the new structure */ if (stmt->bindings_allocated < num_columns) { - new_bindings = create_empty_bindings(num_columns); if (!new_bindings) { --- 429,440 ---- mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns); ! /* ! * if we have too few, allocate room for more, and copy the old ! * entries into the new structure ! */ if (stmt->bindings_allocated < num_columns) { new_bindings = create_empty_bindings(num_columns); if (!new_bindings) { *************** *** 461,471 **** stmt->bindings = new_bindings; stmt->bindings_allocated = num_columns; - } ! /* There is no reason to zero out extra bindings if there are */ ! /* more than needed. If an app has allocated extra bindings, */ ! /* let it worry about it by unbinding those columns. */ /* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */ /* SQLExecDirect(...) # returns 5 cols */ --- 459,470 ---- stmt->bindings = new_bindings; stmt->bindings_allocated = num_columns; } ! /* ! * There is no reason to zero out extra bindings if there are ! * more than needed. If an app has allocated extra bindings, ! * let it worry about it by unbinding those columns. ! */ /* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */ /* SQLExecDirect(...) # returns 5 cols */ Index: src/interfaces/odbc/columninfo.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/columninfo.c,v retrieving revision 1.18 diff -c -r1.18 columninfo.c *** src/interfaces/odbc/columninfo.c 2001/03/27 04:00:53 1.18 --- src/interfaces/odbc/columninfo.c 2001/03/28 16:53:12 *************** *** 1,4 **** ! /* Module: columninfo.c * * Description: This module contains routines related to * reading and storing the field information from a query. --- 1,5 ---- ! /*------- ! * Module: columninfo.c * * Description: This module contains routines related to * reading and storing the field information from a query. *************** *** 8,14 **** * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #include "columninfo.h" --- 9,15 ---- * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #include "columninfo.h" *************** *** 45,54 **** free(self); } ! /* Read in field descriptions. ! If self is not null, then also store the information. ! If self is null, then just read, don't store. ! */ char CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn) { --- 46,56 ---- free(self); } ! /* ! * Read in field descriptions. ! * If self is not null, then also store the information. ! * If self is null, then just read, don't store. ! */ char CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn) { *************** *** 77,83 **** /* now read in the descriptions */ for (lf = 0; lf < new_num_fields; lf++) { - SOCK_get_string(sock, new_field_name, MAX_MESSAGE_LEN); new_adtid = (Oid) SOCK_get_int(sock, 4); new_adtsize = (Int2) SOCK_get_int(sock, 2); --- 79,84 ---- *************** *** 85,91 **** /* If 6.4 protocol, then read the atttypmod field */ if (PG_VERSION_GE(conn, 6.4)) { - mylog("READING ATTTYPMOD\n"); new_atttypmod = (Int4) SOCK_get_int(sock, 4); --- 86,91 ---- *************** *** 106,112 **** } - void CI_free_memory(ColumnInfoClass *self) { --- 106,111 ---- *************** *** 146,152 **** CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod) { - /* check bounds */ if ((field_num < 0) || (field_num >= self->num_fields)) return; --- 145,150 ---- Index: src/interfaces/odbc/connection.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/connection.c,v retrieving revision 1.27 diff -c -r1.27 connection.c *** src/interfaces/odbc/connection.c 2001/03/27 04:00:53 1.27 --- src/interfaces/odbc/connection.c 2001/03/28 16:53:13 *************** *** 1,4 **** ! /* Module: connection.c * * Description: This module contains routines related to * connecting to and disconnecting from the Postgres DBMS. --- 1,5 ---- ! /*------ ! * Module: connection.c * * Description: This module contains routines related to * connecting to and disconnecting from the Postgres DBMS. *************** *** 9,15 **** * SQLBrowseConnect(NI) * * Comments: See "notice.txt" for copyright and license information. ! * */ /* Multibyte support Eiji Tokuya 2001-03-15 */ --- 10,16 ---- * SQLBrowseConnect(NI) * * Comments: See "notice.txt" for copyright and license information. ! *------- */ /* Multibyte support Eiji Tokuya 2001-03-15 */ *************** *** 83,90 **** } - /* - - - - - - - - - */ - RETCODE SQL_API SQLConnect( HDBC hdbc, --- 84,89 ---- *************** *** 140,146 **** return SQL_SUCCESS; } - /* - - - - - - - - - */ RETCODE SQL_API SQLBrowseConnect( --- 139,144 ---- *************** *** 158,164 **** return SQL_SUCCESS; } - /* - - - - - - - - - */ /* Drop any hstmts open on hdbc and disconnect from database */ RETCODE SQL_API --- 156,161 ---- *************** *** 199,206 **** } - /* - - - - - - - - - */ - RETCODE SQL_API SQLFreeConnect( HDBC hdbc) --- 196,201 ---- *************** *** 235,244 **** /* ! * ! * IMPLEMENTATION CONNECTION CLASS ! * ! */ ConnectionClass * CC_Constructor() --- 230,237 ---- /* ! * IMPLEMENTATION CONNECTION CLASS ! */ ConnectionClass * CC_Constructor() *************** *** 249,255 **** if (rv != NULL) { - rv->henv = NULL; /* not yet associated with an environment */ rv->errormsg = NULL; --- 242,247 ---- *************** *** 301,307 **** char CC_Destructor(ConnectionClass *self) { - mylog("enter CC_Destructor, self=%u\n", self); if (self->status == CONN_EXECUTING) --- 293,298 ---- *************** *** 373,380 **** self->errormsg_created = FALSE; } ! /* Used to cancel a transaction */ ! /* We are almost always in the middle of a transaction. */ char CC_abort(ConnectionClass *self) { --- 364,373 ---- self->errormsg_created = FALSE; } ! /* ! * Used to cancel a transaction. ! * We are almost always in the middle of a transaction. ! */ char CC_abort(ConnectionClass *self) { *************** *** 434,440 **** stmt = self->stmts[i]; if (stmt) { - stmt->hdbc = NULL; /* prevent any more dbase interactions */ SC_Destructor(stmt); --- 427,432 ---- *************** *** 521,527 **** else { - 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, --- 513,518 ---- *************** *** 646,659 **** mylog("gonna do authentication\n"); ! /* *************************************************** */ ! /* Now get the authentication request from backend */ ! /* *************************************************** */ if (!PROTOCOL_62(ci)) do { - if (do_password) beresp = 'R'; else --- 637,649 ---- mylog("gonna do authentication\n"); ! /* ! * Now get the authentication request from backend ! */ if (!PROTOCOL_62(ci)) do { if (do_password) beresp = 'R'; else *************** *** 743,750 **** CC_clear_error(self); /* clear any password error */ ! /* send an empty query in order to find out whether the specified */ ! /* database really exists on the server machine */ mylog("sending an empty query...\n"); res = CC_send_query(self, " ", NULL); --- 733,742 ---- CC_clear_error(self); /* clear any password error */ ! /* ! * send an empty query in order to find out whether the specified ! * database really exists on the server machine ! */ mylog("sending an empty query...\n"); res = CC_send_query(self, " ", NULL); *************** *** 764,772 **** CC_set_translation(self); ! /**********************************************/ ! /******* Send any initial settings *********/ ! /**********************************************/ /* * Since these functions allocate statements, and since the connection --- 756,764 ---- CC_set_translation(self); ! /* ! * Send any initial settings ! */ /* * Since these functions allocate statements, and since the connection *************** *** 838,846 **** return FALSE; } ! /* Create a more informative error message by concatenating the connection ! error message with its socket error message. ! */ char * CC_create_errormsg(ConnectionClass *self) { --- 830,839 ---- return FALSE; } ! /* ! * Create a more informative error message by concatenating the connection ! * error message with its socket error message. ! */ char * CC_create_errormsg(ConnectionClass *self) { *************** *** 897,910 **** } ! /* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into ! the same existing QResultClass (this occurs when the tuple cache is depleted and ! needs to be re-filled). ! ! The "cursor" is used by SQLExecute to associate a statement handle as the cursor name ! (i.e., C3326857) for SQL select statements. This cursor is then used in future ! 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements. ! */ QResultClass * CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) { --- 890,904 ---- } ! /* ! * The "result_in" is only used by QR_next_tuple() to fetch another group of rows into ! * the same existing QResultClass (this occurs when the tuple cache is depleted and ! * needs to be re-filled). ! * ! * The "cursor" is used by SQLExecute to associate a statement handle as the cursor name ! * (i.e., C3326857) for SQL select statements. This cursor is then used in future ! * 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements. ! */ QResultClass * CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) { *************** *** 914,923 **** int id; SocketClass *sock = self->sock; static char msgbuffer[MAX_MESSAGE_LEN + 1]; ! char cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups ! * this string so dont ! * need static */ ! mylog("send_query(): conn=%u, query='%s'\n", self, query); qlog("conn=%u, query='%s'\n", self, query); --- 908,915 ---- int id; SocketClass *sock = self->sock; static char msgbuffer[MAX_MESSAGE_LEN + 1]; ! /* QR_set_command() dups this string so don't need static */ ! char cmdbuffer[MAX_MESSAGE_LEN + 1]; mylog("send_query(): conn=%u, query='%s'\n", self, query); qlog("conn=%u, query='%s'\n", self, query); *************** *** 1003,1009 **** } else { - char clear = 0; mylog("send_query: ok - 'C' - %s\n", cmdbuffer); --- 995,1000 ---- *************** *** 1239,1245 **** for (i = 0; i < nargs; ++i) { - mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr); SOCK_put_int(sock, args[i].len, 4); --- 1230,1235 ---- *************** *** 1371,1379 **** mylog("%s: entering...\n", func); ! /* This function must use the local odbc API functions since the odbc state ! has not transitioned to "connected" yet. ! */ result = SQLAllocStmt(self, &hstmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) --- 1361,1370 ---- mylog("%s: entering...\n", func); ! /* ! * This function must use the local odbc API functions since the odbc state ! * has not transitioned to "connected" yet. ! */ result = SQLAllocStmt(self, &hstmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) *************** *** 1455,1464 **** return status; } ! /* This function is just a hack to get the oid of our Large Object oid type. ! If a real Large Object oid type is made part of Postgres, this function ! will go away and the define 'PG_TYPE_LO' will be updated. ! */ void CC_lookup_lo(ConnectionClass *self) { --- 1446,1456 ---- return status; } ! /* ! * This function is just a hack to get the oid of our Large Object oid type. ! * If a real Large Object oid type is made part of Postgres, this function ! * will go away and the define 'PG_TYPE_LO' will be updated. ! */ void CC_lookup_lo(ConnectionClass *self) { *************** *** 1469,1477 **** mylog("%s: entering...\n", func); ! /* This function must use the local odbc API functions since the odbc state ! has not transitioned to "connected" yet. ! */ result = SQLAllocStmt(self, &hstmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) return; --- 1461,1470 ---- mylog("%s: entering...\n", func); ! /* ! * This function must use the local odbc API functions since the odbc state ! * has not transitioned to "connected" yet. ! */ result = SQLAllocStmt(self, &hstmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) return; *************** *** 1504,1513 **** result = SQLFreeStmt(hstmt, SQL_DROP); } ! /* This function initializes the version of PostgreSQL from ! connInfo.protocol that we're connected to. ! h-inoue 01-2-2001 ! */ void CC_initialize_pg_version(ConnectionClass *self) { --- 1497,1507 ---- result = SQLFreeStmt(hstmt, SQL_DROP); } ! /* ! * This function initializes the version of PostgreSQL from ! * connInfo.protocol that we're connected to. ! * h-inoue 01-2-2001 ! */ void CC_initialize_pg_version(ConnectionClass *self) { *************** *** 1532,1541 **** } } ! /* This function gets the version of PostgreSQL that we're connected to. ! This is used to return the correct info in SQLGetInfo ! DJP - 25-1-2001 ! */ void CC_lookup_pg_version(ConnectionClass *self) { --- 1526,1536 ---- } } ! /* ! * This function gets the version of PostgreSQL that we're connected to. ! * This is used to return the correct info in SQLGetInfo ! * DJP - 25-1-2001 ! */ void CC_lookup_pg_version(ConnectionClass *self) { *************** *** 1549,1557 **** mylog("%s: entering...\n", func); ! /* This function must use the local odbc API functions since the odbc state ! has not transitioned to "connected" yet. ! */ result = SQLAllocStmt(self, &hstmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) return; --- 1544,1553 ---- mylog("%s: entering...\n", func); ! /* ! * This function must use the local odbc API functions since the odbc state ! * has not transitioned to "connected" yet. ! */ result = SQLAllocStmt(self, &hstmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) return; *************** *** 1579,1586 **** return; } ! /* Extract the Major and Minor numbers from the string. */ ! /* This assumes the string starts 'Postgresql X.X' */ strcpy(szVersion, "0.0"); if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2) { --- 1575,1584 ---- return; } ! /* ! * Extract the Major and Minor numbers from the string. ! * This assumes the string starts 'Postgresql X.X' ! */ strcpy(szVersion, "0.0"); if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2) { Index: src/interfaces/odbc/convert.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/convert.c,v retrieving revision 1.35 diff -c -r1.35 convert.c *** src/interfaces/odbc/convert.c 2001/03/27 04:00:53 1.35 --- src/interfaces/odbc/convert.c 2001/03/28 16:53:14 *************** *** 1,4 **** ! /* Module: convert.c * * Description: This module contains routines related to * converting parameters and columns into requested data types. --- 1,5 ---- ! /*------- ! * Module: convert.c * * Description: This module contains routines related to * converting parameters and columns into requested data types. *************** *** 12,18 **** * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ /* Multibyte support Eiji Tokuya 2001-03-15 */ --- 13,19 ---- * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *------- */ /* Multibyte support Eiji Tokuya 2001-03-15 */ *************** *** 63,73 **** extern GLOBAL_VALUES globals; ! /* How to map ODBC scalar functions {fn func(args)} to Postgres ! * This is just a simple substitution ! * List augmented from ! * http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm ! * - thomas 2000-04-03 */ char *mapFuncs[][2] = { /* { "ASCII", "ascii" }, */ --- 64,74 ---- extern GLOBAL_VALUES globals; ! /* ! * How to map ODBC scalar functions {fn func(args)} to Postgres. ! * This is just a simple substitution. List augmented from: ! * http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm ! * - thomas 2000-04-03 */ char *mapFuncs[][2] = { /* { "ASCII", "ascii" }, */ *************** *** 140,160 **** unsigned int conv_from_hex(unsigned char *s); char *conv_to_octal(unsigned char val); ! /******** A Guide for date/time/timestamp conversions ************** - field_type fCType Output - ---------- ------ ---------- - PG_TYPE_DATE SQL_C_DEFAULT SQL_C_DATE - PG_TYPE_DATE SQL_C_DATE SQL_C_DATE - PG_TYPE_DATE SQL_C_TIMESTAMP SQL_C_TIMESTAMP (time = 0 (midnight)) - PG_TYPE_TIME SQL_C_DEFAULT SQL_C_TIME - PG_TYPE_TIME SQL_C_TIME SQL_C_TIME - PG_TYPE_TIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP (date = current date) - PG_TYPE_ABSTIME SQL_C_DEFAULT SQL_C_TIMESTAMP - PG_TYPE_ABSTIME SQL_C_DATE SQL_C_DATE (time is truncated) - PG_TYPE_ABSTIME SQL_C_TIME SQL_C_TIME (date is truncated) - PG_TYPE_ABSTIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP - ******************************************************************************/ /* This is called by SQLFetch() */ --- 141,164 ---- unsigned int conv_from_hex(unsigned char *s); char *conv_to_octal(unsigned char val); ! /*--------- ! * A Guide for date/time/timestamp conversions ! * ! * field_type fCType Output ! * ---------- ------ ---------- ! * PG_TYPE_DATE SQL_C_DEFAULT SQL_C_DATE ! * PG_TYPE_DATE SQL_C_DATE SQL_C_DATE ! * PG_TYPE_DATE SQL_C_TIMESTAMP SQL_C_TIMESTAMP (time = 0 (midnight)) ! * PG_TYPE_TIME SQL_C_DEFAULT SQL_C_TIME ! * PG_TYPE_TIME SQL_C_TIME SQL_C_TIME ! * PG_TYPE_TIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP (date = current date) ! * PG_TYPE_ABSTIME SQL_C_DEFAULT SQL_C_TIMESTAMP ! * PG_TYPE_ABSTIME SQL_C_DATE SQL_C_DATE (time is truncated) ! * PG_TYPE_ABSTIME SQL_C_TIME SQL_C_TIME (date is truncated) ! * PG_TYPE_ABSTIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP ! *--------- ! */ /* This is called by SQLFetch() */ *************** *** 186,202 **** int result = COPY_OK; char tempBuf[TEXT_FIELD_SIZE + 5]; ! /* rgbValueOffset is *ONLY* for character and binary data */ ! /* pcbValueOffset is for computing any pcbValue location */ if (bind_size > 0) { - pcbValueOffset = rgbValueOffset = (bind_size * bind_row); } else { - pcbValueOffset = bind_row * sizeof(SDWORD); rgbValueOffset = bind_row * cbValueMax; --- 190,207 ---- int result = COPY_OK; char tempBuf[TEXT_FIELD_SIZE + 5]; ! /*--------- ! * rgbValueOffset is *ONLY* for character and binary data. ! * pcbValueOffset is for computing any pcbValue location ! *--------- ! */ if (bind_size > 0) { pcbValueOffset = rgbValueOffset = (bind_size * bind_row); } else { pcbValueOffset = bind_row * sizeof(SDWORD); rgbValueOffset = bind_row * cbValueMax; *************** *** 214,227 **** if (!value) { ! /* handle a null just by returning SQL_NULL_DATA in pcbValue, */ ! /* and doing nothing to the buffer. */ if (pcbValue) *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA; return COPY_OK; } - if (stmt->hdbc->DataSourceToDriver != NULL) { int length = strlen(value); --- 219,233 ---- if (!value) { ! /* ! * handle a null just by returning SQL_NULL_DATA in pcbValue, ! * and doing nothing to the buffer. ! */ if (pcbValue) *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA; return COPY_OK; } if (stmt->hdbc->DataSourceToDriver != NULL) { int length = strlen(value); *************** *** 233,253 **** NULL, 0, NULL); } ! ! /******************************************************************** ! First convert any specific postgres types into more ! useable data. ! ! NOTE: Conversions from PG char/varchar of a date/time/timestamp ! value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported ! *********************************************************************/ switch (field_type) { ! ! /* ! * $$$ need to add parsing for date/time/timestamp strings in ! * PG_TYPE_CHAR,VARCHAR $$$ ! */ case PG_TYPE_DATE: sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d); break; --- 239,257 ---- NULL, 0, NULL); } ! /* ! * First convert any specific postgres types into more ! * useable data. ! * ! * NOTE: Conversions from PG char/varchar of a date/time/timestamp ! * value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported ! */ switch (field_type) { ! /* ! * $$$ need to add parsing for date/time/timestamp strings in ! * PG_TYPE_CHAR,VARCHAR $$$ ! */ case PG_TYPE_DATE: sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d); break; *************** *** 260,272 **** case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: if (strnicmp(value, "invalid", 7) != 0) - { sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss); - - } else ! { /* The timestamp is invalid so set ! * something conspicuous, like the epoch */ t = 0; tim = localtime(&t); st.m = tim->tm_mon + 1; --- 264,276 ---- case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: if (strnicmp(value, "invalid", 7) != 0) sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss); else ! { ! /* ! * The timestamp is invalid so set ! * something conspicuous, like the epoch ! */ t = 0; tim = localtime(&t); st.m = tim->tm_mon + 1; *************** *** 289,295 **** } break; ! /* This is for internal use by SQLStatistics() */ case PG_TYPE_INT2VECTOR: { int nval, --- 293,299 ---- } break; ! /* This is for internal use by SQLStatistics() */ case PG_TYPE_INT2VECTOR: { int nval, *************** *** 368,382 **** mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType); } - rgbValueBindRow = (char *) rgbValue + rgbValueOffset; if (fCType == SQL_C_CHAR) { - - /* Special character formatting as required */ - /* * These really should return error if cbValueMax is not big * enough. --- 372,382 ---- *************** *** 455,461 **** if (cbValueMax > 0) { - copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len; /* Copy the data */ --- 455,460 ---- *************** *** 482,488 **** } else { - /* * for SQL_C_CHAR, it's probably ok to leave currency symbols in. * But to convert to numeric types, it is necessary to get rid of --- 481,486 ---- *************** *** 632,638 **** if (stmt->current_col >= 0) { - /* No more data left for this column */ if (stmt->bindings[stmt->current_col].data_left == 0) return COPY_NO_DATA_FOUND; --- 630,635 ---- *************** *** 689,698 **** } ! /* This function inserts parameters into an SQL statements. ! It will also modify a SELECT statement for use with declare/fetch cursors. ! This function no longer does any dynamic memory allocation! ! */ int copy_statement_with_parameters(StatementClass *stmt) { --- 686,696 ---- } ! /* ! * This function inserts parameters into an SQL statements. ! * It will also modify a SELECT statement for use with declare/fetch cursors. ! * This function no longer does any dynamic memory allocation! ! */ int copy_statement_with_parameters(StatementClass *stmt) { *************** *** 759,765 **** for (opos = 0; opos < oldstmtlen; opos++) { - /* Squeeze carriage-return/linefeed pairs to linefeed only */ if (old_statement[opos] == '\r' && opos + 1 < oldstmtlen && old_statement[opos + 1] == '\n') --- 757,762 ---- *************** *** 781,790 **** #ifdef MULTIBYTE char *end = multibyte_strchr(begin, '}'); - #else char *end = strchr(begin, '}'); - #endif if (!end) --- 778,785 ---- *************** *** 806,817 **** } opos += end - begin + 1; - *end = '}'; - continue; } - /* * Can you have parameter markers inside of quotes? I dont think * so. All the queries I've seen expect the driver to put quotes --- 801,809 ---- *************** *** 827,839 **** new_statement[npos++] = old_statement[opos]; continue; } - - ! /****************************************************/ ! /* Its a '?' parameter alright */ ! /****************************************************/ ! param_number++; if (param_number >= stmt->parameters_allocated) --- 819,828 ---- new_statement[npos++] = old_statement[opos]; continue; } ! /* ! * Its a '?' parameter alright ! */ param_number++; if (param_number >= stmt->parameters_allocated) *************** *** 882,888 **** param_string[0] = '\0'; cbuf[0] = '\0'; - /* Convert input C type to a neutral format */ switch (param_ctype) { --- 871,876 ---- *************** *** 1089,1101 **** if (stmt->parameters[param_number].data_at_exec) { - lobj_oid = stmt->parameters[param_number].lobj_oid; - } else { - /* begin transaction if needed */ if (!CC_is_in_trans(stmt->hdbc)) { --- 1077,1086 ---- *************** *** 1240,1254 **** new_statement[npos++] = '\''; /* Close Quote */ break; - } - } /* end, for */ /* make sure new_statement is always null-terminated */ new_statement[npos] = '\0'; - if (stmt->hdbc->DriverToDataSource != NULL) { int length = strlen(new_statement); --- 1225,1236 ---- *************** *** 1260,1266 **** NULL, 0, NULL); } - return SQL_SUCCESS; } --- 1242,1247 ---- *************** *** 1276,1282 **** return NULL; } ! /* convert_escape() * This function returns a pointer to static memory! */ char * --- 1257,1265 ---- return NULL; } ! /* ! * convert_escape() ! * * This function returns a pointer to static memory! */ char * *************** *** 1305,1311 **** } else if (strcmp(key, "fn") == 0) { - /* * Function invocation Separate off the func name, skipping * trailing whitespace. --- 1288,1293 ---- *************** *** 1356,1362 **** } return escape; - } --- 1338,1343 ---- *************** *** 1381,1388 **** ! /* This function parses a character string for date/time info and fills in SIMPLE_TIME */ ! /* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value */ char parse_datetime(char *buf, SIMPLE_TIME *st) { --- 1362,1371 ---- ! /* ! * This function parses a character string for date/time info and fills in SIMPLE_TIME ! * It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value ! */ char parse_datetime(char *buf, SIMPLE_TIME *st) { *************** *** 1468,1476 **** return out; } ! /* Change carriage-return/linefeed to just linefeed ! Plus, escape any special characters. ! */ char * convert_special_chars(char *si, char *dst, int used) { --- 1451,1460 ---- return out; } ! /* ! * Change carriage-return/linefeed to just linefeed ! * Plus, escape any special characters. ! */ char * convert_special_chars(char *si, char *dst, int used) { *************** *** 1544,1550 **** for (i = 1; i <= 2; i++) { - if (s[i] >= 'a' && s[i] <= 'f') val = s[i] - 'a' + 10; else if (s[i] >= 'A' && s[i] <= 'F') --- 1528,1533 ---- *************** *** 1611,1617 **** int i, o = 0; - for (i = 0; i < len; i++) { mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]); --- 1594,1599 ---- *************** *** 1622,1628 **** strcpy(&out[o], conv_to_octal(in[i])); o += 5; } - } mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out); --- 1604,1609 ---- *************** *** 1679,1700 **** out[o++] = '\0'; } - ! /* 1. get oid (from 'value') ! 2. open the large object ! 3. read from the large object (handle multiple GetData) ! 4. close when read less than requested? -OR- ! lseek/read each time ! handle case where application receives truncated and ! decides not to continue reading. ! ! CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only ! data type currently mapped to a PG_TYPE_LO. But, if any other types ! are desired to map to a large object (PG_TYPE_LO), then that would ! need to be handled here. For example, LONGVARCHAR could possibly be ! mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now. ! */ int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue) --- 1660,1682 ---- out[o++] = '\0'; } ! /*------- ! * 1. get oid (from 'value') ! * 2. open the large object ! * 3. read from the large object (handle multiple GetData) ! * 4. close when read less than requested? -OR- ! * lseek/read each time ! * handle case where application receives truncated and ! * decides not to continue reading. ! * ! * CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only ! * data type currently mapped to a PG_TYPE_LO. But, if any other types ! * are desired to map to a large object (PG_TYPE_LO), then that would ! * need to be handled here. For example, LONGVARCHAR could possibly be ! * mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now. ! *------- ! */ int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue) *************** *** 1706,1712 **** BindInfoClass *bindInfo = NULL; ! /* If using SQLGetData, then current_col will be set */ if (stmt->current_col >= 0) { bindInfo = &stmt->bindings[stmt->current_col]; --- 1688,1694 ---- BindInfoClass *bindInfo = NULL; ! /* If using SQLGetData, then current_col will be set */ if (stmt->current_col >= 0) { bindInfo = &stmt->bindings[stmt->current_col]; *************** *** 1720,1726 **** if (!bindInfo || bindInfo->data_left == -1) { - /* begin transaction if needed */ if (!CC_is_in_trans(stmt->hdbc)) { --- 1702,1707 ---- *************** *** 1759,1765 **** retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END); if (retval >= 0) { - left = lo_tell(stmt->hdbc, stmt->lobj_fd); if (bindInfo) bindInfo->data_left = left; --- 1740,1745 ---- *************** *** 1824,1834 **** if (pcbValue) *pcbValue = left < 0 ? SQL_NO_TOTAL : left; - if (bindInfo && bindInfo->data_left > 0) bindInfo->data_left -= retval; - if (!bindInfo || bindInfo->data_left == 0) { lo_close(stmt->hdbc, stmt->lobj_fd); --- 1804,1812 ---- *************** *** 1861,1867 **** stmt->lobj_fd = -1; /* prevent further reading */ } - return result; - } --- 1839,1843 ---- Index: src/interfaces/odbc/dlg_specific.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/dlg_specific.c,v retrieving revision 1.28 diff -c -r1.28 dlg_specific.c *** src/interfaces/odbc/dlg_specific.c 2001/03/27 04:00:53 1.28 --- src/interfaces/odbc/dlg_specific.c 2001/03/28 16:53:14 *************** *** 1,4 **** ! /* Module: dlg_specific.c * * Description: This module contains any specific code for handling * dialog boxes such as driver/datasource options. Both the --- 1,5 ---- ! /*------- ! * Module: dlg_specific.c * * Description: This module contains any specific code for handling * dialog boxes such as driver/datasource options. Both the *************** *** 12,18 **** * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ /* Multibyte support Eiji Tokuya 2001-03-15 */ --- 13,19 ---- * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *------- */ /* Multibyte support Eiji Tokuya 2001-03-15 */ *************** *** 54,60 **** void SetDlgStuff(HWND hdlg, ConnInfo *ci) { - /* * If driver attribute NOT present, then set the datasource name and * description --- 55,60 ---- *************** *** 85,91 **** } - int CALLBACK driver_optionsProc(HWND hdlg, WORD wMsg, --- 85,90 ---- *************** *** 141,147 **** 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); --- 140,145 ---- *************** *** 228,234 **** break; } - } return FALSE; --- 226,231 ---- *************** *** 267,277 **** else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0) CheckDlgButton(hdlg, DS_PG63, 1); else ! /* latest */ CheckDlgButton(hdlg, DS_PG64, 1); ! ! ! CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column)); CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index)); CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning)); --- 264,272 ---- else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0) CheckDlgButton(hdlg, DS_PG63, 1); else ! /* latest */ CheckDlgButton(hdlg, DS_PG64, 1); ! CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column)); CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index)); CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning)); *************** *** 283,289 **** SetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings); break; - case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { --- 278,283 ---- *************** *** 292,300 **** EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN)); return TRUE; - case IDOK: - ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); mylog("IDOK: got ci = %u\n", ci); --- 286,292 ---- *************** *** 307,313 **** else if (IsDlgButtonChecked(hdlg, DS_PG63)) strcpy(ci->protocol, PG63); else ! /* latest */ strcpy(ci->protocol, PG64); sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES)); --- 299,305 ---- else if (IsDlgButtonChecked(hdlg, DS_PG63)) strcpy(ci->protocol, PG63); else ! /* latest */ strcpy(ci->protocol, PG64); sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES)); *************** *** 321,327 **** /* Datasource Connection Settings */ GetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings, sizeof(ci->conn_settings)); - /* fall through */ case IDCANCEL: --- 313,318 ---- *************** *** 368,374 **** void copyAttributes(ConnInfo *ci, char *attribute, char *value) { - if (stricmp(attribute, "DSN") == 0) strcpy(ci->dsn, value); --- 359,364 ---- *************** *** 415,421 **** } 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 --- 405,410 ---- *************** *** 450,457 **** char *DSN = ci->dsn; char encoded_conn_settings[LARGE_REGISTRY_LEN]; ! /* 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. */ if (DSN[0] == '\0') { if (ci->driver[0] != '\0') --- 439,448 ---- char *DSN = ci->dsn; char encoded_conn_settings[LARGE_REGISTRY_LEN]; ! /* ! * 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. ! */ if (DSN[0] == '\0') { if (ci->driver[0] != '\0') *************** *** 514,524 **** if (ci->translation_option[0] == '\0' || 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); - qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n", DSN, ci->server, --- 505,513 ---- *************** *** 546,552 **** qlog(" translation_dll='%s',translation_option='%s'\n", ci->translation_dll, ci->translation_option); - } --- 535,540 ---- *************** *** 626,640 **** } ! /* This function reads the ODBCINST.INI portion of ! the registry and gets any driver defaults. ! */ void getGlobalDefaults(char *section, char *filename, char override) { char temp[256]; - /* Fetch Count is stored in driver section */ SQLGetPrivateProfileString(section, INI_FETCH, "", temp, sizeof(temp), filename); --- 614,628 ---- } ! /* ! * This function reads the ODBCINST.INI portion of ! * the registry and gets any driver defaults. ! */ void getGlobalDefaults(char *section, char *filename, char override) { char temp[256]; /* Fetch Count is stored in driver section */ SQLGetPrivateProfileString(section, INI_FETCH, "", temp, sizeof(temp), filename); *************** *** 648,654 **** else if (!override) globals.fetch_max = FETCH_MAX; - /* Socket Buffersize is stored in driver section */ SQLGetPrivateProfileString(section, INI_SOCKET, "", temp, sizeof(temp), filename); --- 636,641 ---- *************** *** 657,663 **** else if (!override) globals.socket_buffersize = SOCK_BUFFER_SIZE; - /* Debug is stored in the driver section */ SQLGetPrivateProfileString(section, INI_DEBUG, "", temp, sizeof(temp), filename); --- 644,649 ---- *************** *** 666,672 **** else if (!override) globals.debug = DEFAULT_DEBUG; - /* CommLog is stored in the driver section */ SQLGetPrivateProfileString(section, INI_COMMLOG, "", temp, sizeof(temp), filename); --- 652,657 ---- *************** *** 675,681 **** else if (!override) globals.commlog = DEFAULT_COMMLOG; - /* Optimizer is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_OPTIMIZER, "", temp, sizeof(temp), filename); --- 660,665 ---- *************** *** 734,741 **** else if (!override) globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; - - /* UseDeclareFetch is stored in the driver section only */ SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "", temp, sizeof(temp), filename); --- 718,723 ---- *************** *** 744,750 **** else if (!override) globals.use_declarefetch = DEFAULT_USEDECLAREFETCH; - /* Max Varchar Size */ SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "", temp, sizeof(temp), filename); --- 726,731 ---- *************** *** 804,810 **** /* Dont allow override of an override! */ if (!override) { - /* * ConnSettings is stored in the driver section and per datasource * for override --- 785,790 ---- *************** *** 831,844 **** strcpy(globals.protocol, temp); else strcpy(globals.protocol, DEFAULT_PROTOCOL); - } } ! /* This function writes any global parameters (that can be manipulated) ! to the ODBCINST.INI portion of the registry ! */ void updateGlobals(void) { --- 811,824 ---- strcpy(globals.protocol, temp); else strcpy(globals.protocol, DEFAULT_PROTOCOL); } } ! /* ! * This function writes any global parameters (that can be manipulated) ! * to the ODBCINST.INI portion of the registry ! */ void updateGlobals(void) { Index: src/interfaces/odbc/drvconn.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/drvconn.c,v retrieving revision 1.22 diff -c -r1.22 drvconn.c *** src/interfaces/odbc/drvconn.c 2001/03/27 04:00:53 1.22 --- src/interfaces/odbc/drvconn.c 2001/03/28 16:53:15 *************** *** 1,4 **** ! /* Module: drvconn.c * * Description: This module contains only routines related to * implementing SQLDriverConnect. --- 1,5 ---- ! /*------- ! * Module: drvconn.c * * Description: This module contains only routines related to * implementing SQLDriverConnect. *************** *** 8,14 **** * API functions: SQLDriverConnect * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 9,15 ---- * API functions: SQLDriverConnect * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #ifdef HAVE_CONFIG_H *************** *** 110,118 **** /* Parse the connect string and fill in conninfo for this hdbc. */ dconn_get_connect_attributes(connStrIn, ci); ! /* If the ConnInfo in the hdbc is missing anything, */ ! /* this function will fill them in from the registry (assuming */ ! /* of course there is a DSN given -- if not, it does nothing!) */ getDSNinfo(ci, CONN_DONT_OVERWRITE); /* Fill in any default parameters if they are not there. */ --- 111,121 ---- /* Parse the connect string and fill in conninfo for this hdbc. */ dconn_get_connect_attributes(connStrIn, ci); ! /* ! * If the ConnInfo in the hdbc is missing anything, ! * this function will fill them in from the registry (assuming ! * of course there is a DSN given -- if not, it does nothing!) ! */ getDSNinfo(ci, CONN_DONT_OVERWRITE); /* Fill in any default parameters if they are not there. */ *************** *** 147,153 **** ci->port[0] == '\0' || password_required) { - dialog_result = dconn_DoDialog(hwnd, ci); if (dialog_result != SQL_SUCCESS) return dialog_result; --- 150,155 ---- *************** *** 173,184 **** ci->database[0] == '\0' || ci->port[0] == '\0') { ! /* (password_required && ci->password[0] == '\0')) */ return SQL_NO_DATA_FOUND; } - /* do the actual connect */ retval = CC_connect(conn, password_required); if (retval < 0) --- 175,185 ---- ci->database[0] == '\0' || ci->port[0] == '\0') { ! /* (password_required && ci->password[0] == '\0')) */ return SQL_NO_DATA_FOUND; } /* do the actual connect */ retval = CC_connect(conn, password_required); if (retval < 0) *************** *** 206,214 **** return SQL_ERROR; } ! /*********************************************/ ! /* Create the Output Connection String */ ! /*********************************************/ result = SQL_SUCCESS; makeConnectString(connStrOut, ci); --- 207,215 ---- return SQL_ERROR; } ! /* ! * Create the Output Connection String ! */ result = SQL_SUCCESS; makeConnectString(connStrOut, ci); *************** *** 216,222 **** if (szConnStrOut) { - /* * Return the completed string to the caller. The correct method * is to only construct the connect string if a dialog was put up, --- 217,222 ---- *************** *** 296,302 **** SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for * the "OK" */ - SetDlgStuff(hdlg, ci); if (ci->database[0] == '\0') --- 296,301 ---- *************** *** 309,346 **** SetFocus(GetDlgItem(hdlg, IDC_USER)); else if (ci->focus_password) SetFocus(GetDlgItem(hdlg, IDC_PASSWORD)); - - break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: - ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); GetDlgStuff(hdlg, ci); - case IDCANCEL: EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); return TRUE; case IDC_DRIVER: - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), hdlg, driver_optionsProc, (LPARAM) NULL); - - break; case IDC_DATASOURCE: - ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS), hdlg, ds_optionsProc, (LPARAM) ci); - break; } } --- 308,336 ---- *************** *** 392,398 **** copyAttributes(ci, attribute, value); } - free(our_connect_string); } --- 382,387 ---- Index: src/interfaces/odbc/environ.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/environ.c,v retrieving revision 1.24 diff -c -r1.24 environ.c *** src/interfaces/odbc/environ.c 2001/03/27 04:00:53 1.24 --- src/interfaces/odbc/environ.c 2001/03/28 16:53:15 *************** *** 1,4 **** ! /* Module: environ.c * * Description: This module contains routines related to * the environment, such as storing connection handles, --- 1,5 ---- ! /*------- ! * Module: environ.c * * Description: This module contains routines related to * the environment, such as storing connection handles, *************** *** 9,15 **** * API functions: SQLAllocEnv, SQLFreeEnv, SQLError * * Comments: See "notice.txt" for copyright and license information. ! * */ #include "environ.h" --- 10,16 ---- * API functions: SQLAllocEnv, SQLFreeEnv, SQLError * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #include "environ.h" *************** *** 208,231 **** case STMT_INVALID_CURSOR_POSITION: strcpy(szSqlState, "S1109"); break; - case STMT_VALUE_OUT_OF_RANGE: strcpy(szSqlState, "22003"); break; - case STMT_OPERATION_INVALID: strcpy(szSqlState, "S1011"); break; - case STMT_EXEC_ERROR: default: strcpy(szSqlState, "S1000"); /* also a general error */ break; } - mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg); - } else { --- 209,227 ---- *************** *** 237,246 **** szErrorMsg[0] = '\0'; mylog(" returning NO_DATA_FOUND\n"); return SQL_NO_DATA_FOUND; } - return SQL_SUCCESS; } else if (SQL_NULL_HDBC != hdbc) { --- 233,243 ---- szErrorMsg[0] = '\0'; mylog(" returning NO_DATA_FOUND\n"); + return SQL_NO_DATA_FOUND; } + return SQL_SUCCESS; } else if (SQL_NULL_HDBC != hdbc) { *************** *** 310,316 **** break; case CONN_TRANSACT_IN_PROGRES: strcpy(szSqlState, "S1010"); - /* * when the user tries to switch commit mode in a * transaction --- 307,312 ---- *************** *** 324,341 **** case STMT_NOT_IMPLEMENTED_ERROR: strcpy(szSqlState, "S1C00"); break; - case CONN_VALUE_OUT_OF_RANGE: case STMT_VALUE_OUT_OF_RANGE: strcpy(szSqlState, "22003"); break; - default: strcpy(szSqlState, "S1000"); /* general error */ break; } - } else { --- 320,334 ---- *************** *** 349,356 **** return SQL_NO_DATA_FOUND; } - return SQL_SUCCESS; } else if (SQL_NULL_HENV != henv) { --- 342,349 ---- return SQL_NO_DATA_FOUND; } + return SQL_SUCCESS; } else if (SQL_NULL_HENV != henv) { *************** *** 419,433 **** } - /*********************************************************************/ /* * EnvironmentClass implementation */ ! ! ! ! EnvironmentClass ! * EN_Constructor(void) { EnvironmentClass *rv; --- 412,421 ---- } /* * EnvironmentClass implementation */ ! EnvironmentClass * EN_Constructor(void) { EnvironmentClass *rv; *************** *** 451,458 **** mylog("in EN_Destructor, self=%u\n", self); ! /* the error messages are static strings distributed throughout */ ! /* the source--they should not be freed */ /* Free any connections belonging to this environment */ for (lf = 0; lf < MAX_CONNECTIONS; lf++) --- 439,448 ---- mylog("in EN_Destructor, self=%u\n", self); ! /* ! * the error messages are static strings distributed throughout ! * the source--they should not be freed ! */ /* Free any connections belonging to this environment */ for (lf = 0; lf < MAX_CONNECTIONS; lf++) Index: src/interfaces/odbc/execute.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/execute.c,v retrieving revision 1.25 diff -c -r1.25 execute.c *** src/interfaces/odbc/execute.c 2001/03/27 04:00:53 1.25 --- src/interfaces/odbc/execute.c 2001/03/28 16:53:15 *************** *** 1,4 **** ! /* Module: execute.c * * Description: This module contains routines related to * preparing and executing an SQL statement. --- 1,5 ---- ! /*------- ! * Module: execute.c * * Description: This module contains routines related to * preparing and executing an SQL statement. *************** *** 9,15 **** * SQLCancel, SQLNativeSql, SQLParamData, SQLPutData * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 10,16 ---- * SQLCancel, SQLNativeSql, SQLParamData, SQLPutData * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #ifdef HAVE_CONFIG_H *************** *** 125,138 **** } return SQL_SUCCESS; - - } - /* - - - - - - - - - */ - /* Performs the equivalent of SQLPrepare, followed by SQLExecute. */ - RETCODE SQL_API SQLExecDirect( HSTMT hstmt, --- 126,134 ---- *************** *** 154,161 **** if (stmt->statement) free(stmt->statement); ! /* keep a copy of the un-parametrized statement, in case */ ! /* they try to execute this statement again */ stmt->statement = make_string(szSqlStr, cbSqlStr, NULL); if (!stmt->statement) { --- 150,159 ---- if (stmt->statement) free(stmt->statement); ! /* ! * keep a copy of the un-parametrized statement, in case ! * they try to execute this statement again ! */ stmt->statement = make_string(szSqlStr, cbSqlStr, NULL); if (!stmt->statement) { *************** *** 169,177 **** stmt->prepare = FALSE; ! /* If an SQLPrepare was performed prior to this, but was left in */ ! /* the premature state because an error occurred prior to SQLExecute */ ! /* then set the statement to finished so it can be recycled. */ if (stmt->status == STMT_PREMATURE) stmt->status = STMT_FINISHED; --- 167,177 ---- stmt->prepare = FALSE; ! /* ! * If an SQLPrepare was performed prior to this, but was left in ! * the premature state because an error occurred prior to SQLExecute ! * then set the statement to finished so it can be recycled. ! */ if (stmt->status == STMT_PREMATURE) stmt->status = STMT_FINISHED; *************** *** 194,200 **** return result; } ! /* Execute a prepared SQL statement */ RETCODE SQL_API SQLExecute( HSTMT hstmt) --- 194,200 ---- return result; } ! /* Execute a prepared SQL statement */ RETCODE SQL_API SQLExecute( HSTMT hstmt) *************** *** 205,211 **** int i, retval; - mylog("%s: entering...\n", func); if (!stmt) --- 205,210 ---- *************** *** 274,280 **** if ((stmt->prepare && stmt->status != STMT_READY) || (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY)) { - stmt->errornumber = STMT_STATUS_ERROR; stmt->errormsg = "The handle does not point to a statement that is ready to be executed"; SC_log_error(func, "", stmt); --- 273,278 ---- *************** *** 282,288 **** return SQL_ERROR; } - /* * The bound parameters could have possibly changed since the last * execute of this statement? Therefore check for params and re-copy. --- 280,285 ---- *************** *** 319,333 **** mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params); - return SC_execute(stmt); - } - - - /* - - - - - - - - - */ RETCODE SQL_API SQLTransact( HENV henv, --- 316,325 ---- *************** *** 363,369 **** if (conn && conn->henv == henv) if (SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS) return SQL_ERROR; - } return SQL_SUCCESS; } --- 355,360 ---- *************** *** 371,385 **** conn = (ConnectionClass *) hdbc; if (fType == SQL_COMMIT) - { stmt_string = "COMMIT"; - - } else if (fType == SQL_ROLLBACK) - { stmt_string = "ROLLBACK"; - - } else { conn->errornumber = CONN_INVALID_ARGUMENT_NO; --- 362,370 ---- *************** *** 391,397 **** /* If manual commit and in transaction, then proceed. */ if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) { - mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string); res = CC_send_query(conn, stmt_string, NULL); --- 376,381 ---- *************** *** 416,422 **** return SQL_SUCCESS; } - /* - - - - - - - - - */ RETCODE SQL_API SQLCancel( --- 400,405 ---- *************** *** 447,454 **** */ if (stmt->data_at_exec < 0) { - - /* * MAJOR HACK for Windows to reset the driver manager's cursor * state: Because of what seems like a bug in the Odbc driver --- 430,435 ---- *************** *** 490,503 **** stmt->put_data = FALSE; return SQL_SUCCESS; - } - /* - - - - - - - - - */ ! /* Returns the SQL string as modified by the driver. */ ! /* Currently, just copy the input string without modification */ ! /* observing buffer limits and truncation. */ RETCODE SQL_API SQLNativeSql( HDBC hdbc, --- 471,484 ---- stmt->put_data = FALSE; return SQL_SUCCESS; } ! /* ! * Returns the SQL string as modified by the driver. ! * Currently, just copy the input string without modification ! * observing buffer limits and truncation. ! */ RETCODE SQL_API SQLNativeSql( HDBC hdbc, *************** *** 546,557 **** return result; } - - /* - - - - - - - - - */ ! /* Supplies parameter data at execution time. Used in conjuction with */ ! /* SQLPutData. */ ! RETCODE SQL_API SQLParamData( HSTMT hstmt, --- 527,537 ---- return result; } ! /* ! * Supplies parameter data at execution time. ! * Used in conjuction with SQLPutData. ! */ RETCODE SQL_API SQLParamData( HSTMT hstmt, *************** *** 619,629 **** CC_set_no_trans(stmt->hdbc); } - stmt->lobj_fd = -1; } - /* Done, now copy the params and then execute the statement */ if (stmt->data_at_exec == 0) { --- 599,607 ---- *************** *** 657,668 **** return SQL_NEED_DATA; } - - /* - - - - - - - - - */ ! /* Supplies parameter data at execution time. Used in conjunction with */ ! /* SQLParamData. */ ! RETCODE SQL_API SQLPutData( HSTMT hstmt, --- 635,645 ---- return SQL_NEED_DATA; } ! /* ! * Supplies parameter data at execution time. ! * Used in conjunction with SQLParamData. ! */ RETCODE SQL_API SQLPutData( HSTMT hstmt, *************** *** 684,690 **** return SQL_INVALID_HANDLE; } - if (stmt->current_exec_param < 0) { stmt->errornumber = STMT_SEQUENCE_ERROR; --- 661,666 ---- *************** *** 697,703 **** if (!stmt->put_data) { /* first call */ - mylog("SQLPutData: (1) cbValue = %d\n", cbValue); stmt->put_data = TRUE; --- 673,678 ---- *************** *** 716,726 **** if (cbValue == SQL_NULL_DATA) return SQL_SUCCESS; - /* Handle Long Var Binary with Large Objects */ if (current_param->SQLType == SQL_LONGVARBINARY) { - /* begin transaction if needed */ if (!CC_is_in_trans(stmt->hdbc)) { --- 691,699 ---- *************** *** 758,765 **** return SQL_ERROR; } ! /* major hack -- to allow convert to see somethings there */ ! /* have to modify convert to handle this better */ current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid; /* store the fd */ --- 731,740 ---- return SQL_ERROR; } ! /* ! * major hack -- to allow convert to see somethings there ! * have to modify convert to handle this better ! */ current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid; /* store the fd */ *************** *** 774,785 **** retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval); - } else ! { /* for handling text fields and small ! * binaries */ ! if (cbValue == SQL_NTS) { current_param->EXEC_buffer = strdup(rgbValue); --- 749,758 ---- retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval); } else ! { ! /* for handling text fields and small binaries */ if (cbValue == SQL_NTS) { current_param->EXEC_buffer = strdup(rgbValue); *************** *** 806,830 **** } } } - else ! { /* calling SQLPutData more than once */ ! mylog("SQLPutData: (>1) cbValue = %d\n", cbValue); if (current_param->SQLType == SQL_LONGVARBINARY) { - /* the large object fd is in EXEC_buffer */ retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval); *current_param->EXEC_used += cbValue; - } else { - buffer = current_param->EXEC_buffer; if (cbValue == SQL_NTS) --- 779,799 ---- } } } else ! { ! /* calling SQLPutData more than once */ mylog("SQLPutData: (>1) cbValue = %d\n", cbValue); if (current_param->SQLType == SQL_LONGVARBINARY) { /* the large object fd is in EXEC_buffer */ retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval); *current_param->EXEC_used += cbValue; } else { buffer = current_param->EXEC_buffer; if (cbValue == SQL_NTS) *************** *** 845,855 **** /* reassign buffer incase realloc moved it */ current_param->EXEC_buffer = buffer; - } else if (cbValue > 0) { - old_pos = *current_param->EXEC_used; *current_param->EXEC_used += cbValue; --- 814,822 ---- *************** *** 871,887 **** /* reassign buffer incase realloc moved it */ current_param->EXEC_buffer = buffer; - } else { SC_log_error(func, "bad cbValue", stmt); return SQL_ERROR; } - } } - return SQL_SUCCESS; } --- 838,851 ---- Index: src/interfaces/odbc/gpps.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/gpps.c,v retrieving revision 1.17 diff -c -r1.17 gpps.c *** src/interfaces/odbc/gpps.c 2001/03/27 04:00:53 1.17 --- src/interfaces/odbc/gpps.c 2001/03/28 16:53:15 *************** *** 1,4 **** ! /* GetPrivateProfileString() * * approximate implementation of * Windows NT System Services version of GetPrivateProfileString() --- 1,5 ---- ! /*------- ! * GetPrivateProfileString() * * approximate implementation of * Windows NT System Services version of GetPrivateProfileString() *************** *** 15,20 **** --- 16,22 ---- * are allowed (that is an anachronism anyway) * Added code to search for ODBC_INI file in users home directory on * Unix + *------- */ #ifndef WIN32 *************** *** 46,52 **** DWORD GetPrivateProfileString(char *theSection, /* section name */ ! char *theKey, /* search key name */ char *theDefault, /* default value if not * found */ char *theReturnBuffer, /* return value stored --- 48,54 ---- DWORD GetPrivateProfileString(char *theSection, /* section name */ ! char *theKey, /* search key name */ char *theDefault, /* default value if not * found */ char *theReturnBuffer, /* return value stored *************** *** 110,116 **** aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL); } - aLength = (theDefault == NULL) ? 0 : strlen(theDefault); if (theReturnBufferLength == 0 || theReturnBuffer == NULL) --- 112,117 ---- *************** *** 123,129 **** if (aFile == NULL) { /* no ini file specified, return the default */ - ++aLength; /* room for NULL char */ aLength = theReturnBufferLength < aLength ? theReturnBufferLength : aLength; --- 124,129 ---- *************** *** 132,138 **** return aLength - 1; } - while (fgets(aLine, sizeof(aLine), aFile) != NULL) { aLineLength = strlen(aLine); --- 132,137 ---- *************** *** 147,153 **** break; case '[': /* section marker */ - if ((aString = strchr(aLine, ']'))) { aStart = aLine + 1; --- 146,151 ---- *************** *** 159,188 **** *(aString + 1) = '\0'; /* accept as matched if NULL key or exact match */ - if (!theSection || !strcmp(aStart, theSection)) aSectionFound = TRUE; else aSectionFound = FALSE; } - break; default: /* try to match value keys if in proper section */ - if (aSectionFound) { /* try to match requested key */ - if ((aString = aValue = strchr(aLine, '='))) { *aValue = '\0'; ++aValue; /* strip leading blanks in value field */ - while (*aValue == ' ' && aValue < aLine + sizeof(aLine)) *aValue++ = '\0'; if (aValue >= aLine + sizeof(aLine)) --- 157,181 ---- *************** *** 196,202 **** aStart++; /* strip trailing blanks from key */ - if (aString) { while (--aString >= aStart && *aString == ' ') --- 189,194 ---- *************** *** 204,219 **** } /* see if key is matched */ - if (theKey == NULL || !strcmp(theKey, aStart)) { /* matched -- first, terminate value part */ - aKeyFound = TRUE; aLength = strlen(aValue); /* remove trailing blanks from aValue if any */ - aString = aValue + aLength - 1; while (--aString > aValue && *aString == ' ') --- 196,208 ---- *************** *** 223,229 **** } /* unquote value if quoted */ - if (aLength >= 2 && aValue[0] == '"' && aValue[aLength - 1] == '"') { --- 212,217 ---- *************** *** 236,242 **** else { /* single quotes allowed also... */ - if (aLength >= 2 && aValue[0] == '\'' && aValue[aLength - 1] == '\'') { --- 224,229 ---- *************** *** 247,259 **** } /* compute maximum length copyable */ - aLineLength = (aLength < theReturnBufferLength - aReturnLength) ? aLength : theReturnBufferLength - aReturnLength; /* do the copy to return buffer */ - if (aLineLength) { strncpy(&theReturnBuffer[aReturnLength], --- 234,244 ---- *************** *** 270,280 **** fclose(aFile); aFile = NULL; } - return aReturnLength > 0 ? aReturnLength - 1 : 0; } } - break; } } --- 255,263 ---- *************** *** 283,289 **** fclose(aFile); if (!aKeyFound) ! { /* key wasn't found return default */ ++aLength; /* room for NULL char */ aLength = theReturnBufferLength < aLength ? theReturnBufferLength : aLength; --- 266,273 ---- fclose(aFile); if (!aKeyFound) ! { ! /* key wasn't found return default */ ++aLength; /* room for NULL char */ aLength = theReturnBufferLength < aLength ? theReturnBufferLength : aLength; *************** *** 296,302 **** DWORD WritePrivateProfileString(char *theSection, /* section name */ ! char *theKey, /* write key name */ char *theBuffer, /* input buffer */ char *theIniFileName) /* pathname of ini file to * write */ --- 280,286 ---- DWORD WritePrivateProfileString(char *theSection, /* section name */ ! char *theKey, /* write key name */ char *theBuffer, /* input buffer */ char *theIniFileName) /* pathname of ini file to * write */ *************** *** 305,317 **** } #if 0 ! /* Ok. What the hell's the default behaviour for a null input buffer, and null * section name. For now if either are null I ignore the request, until * I find out different. */ DWORD WritePrivateProfileString(char *theSection, /* section name */ ! char *theKey, /* write key name */ char *theBuffer, /* input buffer */ char *theIniFileName) /* pathname of ini file to * write */ --- 289,302 ---- } #if 0 ! /* ! * Ok. What the hell's the default behaviour for a null input buffer, and null * section name. For now if either are null I ignore the request, until * I find out different. */ DWORD WritePrivateProfileString(char *theSection, /* section name */ ! char *theKey, /* write key name */ char *theBuffer, /* input buffer */ char *theIniFileName) /* pathname of ini file to * write */ *************** *** 353,363 **** if (ptr == NULL || *ptr == '\0') ptr = "/home"; ! /* This doesn't make it so we find an ini file but allows normal */ ! /* processing to continue further on down. The likelihood is that */ ! /* the file won't be found and thus the default value will be */ ! /* returned. */ ! /* */ if (MAXPGPATH - 1 < strlen(ptr) + j) { if (MAXPGPATH - 1 < strlen(ptr)) --- 338,349 ---- if (ptr == NULL || *ptr == '\0') ptr = "/home"; ! /* ! * This doesn't make it so we find an ini file but allows normal ! * processing to continue further on down. The likelihood is that ! * the file won't be found and thus the default value will be ! * returned. ! */ if (MAXPGPATH - 1 < strlen(ptr) + j) { if (MAXPGPATH - 1 < strlen(ptr)) *************** *** 368,376 **** sprintf(buf, "%s/%s", ptr, theIniFileName); ! /* This code makes it so that a file in the users home dir */ ! /* overrides a the "default" file as passed in */ ! /* */ aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL); if (!aFile) { --- 354,363 ---- sprintf(buf, "%s/%s", ptr, theIniFileName); ! /* ! * This code makes it so that a file in the users home dir ! * overrides a the "default" file as passed in ! */ aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL); if (!aFile) { *************** *** 380,392 **** return 0; } - aLength = strlen(theBuffer); ! /* We have to search for theKey, because if it already */ ! /* exists we have to overwrite it. If it doesn't exist */ ! /* we just write a new line to the file. */ ! /* */ while (fgets(aLine, sizeof(aLine), aFile) != NULL) { aLineLength = strlen(aLine); --- 367,379 ---- return 0; } aLength = strlen(theBuffer); ! /* ! * We have to search for theKey, because if it already ! * exists we have to overwrite it. If it doesn't exist ! * we just write a new line to the file. ! */ while (fgets(aLine, sizeof(aLine), aFile) != NULL) { aLineLength = strlen(aLine); *************** *** 401,407 **** break; case '[': /* section marker */ - if ((aString = strchr(aLine, ']'))) { *aString = '\0'; --- 388,393 ---- *************** *** 411,423 **** if (!strcmp(aLine + 1, theSection)) aSectionFound = TRUE; } - break; default: - /* try to match value keys if in proper section */ - if (aSectionFound) { /* try to match requested key */ --- 397,406 ---- *************** *** 428,434 **** ++aValue; /* strip leading blanks in value field */ - while (*aValue == ' ' && aValue < aLine + sizeof(aLine)) *aValue++ = '\0'; if (aValue >= aLine + sizeof(aLine)) --- 411,416 ---- *************** *** 438,444 **** aValue = ""; /* strip trailing blanks from key */ - if (aString) { while (--aString >= aLine && *aString == ' ') --- 420,425 ---- *************** *** 446,452 **** } /* see if key is matched */ - if (!strcmp(theKey, aLine)) { keyFound = TRUE; --- 427,432 ---- *************** *** 460,466 **** } } } - break; } } --- 440,445 ---- Index: src/interfaces/odbc/info.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/info.c,v retrieving revision 1.44 diff -c -r1.44 info.c *** src/interfaces/odbc/info.c 2001/03/27 04:00:53 1.44 --- src/interfaces/odbc/info.c 2001/03/28 16:53:17 *************** *** 1,4 **** ! /* Module: info.c * * Description: This module contains routines related to * ODBC informational functions. --- 1,5 ---- ! /*-------- ! * Module: info.c * * Description: This module contains routines related to * ODBC informational functions. *************** *** 12,18 **** * SQLTablePrivileges(NI), SQLColumnPrivileges(NI) * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 13,19 ---- * SQLTablePrivileges(NI), SQLColumnPrivileges(NI) * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ #ifdef HAVE_CONFIG_H *************** *** 56,63 **** extern GLOBAL_VALUES globals; - /* - - - - - - - - - */ - RETCODE SQL_API SQLGetInfo( HDBC hdbc, --- 57,62 ---- *************** *** 154,160 **** break; case SQL_CORRELATION_NAME: /* ODBC 1.0 */ - /* * Saying no correlation name makes Query not work right. * value = SQL_CN_NONE; --- 153,158 ---- *************** *** 182,192 **** break; case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */ - /* * Returning the database name causes problems in MS Query. It ! * generates query like: "SELECT DISTINCT a FROM byronncrap3 ! * crap3" * * p = CC_get_database(conn); */ --- 180,189 ---- break; case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */ /* * Returning the database name causes problems in MS Query. It ! * generates query like: "SELECT DISTINCT a FROM byronnbad3 ! * bad3" * * p = CC_get_database(conn); */ *************** *** 198,204 **** break; case SQL_DBMS_VER: /* ODBC 1.0 */ - /* * The ODBC spec wants ##.##.#### ...whatever... so prepend * the driver --- 195,200 ---- *************** *** 256,262 **** break; case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */ - /* * are identifiers case-sensitive (yes, but only when quoted. * If not quoted, they default to lowercase) --- 252,257 ---- *************** *** 275,281 **** break; case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */ - /* * is there a character that escapes '%' and '_' in a LIKE * clause? not as far as I can tell --- 270,275 ---- *************** *** 356,373 **** case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */ len = 4; if (PG_VERSION_GE(conn, 7.1)) ! { /* Large Rowa in 7.1+ */ value = MAX_ROW_SIZE; } else ! { /* Without the Toaster we're limited to ! * the blocksize */ value = BLCKSZ; } break; case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */ - /* * does the preceding value include LONGVARCHAR and * LONGVARBINARY fields? Well, it does include longvarchar, --- 350,367 ---- case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */ len = 4; if (PG_VERSION_GE(conn, 7.1)) ! { ! /* Large Rowa in 7.1+ */ value = MAX_ROW_SIZE; } else ! { ! /* Without the Toaster we're limited to the blocksize */ value = BLCKSZ; } break; case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */ /* * does the preceding value include LONGVARCHAR and * LONGVARBINARY fields? Well, it does include longvarchar, *************** *** 379,393 **** case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */ /* maybe this should be 0? */ len = 4; if (PG_VERSION_GE(conn, 7.0)) - { /* Long Queries in 7.0+ */ value = MAX_STATEMENT_LEN; ! } ! else if (PG_VERSION_GE(conn, 6.5)) /* Prior to 7.0 we used ! * 2*BLCKSZ */ value = (2 * BLCKSZ); else ! /* Prior to 6.5 we used BLCKSZ */ value = BLCKSZ; break; --- 373,386 ---- case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */ /* maybe this should be 0? */ len = 4; + /* Long Queries in 7.0+ */ if (PG_VERSION_GE(conn, 7.0)) value = MAX_STATEMENT_LEN; ! /* Prior to 7.0 we used 2*BLCKSZ */ ! else if (PG_VERSION_GE(conn, 6.5)) value = (2 * BLCKSZ); else ! /* Prior to 6.5 we used BLCKSZ */ value = BLCKSZ; break; *************** *** 417,425 **** break; case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */ - /* ! * Dont need the length, SQLPutData can handle any size and * multiple calls */ p = "N"; --- 410,417 ---- break; case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */ /* ! * Don't need the length, SQLPutData can handle any size and * multiple calls */ p = "N"; *************** *** 463,469 **** case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */ len = 4; if (PG_VERSION_GE(conn, 7.1)) ! { /* OJs in 7.1+ */ value = (SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL | --- 455,462 ---- case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */ len = 4; if (PG_VERSION_GE(conn, 7.1)) ! { ! /* OJs in 7.1+ */ value = (SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_FULL | *************** *** 473,481 **** SQL_OJ_ALL_COMPARISON_OPS); } else ! { /* OJs not in <7.1 */ value = 0; - } break; case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */ --- 466,473 ---- SQL_OJ_ALL_COMPARISON_OPS); } else ! /* OJs not in <7.1 */ value = 0; break; case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */ *************** *** 484,496 **** case SQL_OUTER_JOINS: /* ODBC 1.0 */ if (PG_VERSION_GE(conn, 7.1)) ! { /* OJs in 7.1+ */ p = "Y"; - } else ! { /* OJs not in <7.1 */ p = "N"; - } break; case SQL_OWNER_TERM: /* ODBC 1.0 */ --- 476,486 ---- case SQL_OUTER_JOINS: /* ODBC 1.0 */ if (PG_VERSION_GE(conn, 7.1)) ! /* OJs in 7.1+ */ p = "Y"; else ! /* OJs not in <7.1 */ p = "N"; break; case SQL_OWNER_TERM: /* ODBC 1.0 */ *************** *** 547,553 **** break; case SQL_ROW_UPDATES: /* ODBC 1.0 */ - /* * Driver doesn't support keyset-driven or mixed cursors, so * not much point in saying row updates are supported --- 537,542 ---- *************** *** 635,641 **** break; case SQL_TXN_CAPABLE: /* ODBC 1.0 */ - /* * Postgres can deal with create or drop table statements in a * transaction --- 624,629 ---- *************** *** 677,683 **** * what length would be required if a real buffer had been passed in. */ if (p) ! { /* char/binary data */ len = strlen(p); if (rgbInfoValue) --- 665,672 ---- * what length would be required if a real buffer had been passed in. */ if (p) ! { ! /* char/binary data */ len = strlen(p); if (rgbInfoValue) *************** *** 692,704 **** } } } - else ! { /* numeric data */ ! if (rgbInfoValue) { - if (len == 2) *((WORD *) rgbInfoValue) = (WORD) value; else if (len == 4) --- 681,691 ---- } } } else ! { ! /* numeric data */ if (rgbInfoValue) { if (len == 2) *((WORD *) rgbInfoValue) = (WORD) value; else if (len == 4) *************** *** 712,719 **** return result; } - /* - - - - - - - - - */ - RETCODE SQL_API SQLGetTypeInfo( --- 699,704 ---- *************** *** 725,731 **** TupleNode *row; int i; ! /* Int4 type; */ Int4 pgType; Int2 sqlType; --- 710,716 ---- TupleNode *row; int i; ! /* Int4 type; */ Int4 pgType; Int2 sqlType; *************** *** 737,743 **** return SQL_INVALID_HANDLE; } - stmt->manual_result = TRUE; stmt->result = QR_Constructor(); if (!stmt->result) --- 722,727 ---- *************** *** 801,807 **** } } - stmt->status = STMT_FINISHED; stmt->currTuple = -1; stmt->rowset_start = -1; --- 785,790 ---- *************** *** 810,816 **** return SQL_SUCCESS; } - /* - - - - - - - - - */ RETCODE SQL_API SQLGetFunctions( --- 793,798 ---- *************** *** 824,830 **** if (fFunction == SQL_API_ALL_FUNCTIONS) { - if (globals.lie) { int i; --- 806,811 ---- *************** *** 910,922 **** } else { - if (globals.lie) *pfExists = TRUE; - else { - switch (fFunction) { case SQL_API_SQLALLOCCONNECT: --- 891,900 ---- *************** *** 1094,1105 **** } } } - return SQL_SUCCESS; } - RETCODE SQL_API SQLTables( HSTMT hstmt, --- 1072,1081 ---- *************** *** 1160,1173 **** return SQL_ERROR; } tbl_stmt = (StatementClass *) htbl_stmt; - - /* ********************************************************************** */ - /* Create the query to find out the tables */ - /* ********************************************************************** */ if (PG_VERSION_GE(conn, 7.1)) ! { /* view is represented by its relkind ! * since 7.1 */ strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user"); strcat(tables_query, " where relkind in ('r', 'v')"); } --- 1136,1148 ---- return SQL_ERROR; } tbl_stmt = (StatementClass *) htbl_stmt; + /* + * Create the query to find out the tables + */ if (PG_VERSION_GE(conn, 7.1)) ! { ! /* view is represented by its relkind since 7.1 */ strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user"); strcat(tables_query, " where relkind in ('r', 'v')"); } *************** *** 1180,1194 **** my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner); my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName); - /* Parse the extra systable prefix */ strcpy(prefixes, globals.extra_systable_prefixes); i = 0; prefix[i] = strtok(prefixes, ";"); while (prefix[i] && i < 32) - { prefix[++i] = strtok(NULL, ";"); - } /* Parse the desired table types to return */ show_system_tables = FALSE; --- 1155,1166 ---- *************** *** 1216,1222 **** show_regular_tables = TRUE; else if (strstr(table_type[i], "VIEW")) show_views = TRUE; - i++; } } --- 1188,1193 ---- *************** *** 1243,1263 **** strcat(tables_query, prefix[i]); i++; } - strcat(tables_query, "'"); } - /* match users */ ! if (PG_VERSION_LT(conn, 7.1)) /* filter out large objects in ! * older versions */ strcat(tables_query, " and relname !~ '^xinv[0-9]+'"); strcat(tables_query, " and usesysid = relowner"); strcat(tables_query, " order by relname"); - /* ********************************************************************** */ - result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { --- 1214,1230 ---- strcat(tables_query, prefix[i]); i++; } strcat(tables_query, "'"); } /* match users */ ! if (PG_VERSION_LT(conn, 7.1)) ! /* filter out large objects in older versions */ strcat(tables_query, " and relname !~ '^xinv[0-9]+'"); strcat(tables_query, " and usesysid = relowner"); strcat(tables_query, " order by relname"); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { *************** *** 1330,1336 **** result = SQLFetch(htbl_stmt); while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { - /* * Determine if this table name is a system table. If treating * system tables as regular tables, then no need to do this test. --- 1297,1302 ---- *************** *** 1338,1349 **** systable = FALSE; if (!atoi(ci->show_system_tables)) { - if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0) systable = TRUE; else ! { /* Check extra system table prefixes */ i = 0; while (prefix[i]) { --- 1304,1315 ---- systable = FALSE; if (!atoi(ci->show_system_tables)) { if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0) systable = TRUE; else ! { ! /* Check extra system table prefixes */ i = 0; while (prefix[i]) { *************** *** 1359,1366 **** } /* Determine if the table name is a view */ ! if (PG_VERSION_GE(conn, 7.1)) /* view is represented by its ! * relkind since 7.1 */ view = (relkind_or_hasrules[0] == 'v'); else view = (relkind_or_hasrules[0] == '1'); --- 1325,1332 ---- } /* Determine if the table name is a view */ ! if (PG_VERSION_GE(conn, 7.1)) ! /* view is represented by its relkind since 7.1 */ view = (relkind_or_hasrules[0] == 'v'); else view = (relkind_or_hasrules[0] == '1'); *************** *** 1379,1394 **** (view && show_views) || (regular_table && show_regular_tables)) { - row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField)); set_tuplefield_string(&row->tuple[0], ""); ! /* I have to hide the table owner from Access, otherwise it */ ! /* insists on referring to the table as 'owner.table'. */ ! /* (this is valid according to the ODBC SQL grammar, but */ ! /* Postgres won't support it.) */ ! /* set_tuplefield_string(&row->tuple[1], table_owner); */ mylog("SQLTables: table_name = '%s'\n", table_name); --- 1345,1362 ---- (view && show_views) || (regular_table && show_regular_tables)) { row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField)); set_tuplefield_string(&row->tuple[0], ""); ! /* ! * I have to hide the table owner from Access, otherwise it ! * insists on referring to the table as 'owner.table'. ! * (this is valid according to the ODBC SQL grammar, but ! * Postgres won't support it.) ! * ! * set_tuplefield_string(&row->tuple[1], table_owner); ! */ mylog("SQLTables: table_name = '%s'\n", table_name); *************** *** 1410,1417 **** return SQL_ERROR; } ! /* also, things need to think that this statement is finished so */ ! /* the results can be retrieved. */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ --- 1378,1387 ---- return SQL_ERROR; } ! /* ! * also, things need to think that this statement is finished so ! * the results can be retrieved. ! */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ *************** *** 1425,1432 **** } - - RETCODE SQL_API SQLColumns( HSTMT hstmt, --- 1395,1400 ---- *************** *** 1479,1491 **** conn = (ConnectionClass *) (stmt->hdbc); ci = &stmt->hdbc->connInfo; - /* ********************************************************************** */ - /* * Create the query to find out the columns (Note: pre 6.3 did not * have the atttypmod field) */ - /* ********************************************************************** */ sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid" ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules" " from pg_user u, pg_class c, pg_attribute a, pg_type t" --- 1447,1456 ---- *************** *** 1497,1506 **** my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner); my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName); ! /* give the output in the order the columns were defined */ ! /* when the table was created */ strcat(columns_query, " order by attnum"); - /* ********************************************************************** */ result = SQLAllocStmt(stmt->hdbc, &hcol_stmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) --- 1462,1472 ---- my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner); my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName); ! /* ! * give the output in the order the columns were defined ! * when the table was created ! */ strcat(columns_query, " order by attnum"); result = SQLAllocStmt(stmt->hdbc, &hcol_stmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) *************** *** 1673,1682 **** QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4); QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4); - result = SQLFetch(hcol_stmt); - /* * Only show oid if option AND there are other columns AND it's not * being called by SQLStatistics . Always show OID if it's a system --- 1639,1646 ---- *************** *** 1685,1696 **** if (result != SQL_ERROR && !stmt->internal) { - if (relhasrules[0] != '1' && (atoi(ci->show_oid_column) || strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)) { - /* For OID fields */ the_type = PG_TYPE_OID; row = (TupleNode *) malloc(sizeof(TupleNode) + --- 1649,1658 ---- *************** *** 1718,1724 **** QR_add_tuple(stmt->result, row); } - } while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) --- 1680,1685 ---- *************** *** 1776,1786 **** } } - if ((field_type == PG_TYPE_VARCHAR) || (field_type == PG_TYPE_BPCHAR)) { - useStaticPrecision = FALSE; if (mod_length >= 4) --- 1737,1745 ---- *************** *** 1827,1834 **** return SQL_ERROR; } ! /* Put the row version column at the end so it might not be */ ! /* mistaken for a key field. */ if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning)) { /* For Row Versioning fields */ --- 1786,1795 ---- return SQL_ERROR; } ! /* ! * Put the row version column at the end so it might not be ! * mistaken for a key field. ! */ if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning)) { /* For Row Versioning fields */ *************** *** 1855,1862 **** QR_add_tuple(stmt->result, row); } ! /* also, things need to think that this statement is finished so */ ! /* the results can be retrieved. */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ --- 1816,1825 ---- QR_add_tuple(stmt->result, row); } ! /* ! * also, things need to think that this statement is finished so ! * the results can be retrieved. ! */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ *************** *** 1892,1899 **** RETCODE result; char relhasrules[MAX_INFO_STRING]; - - mylog("%s: entering...stmt=%u\n", func, stmt); if (!stmt) --- 1855,1860 ---- *************** *** 1904,1914 **** ci = &stmt->hdbc->connInfo; stmt->manual_result = TRUE; - ! /* ********************************************************************** */ ! /* Create the query to find out if this is a view or not... */ ! /* ********************************************************************** */ sprintf(columns_query, "select c.relhasrules " "from pg_user u, pg_class c where " "u.usesysid = c.relowner"); --- 1865,1874 ---- ci = &stmt->hdbc->connInfo; stmt->manual_result = TRUE; ! /* ! * Create the query to find out if this is a view or not... ! */ sprintf(columns_query, "select c.relhasrules " "from pg_user u, pg_class c where " "u.usesysid = c.relowner"); *************** *** 1988,1994 **** } else if (fColType == SQL_ROWVER) { - Int2 the_type = PG_TYPE_INT4; if (atoi(ci->row_versioning)) --- 1948,1953 ---- *************** *** 2009,2016 **** } } - - stmt->status = STMT_FINISHED; stmt->currTuple = -1; stmt->rowset_start = -1; --- 1968,1973 ---- *************** *** 2104,2112 **** QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4); QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING); ! ! /* only use the table name... the owner should be redundant, and */ ! /* we never use qualifiers. */ table_name = make_string(szTableName, cbTableName, NULL); if (!table_name) { --- 2061,2070 ---- QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4); QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING); ! /* ! * only use the table name... the owner should be redundant, and ! * we never use qualifiers. ! */ table_name = make_string(szTableName, cbTableName, NULL); if (!table_name) { *************** *** 2116,2123 **** return SQL_ERROR; } ! /* we need to get a list of the field names first, */ ! /* so we can return them later. */ result = SQLAllocStmt(stmt->hdbc, &hcol_stmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { --- 2074,2083 ---- return SQL_ERROR; } ! /* ! * we need to get a list of the field names first, ! * so we can return them later. ! */ result = SQLAllocStmt(stmt->hdbc, &hcol_stmt); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { *************** *** 2172,2177 **** --- 2132,2138 ---- result = SQLFetch(hcol_stmt); } + if (result != SQL_NO_DATA_FOUND || total_columns == 0) { stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column *************** *** 2205,2218 **** result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query)); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { ! stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "Couldn't execute ! * index query ! * (w/SQLExecDirect) in ! * SQLStatistics."; */ stmt->errornumber = indx_stmt->errornumber; SQLFreeStmt(hindx_stmt, SQL_DROP); goto SEEYA; - } /* bind the index name column */ --- 2166,2180 ---- result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query)); if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { ! /* ! * "Couldn't execute index query (w/SQLExecDirect) in ! * SQLStatistics."; ! */ ! stmt->errormsg = SC_create_errormsg(hindx_stmt); ! stmt->errornumber = indx_stmt->errornumber; SQLFreeStmt(hindx_stmt, SQL_DROP); goto SEEYA; } /* bind the index name column */ *************** *** 2314,2320 **** result = SQLFetch(hindx_stmt); while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { - /* If only requesting unique indexs, then just return those. */ if (fUnique == SQL_INDEX_ALL || (fUnique == SQL_INDEX_UNIQUE && atoi(isunique))) --- 2276,2281 ---- *************** *** 2323,2329 **** /* add a row in this table for each field in the index */ while (i < 16 && fields_vector[i] != 0) { - row = (TupleNode *) malloc(sizeof(TupleNode) + (13 - 1) *sizeof(TupleField)); --- 2284,2289 ---- *************** *** 2380,2387 **** } if (result != SQL_NO_DATA_FOUND) { ! stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "SQLFetch failed in ! * SQLStatistics."; */ stmt->errornumber = indx_stmt->errornumber; SQLFreeStmt(hindx_stmt, SQL_DROP); goto SEEYA; --- 2340,2347 ---- } if (result != SQL_NO_DATA_FOUND) { ! /* "SQLFetch failed in SQLStatistics."; */ ! stmt->errormsg = SC_create_errormsg(hindx_stmt); stmt->errornumber = indx_stmt->errornumber; SQLFreeStmt(hindx_stmt, SQL_DROP); goto SEEYA; *************** *** 2389,2396 **** SQLFreeStmt(hindx_stmt, SQL_DROP); ! /* also, things need to think that this statement is finished so */ ! /* the results can be retrieved. */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ --- 2349,2358 ---- SQLFreeStmt(hindx_stmt, SQL_DROP); ! /* ! * also, things need to think that this statement is finished so ! * the results can be retrieved. ! */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ *************** *** 2418,2423 **** --- 2380,2386 ---- return SQL_SUCCESS; } + RETCODE SQL_API SQLColumnPrivileges( HSTMT hstmt, *************** *** 2434,2448 **** mylog("%s: entering...\n", func); ! /* Neither Access or Borland care about this. */ SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); return SQL_ERROR; } ! /* SQLPrimaryKeys() ! * Retrieve the primary key columns for the specified table. */ RETCODE SQL_API SQLPrimaryKeys( --- 2397,2413 ---- mylog("%s: entering...\n", func); ! /* Neither Access or Borland care about this. */ SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); return SQL_ERROR; } ! /* ! * SQLPrimaryKeys() ! * ! * Retrieve the primary key columns for the specified table. */ RETCODE SQL_API SQLPrimaryKeys( *************** *** 2572,2578 **** while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { - row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); set_tuplefield_null(&row->tuple[0]); --- 2537,2542 ---- *************** *** 2608,2615 **** SQLFreeStmt(htbl_stmt, SQL_DROP); ! /* also, things need to think that this statement is finished so */ ! /* the results can be retrieved. */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ --- 2572,2581 ---- SQLFreeStmt(htbl_stmt, SQL_DROP); ! /* ! * also, things need to think that this statement is finished so ! * the results can be retrieved. ! */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ *************** *** 2621,2626 **** --- 2587,2593 ---- return SQL_SUCCESS; } + RETCODE SQL_API SQLForeignKeys( HSTMT hstmt, *************** *** 2667,2681 **** #if (ODBCVER >= 0x0300) SWORD defer_type; - #endif char pkey[MAX_INFO_STRING]; Int2 result_cols; - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) { SC_log_error(func, "", NULL); --- 2634,2645 ---- #if (ODBCVER >= 0x0300) SWORD defer_type; #endif char pkey[MAX_INFO_STRING]; Int2 result_cols; + mylog("%s: entering...stmt=%u\n", func, stmt); if (!stmt) { SC_log_error(func, "", NULL); *************** *** 2723,2730 **** QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2); #endif /* ODBCVER >= 0x0300 */ ! /* also, things need to think that this statement is finished so */ ! /* the results can be retrieved. */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ --- 2687,2696 ---- QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2); #endif /* ODBCVER >= 0x0300 */ ! /* ! * also, things need to think that this statement is finished so ! * the results can be retrieved. ! */ stmt->status = STMT_FINISHED; /* set up the current tuple pointer for SQLFetch */ *************** *** 2898,2904 **** while (result == SQL_SUCCESS) { - /* Compute the number of keyparts. */ num_keys = (trig_nargs - 4) / 2; --- 2864,2869 ---- *************** *** 2913,2919 **** /* If there is a pk table specified, then check it. */ if (pk_table_needed[0] != '\0') { - /* If it doesn't match, then continue */ if (strcmp(pk_table, pk_table_needed)) { --- 2878,2883 ---- *************** *** 2932,2938 **** return SQL_ERROR; } - /* Check that the key listed is the primary key */ keyresult = SQLFetch(hpkey_stmt); --- 2896,2901 ---- *************** *** 2949,2955 **** num_keys = 0; break; } - /* Get to next primary key */ for (k = 0; k < 2; k++) pkey_ptr += strlen(pkey_ptr) + 1; --- 2912,2917 ---- *************** *** 3002,3008 **** for (k = 0; k < num_keys; k++) { - row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr); --- 2964,2969 ---- *************** *** 3050,3056 **** */ else if (pk_table_needed[0] != '\0') { - sprintf(tables_query, "SELECT pg_trigger.tgargs, " " pg_trigger.tgnargs, " " pg_trigger.tgdeferrable, " --- 3011,3016 ---- *************** *** 3172,3178 **** while (result == SQL_SUCCESS) { - /* Calculate the number of key parts */ num_keys = (trig_nargs - 4) / 2;; --- 3132,3137 ---- *************** *** 3216,3222 **** for (i = 0; i < 5; i++) pkey_ptr += strlen(pkey_ptr) + 1; - /* Get to first foreign table */ fk_table = trig_args; fk_table += strlen(fk_table) + 1; --- 3175,3180 ---- *************** *** 3228,3234 **** for (k = 0; k < num_keys; k++) { - mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr); row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); --- 3186,3191 ---- *************** *** 3270,3276 **** fkey_ptr += strlen(fkey_ptr) + 1; } } - result = SQLFetch(htbl_stmt); } } --- 3227,3232 ---- *************** *** 3290,3296 **** } - RETCODE SQL_API SQLProcedureColumns( HSTMT hstmt, --- 3246,3251 ---- *************** *** 3311,3316 **** --- 3266,3272 ---- return SQL_ERROR; } + RETCODE SQL_API SQLProcedures( HSTMT hstmt, *************** *** 3328,3333 **** --- 3284,3290 ---- SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); return SQL_ERROR; } + RETCODE SQL_API SQLTablePrivileges( Index: src/interfaces/odbc/lobj.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/lobj.c,v retrieving revision 1.11 diff -c -r1.11 lobj.c *** src/interfaces/odbc/lobj.c 2001/03/27 04:00:54 1.11 --- src/interfaces/odbc/lobj.c 2001/03/28 16:53:17 *************** *** 1,4 **** ! /* Module: lobj.c * * Description: This module contains routines related to manipulating * large objects. --- 1,5 ---- ! /*-------- ! * Module: lobj.c * * Description: This module contains routines related to manipulating * large objects. *************** *** 8,14 **** * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #include "lobj.h" --- 9,15 ---- * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ #include "lobj.h" *************** *** 30,37 **** return 0; /* invalid oid */ else return retval; - - } int --- 31,36 ---- *************** *** 40,47 **** int fd; int result_len; LO_ARG argv[2]; ! ! argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = lobjId; --- 39,45 ---- int fd; int result_len; LO_ARG argv[2]; ! argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = lobjId; *************** *** 66,92 **** int retval, result_len; - argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = fd; if (!CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1)) return -1; - else return retval; - } - int lo_read(ConnectionClass *conn, int fd, char *buf, int len) { LO_ARG argv[2]; int result_len; - argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = fd; --- 64,85 ---- *************** *** 97,103 **** if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2)) return -1; - else return result_len; } --- 90,95 ---- *************** *** 109,115 **** int retval, result_len; - if (len <= 0) return 0; --- 101,106 ---- *************** *** 123,129 **** if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2)) return -1; - else return retval; } --- 114,119 ---- *************** *** 135,141 **** int retval, result_len; - argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = fd; --- 125,130 ---- *************** *** 150,156 **** if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3)) return -1; - else return retval; } --- 139,144 ---- *************** *** 162,175 **** int retval, result_len; - argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = fd; if (!CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1)) return -1; - else return retval; } --- 150,161 ---- *************** *** 181,194 **** int retval, result_len; - argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = lobjId; if (!CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1)) return -1; - else return retval; } --- 167,178 ---- Index: src/interfaces/odbc/misc.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/misc.c,v retrieving revision 1.20 diff -c -r1.20 misc.c *** src/interfaces/odbc/misc.c 2001/03/27 04:00:54 1.20 --- src/interfaces/odbc/misc.c 2001/03/28 16:53:17 *************** *** 1,4 **** ! /* Module: misc.c * * Description: This module contains miscellaneous routines * such as for debugging/logging and string functions. --- 1,5 ---- ! /*------- ! * Module: misc.c * * Description: This module contains miscellaneous routines * such as for debugging/logging and string functions. *************** *** 8,14 **** * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #include --- 9,15 ---- * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #include *************** *** 83,89 **** va_end(args); } } - #endif --- 84,89 ---- *************** *** 114,120 **** va_end(args); } } - #endif /* Undefine these because windows.h will redefine and cause a warning */ --- 114,119 ---- *************** *** 137,143 **** #endif ! /* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */ int my_strcpy(char *dst, int dst_len, char *src, int src_len) { --- 136,145 ---- #endif ! /* ! * returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied ! * (not including null term) ! */ int my_strcpy(char *dst, int dst_len, char *src, int src_len) { *************** *** 154,160 **** if (src_len <= 0) return STRCPY_FAIL; - else { if (src_len < dst_len) --- 156,161 ---- *************** *** 173,182 **** return strlen(dst); } ! /* strncpy copies up to len characters, and doesn't terminate */ ! /* the destination string if src has len characters or more. */ ! /* instead, I want it to copy up to len-1 characters and always */ ! /* terminate the destination string. */ char * strncpy_null(char *dst, const char *src, int len) { --- 174,185 ---- return strlen(dst); } ! /* ! * strncpy copies up to len characters, and doesn't terminate ! * the destination string if src has len characters or more. ! * instead, I want it to copy up to len-1 characters and always ! * terminate the destination string. ! */ char * strncpy_null(char *dst, const char *src, int len) { *************** *** 185,191 **** if (NULL != dst) { - /* Just in case, check for special lengths */ if (len == SQL_NULL_DATA) { --- 188,193 ---- *************** *** 204,212 **** return dst; } ! /* Create a null terminated string (handling the SQL_NTS thing): */ ! /* 1. If buf is supplied, place the string in there (assumes enough space) and return buf. */ ! /* 2. If buf is not supplied, malloc space and return this string */ char * make_string(char *s, int len, char *buf) { --- 206,218 ---- return dst; } ! /*------ ! * Create a null terminated string (handling the SQL_NTS thing): ! * 1. If buf is supplied, place the string in there ! * (assumes enough space) and return buf. ! * 2. If buf is not supplied, malloc space and return this string ! *------ ! */ char * make_string(char *s, int len, char *buf) { *************** *** 234,247 **** return NULL; } ! /* Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing. */ ! /* "fmt" must contain somewhere in it the single form '%.*s' */ ! /* This is heavily used in creating queries for info routines (SQLTables, SQLColumns). */ ! /* This routine could be modified to use vsprintf() to handle multiple arguments. */ char * my_strcat(char *buf, char *fmt, char *s, int len) { - if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) { int length = (len > 0) ? len : strlen(s); --- 240,254 ---- return NULL; } ! /* ! * Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing. ! * "fmt" must contain somewhere in it the single form '%.*s'. ! * This is heavily used in creating queries for info routines (SQLTables, SQLColumns). ! * This routine could be modified to use vsprintf() to handle multiple arguments. ! */ char * my_strcat(char *buf, char *fmt, char *s, int len) { if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) { int length = (len > 0) ? len : strlen(s); Index: src/interfaces/odbc/multibyte.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/multibyte.c,v retrieving revision 1.5 diff -c -r1.5 multibyte.c *** src/interfaces/odbc/multibyte.c 2001/03/27 04:00:54 1.5 --- src/interfaces/odbc/multibyte.c 2001/03/28 16:53:17 *************** *** 1,10 **** ! /* * Module : multibyte.c * * Description: Mlutibyte related additional function. * * Create 2001-03-03 Eiji Tokuya ! * */ #include --- 1,10 ---- ! /*-------- * Module : multibyte.c * * Description: Mlutibyte related additional function. * * Create 2001-03-03 Eiji Tokuya ! *-------- */ #include *************** *** 36,42 **** } break; - /* Chinese Big5 Support. */ case BIG5: { --- 36,41 ---- *************** *** 81,99 **** return ("OHTER"); } ! /* * Multibyte Status Function. * Input char * Output 0 : 1 Byte Character. * 1 : MultibyteCharacter Last Byte. * N : MultibyteCharacter Fast or Middle Byte. */ int multibyte_char_check(unsigned char s) { switch (multibyte_client_encoding) { ! /* Japanese Shift-JIS(CP932) Support. */ case SJIS: { if (multibyte_status < 2 && s > 0x80 && !(s > 0x9f && s < 0xE0)) --- 80,99 ---- return ("OHTER"); } ! /*-------- * Multibyte Status Function. * Input char * Output 0 : 1 Byte Character. * 1 : MultibyteCharacter Last Byte. * N : MultibyteCharacter Fast or Middle Byte. + *-------- */ int multibyte_char_check(unsigned char s) { switch (multibyte_client_encoding) { ! /* Japanese Shift-JIS(CP932) Support. */ case SJIS: { if (multibyte_status < 2 && s > 0x80 && !(s > 0x9f && s < 0xE0)) *************** *** 104,124 **** multibyte_status = 0; } break; - ! /* Chinese Big5(CP950) Support. */ ! case BIG5: ! { ! if (multibyte_status < 2 && s > 0xA0) ! multibyte_status = 2; ! else if (multibyte_status == 2) ! multibyte_status = 1; ! else ! multibyte_status = 0; ! } ! break; ! default: ! multibyte_status = 0; } #ifdef _DEBUG qlog("multibyte_client_encoding = %d s = 0x%02X multibyte_stat = %d\n", multibyte_client_encoding, s, multibyte_status); --- 104,123 ---- multibyte_status = 0; } break; ! /* Chinese Big5(CP950) Support. */ ! case BIG5: ! { ! if (multibyte_status < 2 && s > 0xA0) ! multibyte_status = 2; ! else if (multibyte_status == 2) ! multibyte_status = 1; ! else ! multibyte_status = 0; ! } ! break; ! default: ! multibyte_status = 0; } #ifdef _DEBUG qlog("multibyte_client_encoding = %d s = 0x%02X multibyte_stat = %d\n", multibyte_client_encoding, s, multibyte_status); Index: src/interfaces/odbc/options.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/options.c,v retrieving revision 1.27 diff -c -r1.27 options.c *** src/interfaces/odbc/options.c 2001/03/27 04:00:54 1.27 --- src/interfaces/odbc/options.c 2001/03/28 16:53:18 *************** *** 1,4 **** ! /* Module: options.c * * Description: This module contains routines for getting/setting * connection and statement options. --- 1,5 ---- ! /*-------- ! * Module: options.c * * Description: This module contains routines for getting/setting * connection and statement options. *************** *** 9,15 **** * SQLGetStmtOption * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 10,16 ---- * SQLGetStmtOption * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ #ifdef HAVE_CONFIG_H *************** *** 43,49 **** UDWORD vParam); - RETCODE set_statement_option(ConnectionClass *conn, StatementClass *stmt, --- 44,49 ---- *************** *** 53,59 **** static char *func = "set_statement_option"; char changed = FALSE; - switch (fOption) { case SQL_ASYNC_ENABLE: /* ignored */ --- 53,58 ---- *************** *** 68,79 **** break; case SQL_CONCURRENCY: - /* * positioned update isn't supported so cursor concurrency is * read-only */ - if (conn) conn->stmtOptions.scroll_concurrency = vParam; if (stmt) --- 67,76 ---- *************** *** 104,110 **** */ case SQL_CURSOR_TYPE: - /* * if declare/fetch, then type can only be forward. otherwise, * it can only be forward or static. --- 101,106 ---- *************** *** 113,130 **** if (globals.lie) { - if (conn) conn->stmtOptions.cursor_type = vParam; if (stmt) stmt->options.cursor_type = vParam; - } else { if (globals.use_declarefetch) { - if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY; if (stmt) --- 109,123 ---- *************** *** 137,143 **** { if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC) { - if (conn) conn->stmtOptions.cursor_type = vParam; /* valid type */ if (stmt) --- 130,135 ---- *************** *** 145,151 **** } else { - if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC; if (stmt) --- 137,142 ---- *************** *** 167,180 **** break; ! /* ! * if (globals.lie) stmt->keyset_size = vParam; else { ! * stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; ! * stmt->errormsg = "Driver does not support keyset size ! * option"; SC_log_error(func, "", stmt); return SQL_ERROR; } */ ! case SQL_MAX_LENGTH: /* ignored, but saved */ mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam); if (conn) conn->stmtOptions.maxLength = vParam; --- 158,177 ---- break; ! /*------- ! * if (globals.lie) ! * stmt->keyset_size = vParam; ! * else ! * { ! * stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; ! * stmt->errormsg = "Driver does not support keyset size option"; ! * SC_log_error(func, "", stmt); ! * return SQL_ERROR; ! * } ! *------- */ ! case SQL_MAX_LENGTH: /* ignored, but saved */ mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam); if (conn) conn->stmtOptions.maxLength = vParam; *************** *** 182,188 **** stmt->options.maxLength = vParam; break; ! case SQL_MAX_ROWS: /* ignored, but saved */ mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam); if (conn) conn->stmtOptions.maxRows = vParam; --- 179,185 ---- stmt->options.maxLength = vParam; break; ! case SQL_MAX_ROWS: /* ignored, but saved */ mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam); if (conn) conn->stmtOptions.maxRows = vParam; *************** *** 190,205 **** stmt->options.maxRows = vParam; break; ! case SQL_NOSCAN: /* ignored */ mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam); break; ! case SQL_QUERY_TIMEOUT:/* ignored */ mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam); /* "0" returned in SQLGetStmtOption */ break; ! case SQL_RETRIEVE_DATA:/* ignored, but saved */ mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam); if (conn) conn->stmtOptions.retrieve_data = vParam; --- 187,202 ---- stmt->options.maxRows = vParam; break; ! case SQL_NOSCAN: /* ignored */ mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam); break; ! case SQL_QUERY_TIMEOUT: /* ignored */ mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam); /* "0" returned in SQLGetStmtOption */ break; ! case SQL_RETRIEVE_DATA: /* ignored, but saved */ mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam); if (conn) conn->stmtOptions.retrieve_data = vParam; *************** *** 210,216 **** case SQL_ROWSET_SIZE: mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam); - /* * Save old rowset size for SQLExtendedFetch purposes If the * rowset_size is being changed since the last call to fetch --- 207,212 ---- *************** *** 230,236 **** conn->stmtOptions.rowset_size = vParam; if (stmt) stmt->options.rowset_size = vParam; - break; case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */ --- 226,231 ---- *************** *** 249,255 **** return SQL_ERROR; case SQL_USE_BOOKMARKS: - if (stmt) stmt->options.use_bookmarks = vParam; if (conn) --- 244,249 ---- *************** *** 298,304 **** } - /* Implements only SQL_AUTOCOMMIT */ RETCODE SQL_API SQLSetConnectOption( --- 292,297 ---- *************** *** 320,333 **** return SQL_INVALID_HANDLE; } - switch (fOption) { ! ! /* ! * Statement Options (apply to all stmts on the connection and ! * become defaults for new stmts) ! */ case SQL_ASYNC_ENABLE: case SQL_BIND_TYPE: case SQL_CONCURRENCY: --- 313,324 ---- return SQL_INVALID_HANDLE; } switch (fOption) { ! /* ! * Statement Options (apply to all stmts on the connection and ! * become defaults for new stmts) ! */ case SQL_ASYNC_ENABLE: case SQL_BIND_TYPE: case SQL_CONCURRENCY: *************** *** 362,376 **** break; ! /**********************************/ ! /***** Connection Options *******/ ! /**********************************/ case SQL_ACCESS_MODE: /* ignored */ break; case SQL_AUTOCOMMIT: - if (CC_is_in_trans(conn)) { conn->errormsg = "Cannot switch commit mode while a transaction is in progress"; --- 353,366 ---- break; ! /* ! * Connection Options ! */ case SQL_ACCESS_MODE: /* ignored */ break; case SQL_AUTOCOMMIT: if (CC_is_in_trans(conn)) { conn->errormsg = "Cannot switch commit mode while a transaction is in progress"; *************** *** 397,409 **** CC_log_error(func, "", conn); return SQL_ERROR; } - break; case SQL_CURRENT_QUALIFIER: /* ignored */ break; ! case SQL_LOGIN_TIMEOUT:/* ignored */ break; case SQL_PACKET_SIZE: /* ignored */ --- 387,398 ---- CC_log_error(func, "", conn); return SQL_ERROR; } break; case SQL_CURRENT_QUALIFIER: /* ignored */ break; ! case SQL_LOGIN_TIMEOUT: /* ignored */ break; case SQL_PACKET_SIZE: /* ignored */ *************** *** 412,421 **** case SQL_QUIET_MODE: /* ignored */ break; ! case SQL_TXN_ISOLATION:/* ignored */ break; ! /* These options should be handled by driver manager */ case SQL_ODBC_CURSORS: case SQL_OPT_TRACE: case SQL_OPT_TRACEFILE: --- 401,410 ---- case SQL_QUIET_MODE: /* ignored */ break; ! case SQL_TXN_ISOLATION: /* ignored */ break; ! /* These options should be handled by driver manager */ case SQL_ODBC_CURSORS: case SQL_OPT_TRACE: case SQL_OPT_TRACEFILE: *************** *** 434,440 **** CC_log_error(func, option, conn); return SQL_ERROR; } - } if (changed) --- 423,428 ---- *************** *** 447,453 **** return SQL_SUCCESS; } - /* - - - - - - - - - */ /* This function just can tell you whether you are in Autcommit mode or not */ RETCODE SQL_API --- 435,440 ---- *************** *** 469,475 **** switch (fOption) { ! case SQL_ACCESS_MODE: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE; break; --- 456,462 ---- switch (fOption) { ! case SQL_ACCESS_MODE: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE; break; *************** *** 484,506 **** break; ! case SQL_LOGIN_TIMEOUT:/* NOT SUPPORTED */ *((UDWORD *) pvParam) = 0; break; ! case SQL_PACKET_SIZE: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = globals.socket_buffersize; break; ! case SQL_QUIET_MODE: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = (UDWORD) NULL; break; ! case SQL_TXN_ISOLATION:/* NOT SUPPORTED */ *((UDWORD *) pvParam) = SQL_TXN_SERIALIZABLE; break; ! /* These options should be handled by driver manager */ case SQL_ODBC_CURSORS: case SQL_OPT_TRACE: case SQL_OPT_TRACEFILE: --- 471,493 ---- break; ! case SQL_LOGIN_TIMEOUT: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = 0; break; ! case SQL_PACKET_SIZE: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = globals.socket_buffersize; break; ! case SQL_QUIET_MODE: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = (UDWORD) NULL; break; ! case SQL_TXN_ISOLATION: /* NOT SUPPORTED */ *((UDWORD *) pvParam) = SQL_TXN_SERIALIZABLE; break; ! /* These options should be handled by driver manager */ case SQL_ODBC_CURSORS: case SQL_OPT_TRACE: case SQL_OPT_TRACEFILE: *************** *** 520,532 **** return SQL_ERROR; break; } - } return SQL_SUCCESS; } - /* - - - - - - - - - */ RETCODE SQL_API SQLSetStmtOption( --- 507,517 ---- *************** *** 538,548 **** StatementClass *stmt = (StatementClass *) hstmt; mylog("%s: entering...\n", func); - - /* thought we could fake Access out by just returning SQL_SUCCESS */ - /* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */ - /* and expects the driver to reduce it to the real value */ if (!stmt) { SC_log_error(func, "", NULL); --- 523,534 ---- StatementClass *stmt = (StatementClass *) hstmt; mylog("%s: entering...\n", func); + /* + * Though we could fake Access out by just returning SQL_SUCCESS + * all the time, but it tries to set a huge value for SQL_MAX_LENGTH + * and expects the driver to reduce it to the real value. + */ if (!stmt) { SC_log_error(func, "", NULL); *************** *** 553,560 **** } - /* - - - - - - - - - */ - RETCODE SQL_API SQLGetStmtOption( HSTMT hstmt, --- 539,544 ---- *************** *** 566,576 **** QResultClass *res; mylog("%s: entering...\n", func); - - /* thought we could fake Access out by just returning SQL_SUCCESS */ - /* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */ - /* and expects the driver to reduce it to the real value */ if (!stmt) { SC_log_error(func, "", NULL); --- 550,561 ---- QResultClass *res; mylog("%s: entering...\n", func); + /* + * thought we could fake Access out by just returning SQL_SUCCESS + * all the time, but it tries to set a huge value for SQL_MAX_LENGTH + * and expects the driver to reduce it to the real value + */ if (!stmt) { SC_log_error(func, "", NULL); *************** *** 689,693 **** return SQL_SUCCESS; } - - /* - - - - - - - - - */ --- 674,676 ---- Index: src/interfaces/odbc/parse.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/parse.c,v retrieving revision 1.16 diff -c -r1.16 parse.c *** src/interfaces/odbc/parse.c 2001/03/27 04:00:54 1.16 --- src/interfaces/odbc/parse.c 2001/03/28 16:53:18 *************** *** 1,20 **** ! /* Module: parse.c * ! * Description: This module contains routines related to parsing SQL statements. ! * This can be useful for two reasons: * ! * 1. So the query does not actually have to be executed to return data about it * ! * 2. To be able to return information about precision, nullability, aliases, etc. ! * in the functions SQLDescribeCol and SQLColAttributes. Currently, Postgres ! * doesn't return any information about these things in a query. * * Classes: none * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ /* Multibyte support Eiji Tokuya 2001-03-15 */ --- 1,24 ---- ! /*-------- ! * Module: parse.c * ! * Description: This module contains routines related to parsing SQL ! * statements. This can be useful for two reasons: * ! * 1. So the query does not actually have to be executed ! * to return data about it * ! * 2. To be able to return information about precision, ! * nullability, aliases, etc. in the functions ! * SQLDescribeCol and SQLColAttributes. Currently, ! * Postgres doesn't return any information about ! * these things in a query. * * Classes: none * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ /* Multibyte support Eiji Tokuya 2001-03-15 */ *************** *** 87,93 **** while (!isspace((unsigned char) s[i]) && s[i] != ',' && s[i] != '\0' && out != smax) { - /* Handle quoted stuff */ if (out == 0 && (s[i] == '\"' || s[i] == '\'')) { --- 91,96 ---- *************** *** 225,237 **** fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12)); } char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi) { int k; char *col; - for (k = 0; k < QR_get_num_tuples(col_info->result); k++) { col = QR_get_value_manual(col_info->result, k, 3); --- 228,240 ---- fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12)); } + char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi) { int k; char *col; for (k = 0; k < QR_get_num_tuples(col_info->result); k++) { col = QR_get_value_manual(col_info->result, k, 3); *************** *** 283,289 **** StatementClass *col_stmt; RETCODE result; - mylog("%s: entering...\n", func); ptr = stmt->statement; --- 286,291 ---- *************** *** 295,301 **** while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL) { - unquoted = !(quote || dquote); mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr); --- 297,302 ---- *************** *** 339,345 **** !stricmp(token, "group") || !stricmp(token, "having"))) { - in_select = FALSE; in_from = FALSE; in_where = TRUE; --- 340,345 ---- *************** *** 350,356 **** if (in_select) { - if (in_distinct) { mylog("in distinct\n"); --- 350,355 ---- *************** *** 372,378 **** } if (in_expr || in_func) ! { /* just eat the expression */ mylog("in_expr=%d or func=%d\n", in_expr, in_func); if (quote || dquote) continue; --- 371,378 ---- } if (in_expr || in_func) ! { ! /* just eat the expression */ mylog("in_expr=%d or func=%d\n", in_expr, in_func); if (quote || dquote) continue; *************** *** 383,389 **** in_expr = FALSE; in_field = FALSE; } - else if (token[0] == '(') { blevel++; --- 383,388 ---- *************** *** 405,411 **** if (!in_field) { - if (!token[0]) continue; --- 404,409 ---- *************** *** 453,459 **** blevel = 1; continue; } - else { strcpy(fi[stmt->nfld]->name, token); --- 451,456 ---- *************** *** 469,477 **** continue; } ! /**************************/ ! /* We are in a field now */ ! /**************************/ if (in_dot) { stmt->nfld--; --- 466,474 ---- continue; } ! /* ! * We are in a field now ! */ if (in_dot) { stmt->nfld--; *************** *** 485,491 **** mylog("in_dot: got comma\n"); in_field = FALSE; } - continue; } --- 482,487 ---- *************** *** 538,549 **** fi[stmt->nfld - 1]->expr = TRUE; fi[stmt->nfld - 1]->name[0] = '\0'; mylog("*** setting expression\n"); - } if (in_from) { - if (!in_table) { if (!token[0]) --- 534,543 ---- *************** *** 586,603 **** mylog("more than 1 tables\n"); } } - ! /*************************************************/ ! /* Resolve any possible field names with tables */ ! /*************************************************/ parse = TRUE; /* Resolve field names with tables */ for (i = 0; i < stmt->nfld; i++) { - if (fi[i]->func || fi[i]->expr || fi[i]->numeric) { fi[i]->ti = NULL; --- 580,595 ---- mylog("more than 1 tables\n"); } } ! /* ! * Resolve any possible field names with tables ! */ parse = TRUE; /* Resolve field names with tables */ for (i = 0; i < stmt->nfld; i++) { if (fi[i]->func || fi[i]->expr || fi[i]->numeric) { fi[i]->ti = NULL; *************** *** 605,611 **** parse = FALSE; continue; } - else if (fi[i]->quote) { /* handle as text */ fi[i]->ti = NULL; --- 597,602 ---- *************** *** 613,619 **** fi[i]->precision = 0; continue; } - /* it's a dot, resolve to table or alias */ else if (fi[i]->dot[0]) { --- 604,609 ---- *************** *** 648,663 **** for (i = 0; i < stmt->ntab; i++) mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias); - - /******************************************************/ - /* Now save the SQLColumns Info for the parse tables */ - /******************************************************/ /* Call SQLColumns for each table and store the result */ for (i = 0; i < stmt->ntab; i++) { - /* See if already got it */ char found = FALSE; --- 638,651 ---- for (i = 0; i < stmt->ntab; i++) mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias); + /* + * Now save the SQLColumns Info for the parse tables + */ /* Call SQLColumns for each table and store the result */ for (i = 0; i < stmt->ntab; i++) { /* See if already got it */ char found = FALSE; *************** *** 673,679 **** if (!found) { - mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name); result = SQLAllocStmt(stmt->hdbc, &hcol_stmt); --- 661,666 ---- *************** *** 697,703 **** mylog(" Success\n"); if (!(conn->ntables % COL_INCR)) { - mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables); conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *)); --- 684,689 ---- *************** *** 746,763 **** mylog("associate col_info: i=%d, k=%d\n", i, k); } - mylog("Done SQLColumns\n"); - - /******************************************************/ - /* Now resolve the fields to point to column info */ - /******************************************************/ - ! for (i = 0; i < stmt->nfld;) { - /* Dont worry about functions or quotes */ if (fi[i]->func || fi[i]->quote || fi[i]->numeric) { --- 732,744 ---- mylog("associate col_info: i=%d, k=%d\n", i, k); } mylog("Done SQLColumns\n"); ! /* ! * Now resolve the fields to point to column info ! */ for (i = 0; i < stmt->nfld;) { /* Dont worry about functions or quotes */ if (fi[i]->func || fi[i]->quote || fi[i]->numeric) { *************** *** 768,774 **** /* Stars get expanded to all fields in the table */ else if (fi[i]->name[0] == '*') { - char do_all_tables; int total_cols, old_alloc, --- 749,754 ---- *************** *** 794,800 **** increased_cols = total_cols - 1; /* Allocate some more field pointers if necessary */ - /*------------------------------------------------------------- */ old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR; new_size = stmt->nfld + increased_cols; --- 774,779 ---- *************** *** 814,821 **** stmt->fi = fi; } - /*------------------------------------------------------------- */ - /* * copy any other fields (if there are any) up past the * expansion --- 793,798 ---- *************** *** 827,847 **** } mylog("done copying fields\n"); - /*------------------------------------------------------------- */ /* Set the new number of fields */ stmt->nfld += increased_cols; mylog("stmt->nfld now at %d\n", stmt->nfld); - /*------------------------------------------------------------- */ /* copy the new field info */ - - do_all_tables = (fi[i]->ti ? FALSE : TRUE); for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++) { - TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti; cols = QR_get_num_tuples(the_ti->col_info->result); --- 804,819 ---- *************** *** 874,881 **** i += cols; mylog("i now at %d\n", i); } - - /*------------------------------------------------------------- */ } /* --- 846,851 ---- *************** *** 885,891 **** */ else if (fi[i]->ti) { - if (!searchColInfo(fi[i]->ti->col_info, fi[i])) parse = FALSE; --- 855,860 ---- *************** *** 909,920 **** } } - if (!parse) stmt->parse_status = STMT_PARSE_INCOMPLETE; else stmt->parse_status = STMT_PARSE_COMPLETE; - mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status); return parse; --- 878,887 ---- Index: src/interfaces/odbc/pgtypes.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/pgtypes.c,v retrieving revision 1.24 diff -c -r1.24 pgtypes.c *** src/interfaces/odbc/pgtypes.c 2001/03/27 04:00:54 1.24 --- src/interfaces/odbc/pgtypes.c 2001/03/28 16:53:18 *************** *** 1,17 **** ! /* Module: pgtypes.c * * Description: This module contains routines for getting information ! * about the supported Postgres data types. Only the function ! * pgtype_to_sqltype() returns an unknown condition. All other ! * functions return a suitable default so that even data types that ! * are not directly supported can be used (it is handled as char data). * * Classes: n/a * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 1,19 ---- ! /*-------- ! * Module: pgtypes.c * * Description: This module contains routines for getting information ! * about the supported Postgres data types. Only the ! * function pgtype_to_sqltype() returns an unknown condition. ! * All other functions return a suitable default so that ! * even data types that are not directly supported can be ! * used (it is handled as char data). * * Classes: n/a * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ #ifdef HAVE_CONFIG_H *************** *** 40,54 **** Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); ! /* these are the types we support. all of the pgtype_ functions should */ ! /* return values for each one of these. */ ! /* Even types not directly supported are handled as character types ! so all types should work (points, etc.) */ - /* ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all - the SQL TYPES are reported and mapped to a corresponding Postgres Type - */ /* Int4 pgtypes_defined[] = { PG_TYPE_CHAR, --- 42,59 ---- Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); + /* + * these are the types we support. all of the pgtype_ functions should + * return values for each one of these. + * Even types not directly supported are handled as character types + * so all types should work (points, etc.) + */ ! /* ! * ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all ! * the SQL TYPES are reported and mapped to a corresponding Postgres Type ! */ /* Int4 pgtypes_defined[] = { PG_TYPE_CHAR, *************** *** 109,115 **** switch (fSqlType) { - case SQL_BINARY: pgType = PG_TYPE_BYTEA; break; --- 114,119 ---- *************** *** 185,199 **** return pgType; } ! /* There are two ways of calling this function: ! 1. When going through the supported PG types (SQLGetTypeInfo) ! 2. When taking any type id (SQLColumns, SQLGetData) ! ! The first type will always work because all the types defined are returned here. ! The second type will return a default based on global parameter when it does not ! know. This allows for supporting ! types that are unknown. All other pg routines in here return a suitable default. ! */ Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) { --- 189,206 ---- return pgType; } ! /* ! * There are two ways of calling this function: ! * ! * 1. When going through the supported PG types (SQLGetTypeInfo) ! * ! * 2. When taking any type id (SQLColumns, SQLGetData) ! * ! * The first type will always work because all the types defined are returned here. ! * The second type will return a default based on global parameter when it does not ! * know. This allows for supporting ! * types that are unknown. All other pg routines in here return a suitable default. ! */ Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) { *************** *** 228,234 **** case PG_TYPE_INT4: return SQL_INTEGER; ! /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */ case PG_TYPE_INT8: return SQL_CHAR; --- 235,241 ---- case PG_TYPE_INT4: return SQL_INTEGER; ! /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */ case PG_TYPE_INT8: return SQL_CHAR; *************** *** 253,266 **** return globals.bools_as_char ? SQL_CHAR : SQL_BIT; default: - /* * first, check to see if 'type' is in list. If not, look up * with query. Add oid, name to list. If it's already in * list, just return. */ ! if (type == stmt->hdbc->lobj_type) /* hack until permanent ! * type is available */ return SQL_LONGVARBINARY; return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; --- 260,272 ---- return globals.bools_as_char ? SQL_CHAR : SQL_BIT; default: /* * first, check to see if 'type' is in list. If not, look up * with query. Add oid, name to list. If it's already in * list, just return. */ ! /* hack until permanent type is available */ ! if (type == stmt->hdbc->lobj_type) return SQL_LONGVARBINARY; return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; *************** *** 305,313 **** return SQL_C_BINARY; default: ! ! if (type == stmt->hdbc->lobj_type) /* hack until permanent ! * type is available */ return SQL_C_BINARY; return SQL_C_CHAR; --- 311,318 ---- return SQL_C_BINARY; default: ! /* hack until permanent type is available */ ! if (type == stmt->hdbc->lobj_type) return SQL_C_BINARY; return SQL_C_CHAR; *************** *** 319,325 **** { switch (type) { ! case PG_TYPE_CHAR:return "char"; case PG_TYPE_CHAR2: return "char2"; case PG_TYPE_CHAR4: --- 324,330 ---- { switch (type) { ! case PG_TYPE_CHAR:return "char"; case PG_TYPE_CHAR2: return "char2"; case PG_TYPE_CHAR4: *************** *** 369,376 **** return PG_TYPE_LO_NAME; default: ! if (type == stmt->hdbc->lobj_type) /* hack until permanent ! * type is available */ return PG_TYPE_LO_NAME; /* --- 374,381 ---- return PG_TYPE_LO_NAME; default: ! /* hack until permanent type is available */ ! if (type == stmt->hdbc->lobj_type) return PG_TYPE_LO_NAME; /* *************** *** 524,542 **** return p; } ! /* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will ! override this length with the atttypmod length from pg_attribute . ! ! If col >= 0, then will attempt to get the info from the result set. ! This is used for functions SQLDescribeCol and SQLColAttributes. ! */ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { - switch (type) { - case PG_TYPE_CHAR: return 1; case PG_TYPE_CHAR2: --- 529,546 ---- return p; } ! /* ! * For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will ! * override this length with the atttypmod length from pg_attribute . ! * ! * If col >= 0, then will attempt to get the info from the result set. ! * This is used for functions SQLDescribeCol and SQLColAttributes. ! */ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { switch (type) { case PG_TYPE_CHAR: return 1; case PG_TYPE_CHAR2: *************** *** 600,606 **** Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { - switch (type) { case PG_TYPE_INT2: --- 604,609 ---- *************** *** 628,649 **** case PG_TYPE_FLOAT8: return 22; ! /* Character types use regular precision */ default: return pgtype_precision(stmt, type, col, handle_unknown_size_as); } } ! /* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will ! override this length with the atttypmod length from pg_attribute ! */ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { - switch (type) { - case PG_TYPE_INT2: return 2; --- 631,651 ---- case PG_TYPE_FLOAT8: return 22; ! /* Character types use regular precision */ default: return pgtype_precision(stmt, type, col, handle_unknown_size_as); } } ! /* ! * For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will ! * override this length with the atttypmod length from pg_attribute ! */ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { switch (type) { case PG_TYPE_INT2: return 2; *************** *** 673,681 **** case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: return 16; - ! /* Character types (and NUMERIC) use the default precision */ default: return pgtype_precision(stmt, type, col, handle_unknown_size_as); } --- 675,682 ---- case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: return 16; ! /* Character types (and NUMERIC) use the default precision */ default: return pgtype_precision(stmt, type, col, handle_unknown_size_as); } *************** *** 686,692 **** { switch (type) { - case PG_TYPE_INT2: case PG_TYPE_OID: case PG_TYPE_XID: --- 687,692 ---- *************** *** 697,706 **** case PG_TYPE_MONEY: case PG_TYPE_BOOL: ! /* ! * Number of digits to the right of the decimal point in ! * "yyyy-mm=dd hh:mm:ss[.f...]" ! */ case PG_TYPE_ABSTIME: case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: --- 697,706 ---- case PG_TYPE_MONEY: case PG_TYPE_BOOL: ! /* ! * Number of digits to the right of the decimal point in ! * "yyyy-mm=dd hh:mm:ss[.f...]" ! */ case PG_TYPE_ABSTIME: case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: *************** *** 729,740 **** case PG_TYPE_MONEY: case PG_TYPE_FLOAT8: return 10; - default: return -1; } } Int2 pgtype_nullable(StatementClass *stmt, Int4 type) { --- 729,740 ---- case PG_TYPE_MONEY: case PG_TYPE_FLOAT8: return 10; default: return -1; } } + Int2 pgtype_nullable(StatementClass *stmt, Int4 type) { *************** *** 746,752 **** { switch (type) { - case PG_TYPE_INT2: case PG_TYPE_OID: case PG_TYPE_XID: --- 746,751 ---- *************** *** 853,859 **** { switch (type) { - case PG_TYPE_INT2: case PG_TYPE_OID: case PG_TYPE_XID: --- 852,857 ---- *************** *** 874,880 **** { switch (type) { - case PG_TYPE_INT2: case PG_TYPE_OID: case PG_TYPE_XID: --- 872,877 ---- *************** *** 895,902 **** { switch (type) { ! case PG_TYPE_CHAR: ! case PG_TYPE_VARCHAR:return "max. length"; default: return NULL; } --- 892,899 ---- { switch (type) { ! case PG_TYPE_CHAR: ! case PG_TYPE_VARCHAR:return "max. length"; default: return NULL; } *************** *** 906,913 **** Int2 sqltype_to_default_ctype(Int2 sqltype) { ! /* from the table on page 623 of ODBC 2.0 Programmer's Reference */ ! /* (Appendix D) */ switch (sqltype) { case SQL_CHAR: --- 903,912 ---- Int2 sqltype_to_default_ctype(Int2 sqltype) { ! /* ! * from the table on page 623 of ODBC 2.0 Programmer's Reference ! * (Appendix D) ! */ switch (sqltype) { case SQL_CHAR: *************** *** 951,957 **** case SQL_TIMESTAMP: return SQL_C_TIMESTAMP; ! default: /* should never happen */ return SQL_C_CHAR; } } --- 950,957 ---- case SQL_TIMESTAMP: return SQL_C_TIMESTAMP; ! default: ! /* should never happen */ return SQL_C_CHAR; } } Index: src/interfaces/odbc/psqlodbc.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/psqlodbc.c,v retrieving revision 1.15 diff -c -r1.15 psqlodbc.c *** src/interfaces/odbc/psqlodbc.c 2001/03/27 04:00:54 1.15 --- src/interfaces/odbc/psqlodbc.c 2001/03/28 16:53:19 *************** *** 1,15 **** ! /* Module: psqlodbc.c * ! * Description: This module contains the main entry point (DllMain) for the library. ! * It also contains functions to get and set global variables for the ! * driver in the registry. * * Classes: n/a * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 1,16 ---- ! /*-------- ! * Module: psqlodbc.c * ! * Description: This module contains the main entry point (DllMain) ! * for the library. It also contains functions to get ! * and set global variables for the driver in the registry. * * Classes: n/a * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ #ifdef HAVE_CONFIG_H *************** *** 59,65 **** if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { - WSACleanup(); return FALSE; } --- 60,65 ---- *************** *** 71,79 **** break; case DLL_PROCESS_DETACH: - WSACleanup(); - return TRUE; case DLL_THREAD_DETACH: --- 71,77 ---- *************** *** 111,117 **** #else /* not __GNUC__ */ ! /* These two functions do shared library initialziation on UNIX, well at least * on Linux. I don't know about other systems. */ BOOL --- 109,116 ---- #else /* not __GNUC__ */ ! /* ! * These two functions do shared library initialziation on UNIX, well at least * on Linux. I don't know about other systems. */ BOOL *************** *** 131,142 **** #endif /* not WIN32 */ ! /* This function is used to cause the Driver Manager to ! call functions by number rather than name, which is faster. ! The ordinal value of this function must be 199 to have the ! Driver Manager do this. Also, the ordinal values of the ! functions must match the value of fFunction in SQLGetFunctions() ! */ RETCODE SQL_API SQLDummyOrdinal(void) { --- 130,142 ---- #endif /* not WIN32 */ ! /* ! * This function is used to cause the Driver Manager to ! * call functions by number rather than name, which is faster. ! * The ordinal value of this function must be 199 to have the ! * Driver Manager do this. Also, the ordinal values of the ! * functions must match the value of fFunction in SQLGetFunctions() ! */ RETCODE SQL_API SQLDummyOrdinal(void) { Index: src/interfaces/odbc/qresult.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/qresult.c,v retrieving revision 1.21 diff -c -r1.21 qresult.c *** src/interfaces/odbc/qresult.c 2001/03/27 04:00:55 1.21 --- src/interfaces/odbc/qresult.c 2001/03/28 16:53:19 *************** *** 1,20 **** ! /* Module: qresult.c * * Description: This module contains functions related to ! * managing result information (i.e, fetching rows from the backend, ! * managing the tuple cache, etc.) and retrieving it. ! * Depending on the situation, a QResultClass will hold either data ! * from the backend or a manually built result (see "qresult.h" to ! * see which functions/macros are for manual or backend results. ! * For manually built results, the QResultClass simply points to ! * TupleList and ColumnInfo structures, which actually hold the data. * * Classes: QResultClass (Functions prefix: "QR_") * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #include "qresult.h" --- 1,23 ---- ! /*--------- ! * Module: qresult.c * * Description: This module contains functions related to ! * managing result information (i.e, fetching rows ! * from the backend, managing the tuple cache, etc.) ! * and retrieving it. Depending on the situation, a ! * QResultClass will hold either data from the backend ! * or a manually built result (see "qresult.h" to ! * see which functions/macros are for manual or backend ! * results. For manually built results, the ! * QResultClass simply points to TupleList and ! * ColumnInfo structures, which actually hold the data. * * Classes: QResultClass (Functions prefix: "QR_") * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *--------- */ #include "qresult.h" *************** *** 31,38 **** extern GLOBAL_VALUES globals; ! /* Used for building a Manual Result only */ ! /* All info functions call this function to create the manual result set. */ void QR_set_num_fields(QResultClass *self, int new_num_fields) { --- 34,43 ---- extern GLOBAL_VALUES globals; ! /* ! * Used for building a Manual Result only ! * All info functions call this function to create the manual result set. ! */ void QR_set_num_fields(QResultClass *self, int new_num_fields) { *************** *** 70,80 **** { self->base += base_inc; } - - /************************************/ - /* CLASS QResult */ - /************************************/ QResultClass * QR_Constructor(void) { --- 75,84 ---- { self->base += base_inc; } + /* + * CLASS QResult + */ QResultClass * QR_Constructor(void) { *************** *** 111,117 **** rv->cache_size = globals.fetch_max; rv->rowset_size = 1; - } mylog("exit QR_Constructor\n"); --- 115,120 ---- *************** *** 127,134 **** if (self->manual_tuples) TL_Destructor(self->manual_tuples); ! /* If conn is defined, then we may have used "backend_tuples", */ ! /* so in case we need to, free it up. Also, close the cursor. */ if (self->conn && self->conn->sock && CC_is_in_trans(self->conn)) QR_close(self); /* close the cursor if there is one */ --- 130,139 ---- if (self->manual_tuples) TL_Destructor(self->manual_tuples); ! /* ! * If conn is defined, then we may have used "backend_tuples", ! * so in case we need to, free it up. Also, close the cursor. ! */ if (self->conn && self->conn->sock && CC_is_in_trans(self->conn)) QR_close(self); /* close the cursor if there is one */ *************** *** 153,159 **** free(self); mylog("QResult: exit DESTRUCTOR\n"); - } void --- 158,163 ---- *************** *** 187,193 **** if (self->backend_tuples) { - for (row = 0; row < fcount; row++) { mylog("row = %d, num_fields = %d\n", row, num_fields); --- 191,196 ---- *************** *** 217,227 **** { int tuple_size; ! /* If called from send_query the first time (conn != NULL), */ ! /* then set the inTuples state, */ ! /* and read the tuples. If conn is NULL, */ ! /* it implies that we are being called from next_tuple(), */ ! /* like to get more rows so don't call next_tuple again! */ if (conn != NULL) { self->conn = conn; --- 220,232 ---- { int tuple_size; ! /* ! * If called from send_query the first time (conn != NULL), ! * then set the inTuples state, ! * and read the tuples. If conn is NULL, ! * it implies that we are being called from next_tuple(), ! * like to get more rows so don't call next_tuple again! ! */ if (conn != NULL) { self->conn = conn; *************** *** 242,249 **** self->cursor = strdup(cursor); } ! /* Read the field attributes. */ ! /* $$$$ Should do some error control HERE! $$$$ */ if (CI_read_fields(self->fields, self->conn)) { self->status = PGRES_FIELDS_OK; --- 247,257 ---- self->cursor = strdup(cursor); } ! /* ! * Read the field attributes. ! * ! * $$$$ Should do some error control HERE! $$$$ ! */ if (CI_read_fields(self->fields, self->conn)) { self->status = PGRES_FIELDS_OK; *************** *** 275,281 **** self->inTuples = TRUE; - /* Force a read to occur in next_tuple */ self->fcount = tuple_size + 1; self->fetch_count = tuple_size + 1; --- 283,288 ---- *************** *** 285,293 **** } else { ! ! /* Always have to read the field attributes. */ ! /* But we dont have to reallocate memory for them! */ if (!CI_read_fields(NULL, self->conn)) { --- 292,301 ---- } else { ! /* ! * Always have to read the field attributes. ! * But we dont have to reallocate memory for them! ! */ if (!CI_read_fields(NULL, self->conn)) { *************** *** 299,306 **** } } ! /* Close the cursor and end the transaction (if no cursors left) */ ! /* We only close cursor/end the transaction if a cursor was used. */ int QR_close(QResultClass *self) { --- 307,316 ---- } } ! /* ! * Close the cursor and end the transaction (if no cursors left) ! * We only close cursor/end the transaction if a cursor was used. ! */ int QR_close(QResultClass *self) { *************** *** 346,352 **** } QR_Destructor(res); } - } return TRUE; --- 356,361 ---- *************** *** 360,366 **** QResultClass *res; SocketClass *sock; ! /* Speed up access */ int fetch_count = self->fetch_count; int fcount = self->fcount; int fetch_size, --- 369,375 ---- QResultClass *res; SocketClass *sock; ! /* Speed up access */ int fetch_count = self->fetch_count; int fcount = self->fcount; int fetch_size, *************** *** 369,398 **** char corrected = FALSE; TupleField *the_tuples = self->backend_tuples; static char msgbuffer[MAX_MESSAGE_LEN + 1]; ! char cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups ! * this string so dont ! * need static */ char fetch[128]; QueryInfo qi; if (fetch_count < fcount) ! { /* return a row from cache */ mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount); self->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */ self->fetch_count++; return TRUE; } else if (self->fcount < self->cache_size) ! { /* last row from cache */ /* We are done because we didn't even get CACHE_SIZE tuples */ mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count); self->tupleField = NULL; self->status = PGRES_END_TUPLES; ! return -1; /* end of tuples */ } else { - /* * See if we need to fetch another group of rows. We may be being * called from send_query(), and if so, don't send another fetch, --- 378,408 ---- char corrected = FALSE; TupleField *the_tuples = self->backend_tuples; static char msgbuffer[MAX_MESSAGE_LEN + 1]; ! /* QR_set_command() dups this string so don't need static */ ! char cmdbuffer[MAX_MESSAGE_LEN + 1]; char fetch[128]; QueryInfo qi; if (fetch_count < fcount) ! { ! /* return a row from cache */ mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount); self->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */ self->fetch_count++; return TRUE; } else if (self->fcount < self->cache_size) ! { ! /* last row from cache */ /* We are done because we didn't even get CACHE_SIZE tuples */ mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count); self->tupleField = NULL; self->status = PGRES_END_TUPLES; ! /* end of tuples */ ! return -1; } else { /* * See if we need to fetch another group of rows. We may be being * called from send_query(), and if so, don't send another fetch, *************** *** 402,408 **** if (!self->inTuples) { - if (!globals.use_declarefetch) { mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count); --- 412,417 ---- *************** *** 412,419 **** } if (self->base == fcount) ! { /* not a correction */ ! /* Determine the optimum cache size. */ if (globals.fetch_max % self->rowset_size == 0) fetch_size = globals.fetch_max; --- 421,428 ---- } if (self->base == fcount) ! { ! /* not a correction */ /* Determine the optimum cache size. */ if (globals.fetch_max % self->rowset_size == 0) fetch_size = globals.fetch_max; *************** *** 426,433 **** self->fetch_count = 1; } else ! { /* need to correct */ ! corrected = TRUE; fetch_size = end_tuple - fcount; --- 435,442 ---- self->fetch_count = 1; } else ! { ! /* need to correct */ corrected = TRUE; fetch_size = end_tuple - fcount; *************** *** 436,445 **** offset = self->fetch_count; self->fetch_count++; - } - self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size); if (!self->backend_tuples) { --- 445,452 ---- *************** *** 483,499 **** self->fcount = 0; } - sock = CC_get_socket(self->conn); self->tupleField = NULL; for (;;) { - id = SOCK_get_char(sock); switch (id) { case 'T': /* Tuples within tuples cannot be handled */ self->status = PGRES_BAD_RESPONSE; QR_set_message(self, "Tuples within tuples cannot be handled"); --- 490,505 ---- self->fcount = 0; } sock = CC_get_socket(self->conn); self->tupleField = NULL; for (;;) { id = SOCK_get_char(sock); switch (id) { + case 'T': /* Tuples within tuples cannot be handled */ self->status = PGRES_BAD_RESPONSE; QR_set_message(self, "Tuples within tuples cannot be handled"); *************** *** 522,532 **** QR_set_message(self, "Error reading the tuple"); return FALSE; } - self->fcount++; break; /* continue reading */ - case 'C': /* End of tuple list */ SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN); QR_set_command(self, cmdbuffer); --- 528,536 ---- *************** *** 536,542 **** self->inTuples = FALSE; if (self->fcount > 0) { - qlog(" [ fetched %d rows ]\n", self->fcount); mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount); --- 540,545 ---- *************** *** 545,552 **** return TRUE; } else ! { /* We are surely done here (we read 0 ! * tuples) */ qlog(" [ fetched 0 rows ]\n"); mylog("_next_tuple: 'C': DONE (fcount == 0)\n"); return -1; /* end of tuples */ --- 548,555 ---- return TRUE; } else ! { ! /* We are surely done here (we read 0 tuples) */ qlog(" [ fetched 0 rows ]\n"); mylog("_next_tuple: 'C': DONE (fcount == 0)\n"); return -1; /* end of tuples */ *************** *** 600,606 **** SocketClass *sock = CC_get_socket(self->conn); ColumnInfoClass *flds; - /* set the current row to read the fields into */ this_tuplefield = self->backend_tuples + (self->fcount * num_fields); --- 603,608 ---- *************** *** 629,635 **** } else { - /* * NO, the field is not null. so get at first the length of * the field (four bytes) --- 631,636 ---- Index: src/interfaces/odbc/results.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/results.c,v retrieving revision 1.27 diff -c -r1.27 results.c *** src/interfaces/odbc/results.c 2001/03/27 04:00:55 1.27 --- src/interfaces/odbc/results.c 2001/03/28 16:53:20 *************** *** 1,17 **** ! /* Module: results.c * * Description: This module contains functions related to * retrieving result information through the ODBC API. * * Classes: n/a * ! * API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol, SQLColAttributes, ! * SQLGetData, SQLFetch, SQLExtendedFetch, * SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI), * SQLSetCursorName, SQLGetCursorName * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 1,18 ---- ! /*------- ! * Module: results.c * * Description: This module contains functions related to * retrieving result information through the ODBC API. * * Classes: n/a * ! * API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol, ! * SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch, * SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI), * SQLSetCursorName, SQLGetCursorName * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #ifdef HAVE_CONFIG_H *************** *** 42,48 **** extern GLOBAL_VALUES globals; - RETCODE SQL_API SQLRowCount( HSTMT hstmt, --- 43,48 ---- *************** *** 81,87 **** } else { - res = SC_get_Result(stmt); if (res && pcrow) { --- 81,86 ---- *************** *** 97,103 **** else { *pcrow = -1; - mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow); } --- 96,101 ---- *************** *** 110,117 **** } ! /* This returns the number of columns associated with the database */ ! /* attached to "hstmt". */ RETCODE SQL_API --- 108,117 ---- } ! /* ! * This returns the number of columns associated with the database ! * attached to "hstmt". ! */ RETCODE SQL_API *************** *** 135,141 **** parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { - if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt); --- 135,140 ---- *************** *** 152,158 **** if (!parse_ok) { - SC_pre_execute(stmt); result = SC_get_Result(stmt); --- 151,156 ---- *************** *** 172,184 **** return SQL_SUCCESS; } - - /* - - - - - - - - - */ - ! ! /* Return information about the database column the user wants */ ! /* information about. */ RETCODE SQL_API SQLDescribeCol( HSTMT hstmt, --- 170,180 ---- return SQL_SUCCESS; } ! /* ! * Return information about the database column the user wants ! * information about. ! */ RETCODE SQL_API SQLDescribeCol( HSTMT hstmt, *************** *** 205,211 **** int len = 0; RETCODE result; - mylog("%s: entering...\n", func); if (!stmt) --- 201,206 ---- *************** *** 219,247 **** SC_clear_error(stmt); /* ! * Dont check for bookmark column. This is the responsibility of the ! * driver manager. */ icol--; /* use zero based column numbers */ - parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { - if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt); parse_statement(stmt); } - mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi); if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) { - if (icol >= stmt->nfld) { stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; --- 214,238 ---- SC_clear_error(stmt); /* ! * Dont check for bookmark column. This is the responsibility of the ! * driver manager. */ icol--; /* use zero based column numbers */ parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt); parse_statement(stmt); } mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi); if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) { if (icol >= stmt->nfld) { stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; *************** *** 261,271 **** } } - /* ! * If couldn't parse it OR the field being described was not parsed ! * (i.e., because it was a function or expression, etc, then do it the ! * old fashioned way. */ if (!parse_ok) { --- 252,261 ---- } } /* ! * If couldn't parse it OR the field being described was not parsed ! * (i.e., because it was a function or expression, etc, then do it the ! * old fashioned way. */ if (!parse_ok) { *************** *** 295,314 **** col_name = QR_get_fieldname(res, icol); fieldtype = QR_get_field_type(res, icol); ! precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); /* atoi(ci->unknown_sizes ! * ) */ ! } mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name); mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype); mylog("describeCol: col %d precision = %d\n", icol, precision); - result = SQL_SUCCESS; ! /************************/ ! /* COLUMN NAME */ ! /************************/ len = strlen(col_name); if (pcbColName) --- 285,303 ---- col_name = QR_get_fieldname(res, icol); fieldtype = QR_get_field_type(res, icol); ! /* atoi(ci->unknown_sizes) */ ! precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); ! } mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name); mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype); mylog("describeCol: col %d precision = %d\n", icol, precision); result = SQL_SUCCESS; ! /* ! * COLUMN NAME ! */ len = strlen(col_name); if (pcbColName) *************** *** 325,335 **** stmt->errormsg = "The buffer was too small for the result."; } } - ! /************************/ ! /* SQL TYPE */ ! /************************/ if (pfSqlType) { *pfSqlType = pgtype_to_sqltype(stmt, fieldtype); --- 314,323 ---- stmt->errormsg = "The buffer was too small for the result."; } } ! /* ! * SQL TYPE ! */ if (pfSqlType) { *pfSqlType = pgtype_to_sqltype(stmt, fieldtype); *************** *** 337,348 **** mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType); } ! /************************/ ! /* PRECISION */ ! /************************/ if (pcbColDef) { - if (precision < 0) precision = 0; /* "I dont know" */ --- 325,335 ---- mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType); } ! /* ! * PRECISION ! */ if (pcbColDef) { if (precision < 0) precision = 0; /* "I dont know" */ *************** *** 351,359 **** mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef); } ! /************************/ ! /* SCALE */ ! /************************/ if (pibScale) { Int2 scale; --- 338,346 ---- mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef); } ! /* ! * SCALE ! */ if (pibScale) { Int2 scale; *************** *** 366,374 **** mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale); } ! /************************/ ! /* NULLABILITY */ ! /************************/ if (pfNullable) { *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype); --- 353,361 ---- mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale); } ! /* ! * NULLABILITY ! */ if (pfNullable) { *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype); *************** *** 421,436 **** icol--; ! unknown_sizes = globals.unknown_sizes; /* atoi(ci->unknown_sizes); ! * */ ! if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) /* not appropriate for ! * SQLColAttributes() */ unknown_sizes = UNKNOWNS_AS_MAX; parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { - if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLColAttributes: calling parse_statement\n"); --- 408,423 ---- icol--; ! /* atoi(ci->unknown_sizes); */ ! unknown_sizes = globals.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 (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLColAttributes: calling parse_statement\n"); *************** *** 453,459 **** if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) { - if (icol >= cols) { stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; --- 440,445 ---- *************** *** 461,467 **** SC_log_error(func, "", stmt); return SQL_ERROR; } - field_type = stmt->fi[icol]->type; if (field_type > 0) parse_ok = TRUE; --- 447,452 ---- *************** *** 521,533 **** case SQL_COLUMN_CASE_SENSITIVE: value = pgtype_case_sensitive(stmt, field_type); break; - - /* - * This special case is handled above. - * - * case SQL_COLUMN_COUNT: - */ case SQL_COLUMN_DISPLAY_SIZE: value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes); --- 506,517 ---- case SQL_COLUMN_CASE_SENSITIVE: value = pgtype_case_sensitive(stmt, field_type); break; + /* + * This special case is handled above. + * + * case SQL_COLUMN_COUNT: + */ case SQL_COLUMN_DISPLAY_SIZE: value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes); *************** *** 543,553 **** mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p); break; ! } /* otherwise same as column name -- FALL ! * THROUGH!!! */ case SQL_COLUMN_NAME: - p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol); mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p); --- 527,536 ---- mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p); break; ! } ! /* otherwise same as column name -- FALL THROUGH!!! */ case SQL_COLUMN_NAME: p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol); mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p); *************** *** 590,596 **** break; case SQL_COLUMN_TABLE_NAME: - p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : ""; mylog("SQLColAttr: TABLE_NAME = '%s'\n", p); --- 573,578 ---- *************** *** 612,625 **** break; case SQL_COLUMN_UPDATABLE: - /* * Neither Access or Borland care about this. * * if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY; * else */ - value = SQL_ATTR_WRITE; mylog("SQLColAttr: UPDATEABLE = %d\n", value); --- 594,605 ---- *************** *** 648,665 **** *pcbDesc = len; } else ! { /* numeric data */ ! if (pfDesc) *pfDesc = value; - } - return result; } ! /* Returns result data for a single column in the current row. */ RETCODE SQL_API SQLGetData( --- 628,643 ---- *pcbDesc = len; } else ! { ! /* numeric data */ if (pfDesc) *pfDesc = value; } return result; } ! /* Returns result data for a single column in the current row. */ RETCODE SQL_API SQLGetData( *************** *** 707,713 **** if (icol == 0) { - if (stmt->options.use_bookmarks == SQL_UB_OFF) { stmt->errornumber = STMT_COLNUM_ERROR; --- 685,690 ---- *************** *** 726,737 **** } get_bookmark = TRUE; - } - else { - /* use zero-based column numbers */ icol--; --- 703,711 ---- *************** *** 770,776 **** } } else ! { /* it's a SOCKET result (backend data) */ if (stmt->currTuple == -1 || !res || !res->tupleField) { stmt->errormsg = "Not positioned on a valid row for GetData."; --- 744,751 ---- } } else ! { ! /* it's a SOCKET result (backend data) */ if (stmt->currTuple == -1 || !res || !res->tupleField) { stmt->errormsg = "Not positioned on a valid row for GetData."; *************** *** 844,854 **** } } - ! /* Returns data for bound columns in the current row ("hstmt->iCursor"), */ ! /* advances the cursor. */ ! RETCODE SQL_API SQLFetch( HSTMT hstmt) --- 819,829 ---- } } ! /* ! * Returns data for bound columns in the current row ("hstmt->iCursor"), ! * advances the cursor. ! */ RETCODE SQL_API SQLFetch( HSTMT hstmt) *************** *** 892,898 **** return SQL_ERROR; } - if (stmt->status != STMT_FINISHED) { stmt->errornumber = STMT_STATUS_ERROR; --- 867,872 ---- *************** *** 917,924 **** return SC_fetch(stmt); } ! /* This fetchs a block of data (rowset). */ ! RETCODE SQL_API SQLExtendedFetch( HSTMT hstmt, --- 891,897 ---- return SC_fetch(stmt); } ! /* This fetchs a block of data (rowset). */ RETCODE SQL_API SQLExtendedFetch( HSTMT hstmt, *************** *** 1020,1026 **** switch (fFetchType) { case SQL_FETCH_NEXT: - /* * From the odbc spec... If positioned before the start of the * RESULT SET, then this should be equivalent to --- 993,998 ---- *************** *** 1031,1066 **** stmt->rowset_start = 0; else - { - stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size); - } mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); break; case SQL_FETCH_PRIOR: mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); - - /* * From the odbc spec... If positioned after the end of the * RESULT SET, then this should be equivalent to * SQL_FETCH_LAST. */ - if (stmt->rowset_start >= num_tuples) { stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size); } else - { - stmt->rowset_start -= stmt->options.rowset_size; - - } - break; case SQL_FETCH_FIRST: --- 1003,1027 ---- *************** *** 1091,1101 **** /* Position with respect to the end of the result set */ else stmt->rowset_start = num_tuples + irow; - break; case SQL_FETCH_RELATIVE: - /* * Refresh the current rowset -- not currently implemented, * but lie anyway --- 1052,1060 ---- *************** *** 1104,1128 **** break; stmt->rowset_start += irow; - - break; case SQL_FETCH_BOOKMARK: - stmt->rowset_start = irow - 1; break; default: SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt); return SQL_ERROR; - } ! ! /***********************************/ ! /* CHECK FOR PROPER CURSOR STATE */ ! /***********************************/ /* * Handle Declare Fetch style specially because the end is not really --- 1063,1082 ---- break; stmt->rowset_start += irow; break; case SQL_FETCH_BOOKMARK: stmt->rowset_start = irow - 1; break; default: SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt); return SQL_ERROR; } ! /* ! * CHECK FOR PROPER CURSOR STATE ! */ /* * Handle Declare Fetch style specially because the end is not really *************** *** 1172,1178 **** truncated = error = FALSE; for (i = 0; i < stmt->options.rowset_size; i++) { - stmt->bind_row = i; /* set the binding location */ result = SC_fetch(stmt); --- 1126,1131 ---- *************** *** 1212,1232 **** *pcrow = i; if (i == 0) ! return SQL_NO_DATA_FOUND; /* Only DeclareFetch should wind ! * up here */ else if (error) return SQL_ERROR; else if (truncated) return SQL_SUCCESS_WITH_INFO; else return SQL_SUCCESS; - } - - /* This determines whether there are more results sets available for */ - /* the "hstmt". */ /* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */ RETCODE SQL_API SQLMoreResults( --- 1165,1185 ---- *pcrow = i; if (i == 0) ! /* Only DeclareFetch should wind up here */ ! return SQL_NO_DATA_FOUND; else if (error) return SQL_ERROR; else if (truncated) return SQL_SUCCESS_WITH_INFO; else return SQL_SUCCESS; } + /* + * This determines whether there are more results sets available for + * the "hstmt". + */ /* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */ RETCODE SQL_API SQLMoreResults( *************** *** 1235,1242 **** return SQL_NO_DATA_FOUND; } ! /* This positions the cursor within a rowset, that was positioned using SQLExtendedFetch. */ ! /* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch. */ RETCODE SQL_API SQLSetPos( HSTMT hstmt, --- 1188,1197 ---- return SQL_NO_DATA_FOUND; } ! /* ! * This positions the cursor within a rowset, that was positioned using SQLExtendedFetch. ! * This will be useful (so far) only when using SQLGetData after SQLExtendedFetch. ! */ RETCODE SQL_API SQLSetPos( HSTMT hstmt, *************** *** 1301,1311 **** stmt->currTuple = stmt->rowset_start + irow; return SQL_SUCCESS; - } /* Sets options that control the behavior of cursors. */ - RETCODE SQL_API SQLSetScrollOptions( HSTMT hstmt, --- 1256,1264 ---- *************** *** 1319,1327 **** return SQL_ERROR; } - - /* Set the cursor name on a statement handle */ RETCODE SQL_API SQLSetCursorName( HSTMT hstmt, --- 1272,1279 ---- return SQL_ERROR; } + /* Set the cursor name on a statement handle */ RETCODE SQL_API SQLSetCursorName( HSTMT hstmt, *************** *** 1354,1361 **** return SQL_SUCCESS; } - /* Return the cursor name for a statement handle */ RETCODE SQL_API SQLGetCursorName( HSTMT hstmt, --- 1306,1313 ---- return SQL_SUCCESS; } + /* Return the cursor name for a statement handle */ RETCODE SQL_API SQLGetCursorName( HSTMT hstmt, Index: src/interfaces/odbc/setup.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/setup.c,v retrieving revision 1.17 diff -c -r1.17 setup.c *** src/interfaces/odbc/setup.c 2001/03/27 04:00:55 1.17 --- src/interfaces/odbc/setup.c 2001/03/28 16:53:22 *************** *** 1,4 **** ! /* Module: setup.c * * Description: This module contains the setup functions for * adding/modifying a Data Source in the ODBC.INI portion --- 1,5 ---- ! /*------- ! * Module: setup.c * * Description: This module contains the setup functions for * adding/modifying a Data Source in the ODBC.INI portion *************** *** 9,15 **** * API functions: ConfigDSN * * Comments: See "notice.txt" for copyright and license information. ! * */ #include "psqlodbc.h" --- 10,16 ---- * API functions: ConfigDSN * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #include "psqlodbc.h" *************** *** 28,34 **** extern HINSTANCE NEAR s_hModule;/* Saved module handle. */ extern GLOBAL_VALUES globals; ! /* Constants --------------------------------------------------------------- */ #define MIN(x,y) ((x) < (y) ? (x) : (y)) #ifdef WIN32 --- 29,35 ---- extern HINSTANCE NEAR s_hModule;/* Saved module handle. */ extern GLOBAL_VALUES globals; ! /* Constants */ #define MIN(x,y) ((x) < (y) ? (x) : (y)) #ifdef WIN32 *************** *** 40,46 **** #define MAXDSNAME (32+1) /* Max data source name length */ ! /* Globals ----------------------------------------------------------------- */ /* NOTE: All these are used by the dialog procedures */ typedef struct tagSETUPDLG { --- 41,47 ---- #define MAXDSNAME (32+1) /* Max data source name length */ ! /* Globals */ /* NOTE: All these are used by the dialog procedures */ typedef struct tagSETUPDLG { *************** *** 55,77 **** ! /* Prototypes -------------------------------------------------------------- */ void INTFUNC CenterDialog(HWND hdlg); int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam); void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg); BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg); ! /* ConfigDSN --------------------------------------------------------------- ! Description: ODBC Setup entry point ! This entry point is called by the ODBC Installer ! (see file header for more details) ! Input : hwnd ----------- Parent window handle ! fRequest ------- Request type (i.e., add, config, or remove) ! lpszDriver ----- Driver name ! lpszAttributes - data source attribute string ! Output : TRUE success, FALSE otherwise ! --------------------------------------------------------------------------*/ BOOL CALLBACK ConfigDSN(HWND hwnd, --- 56,81 ---- ! /* Prototypes */ void INTFUNC CenterDialog(HWND hdlg); int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam); void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg); BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg); ! /*-------- ! * ConfigDSN ! * ! * Description: ODBC Setup entry point ! * This entry point is called by the ODBC Installer ! * (see file header for more details) ! * Input : hwnd ----------- Parent window handle ! * fRequest ------- Request type (i.e., add, config, or remove) ! * lpszDriver ----- Driver name ! * lpszAttributes - data source attribute string ! * Output : TRUE success, FALSE otherwise ! *-------- ! */ BOOL CALLBACK ConfigDSN(HWND hwnd, *************** *** 111,117 **** else fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn); } - /* Add or Configure data source */ else { --- 115,120 ---- *************** *** 134,140 **** ConfigDlgProc, (LONG) (LPSTR) lpsetupdlg)); } - else if (lpsetupdlg->ci.dsn[0]) fSuccess = SetDSNAttributes(hwnd, lpsetupdlg); else --- 137,142 ---- *************** *** 148,158 **** } ! /* CenterDialog ------------------------------------------------------------ ! Description: Center the dialog over the frame window ! Input : hdlg -- Dialog window handle ! Output : None ! --------------------------------------------------------------------------*/ void INTFUNC CenterDialog(HWND hdlg) { --- 150,163 ---- } ! /*------- ! * CenterDialog ! * ! * Description: Center the dialog over the frame window ! * Input : hdlg -- Dialog window handle ! * Output : None ! *------- ! */ void INTFUNC CenterDialog(HWND hdlg) { *************** *** 197,220 **** MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE); return; } - - /* ConfigDlgProc ----------------------------------------------------------- - Description: Manage add data source name dialog - Input : hdlg --- Dialog window handle - wMsg --- Message - wParam - Message parameter - lParam - Message parameter - Output : TRUE if message processed, FALSE otherwise - --------------------------------------------------------------------------*/ ! int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam) { - switch (wMsg) { /* Initialize the dialog */ --- 202,224 ---- MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE); return; } ! /*------- ! * ConfigDlgProc ! * Description: Manage add data source name dialog ! * Input : hdlg --- Dialog window handle ! * wMsg --- Message ! * wParam - Message parameter ! * lParam - Message parameter ! * Output : TRUE if message processed, FALSE otherwise ! *------- ! */ int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg) { /* Initialize the dialog */ *************** *** 241,251 **** /* Fill in any defaults */ getDSNdefaults(ci); - /* Initialize dialog fields */ SetDlgStuff(hdlg, ci); - if (lpsetupdlg->fDefault) { EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE); --- 245,253 ---- *************** *** 259,272 **** EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); return TRUE; /* Focus was not set */ } - ! /* Process buttons */ case WM_COMMAND: - switch (GET_WM_COMMAND_ID(wParam, lParam)) { - /* * Ensure the OK button is enabled only when a data * source name --- 261,271 ---- EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); return TRUE; /* Focus was not set */ } ! /* Process buttons */ case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { /* * Ensure the OK button is enabled only when a data * source name *************** *** 281,292 **** EnableWindow(GetDlgItem(hdlg, IDOK), GetDlgItemText(hdlg, IDC_DSNAME, szItem, sizeof(szItem))); - return TRUE; } break; ! /* Accept results */ case IDOK: { LPSETUPDLG lpsetupdlg; --- 280,290 ---- EnableWindow(GetDlgItem(hdlg, IDOK), GetDlgItemText(hdlg, IDC_DSNAME, szItem, sizeof(szItem))); return TRUE; } break; ! /* Accept results */ case IDOK: { LPSETUPDLG lpsetupdlg; *************** *** 297,304 **** GetDlgItemText(hdlg, IDC_DSNAME, lpsetupdlg->ci.dsn, sizeof(lpsetupdlg->ci.dsn)); - - /* Get Dialog Values */ GetDlgStuff(hdlg, &lpsetupdlg->ci); --- 295,300 ---- *************** *** 306,318 **** SetDSNAttributes(hdlg, lpsetupdlg); } ! /* Return to caller */ case IDCANCEL: EndDialog(hdlg, wParam); return TRUE; case IDC_DRIVER: - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), hdlg, driver_optionsProc, (LPARAM) NULL); --- 302,313 ---- SetDSNAttributes(hdlg, lpsetupdlg); } ! /* Return to caller */ case IDCANCEL: EndDialog(hdlg, wParam); return TRUE; case IDC_DRIVER: DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), hdlg, driver_optionsProc, (LPARAM) NULL); *************** *** 330,336 **** return TRUE; } } - break; } --- 325,330 ---- *************** *** 339,349 **** } ! /* ParseAttributes --------------------------------------------------------- ! Description: Parse attribute string moving values into the aAttr array ! Input : lpszAttributes - Pointer to attribute string ! Output : None (global aAttr normally updated) ! --------------------------------------------------------------------------*/ void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg) { --- 333,346 ---- } ! /*------- ! * ParseAttributes ! * ! * Description: Parse attribute string moving values into the aAttr array ! * Input : lpszAttributes - Pointer to attribute string ! * Output : None (global aAttr normally updated) ! *------- ! */ void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg) { *************** *** 356,363 **** memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo)); for (lpsz = lpszAttributes; *lpsz; lpsz++) ! { /* Extract key name (e.g., DSN), it must ! * be terminated by an equals */ lpszStart = lpsz; for (;; lpsz++) { --- 353,360 ---- memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo)); for (lpsz = lpszAttributes; *lpsz; lpsz++) ! { ! /* Extract key name (e.g., DSN), it must be terminated by an equals */ lpszStart = lpsz; for (;; lpsz++) { *************** *** 370,384 **** cbKey = lpsz - lpszStart; if (cbKey < sizeof(aszKey)) { - _fmemcpy(aszKey, lpszStart, cbKey); aszKey[cbKey] = '\0'; } /* Locate end of key value */ lpszStart = ++lpsz; ! for (; *lpsz; lpsz++); ! /* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */ _fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH)); --- 367,380 ---- cbKey = lpsz - lpszStart; if (cbKey < sizeof(aszKey)) { _fmemcpy(aszKey, lpszStart, cbKey); aszKey[cbKey] = '\0'; } /* Locate end of key value */ lpszStart = ++lpsz; ! for (; *lpsz; lpsz++) ! ; /* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */ _fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH)); *************** *** 392,403 **** } ! /* SetDSNAttributes -------------------------------------------------------- ! Description: Write data source attributes to ODBC.INI ! Input : hwnd - Parent window handle (plus globals) ! Output : TRUE if successful, FALSE otherwise ! --------------------------------------------------------------------------*/ ! BOOL INTFUNC SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg) { --- 388,401 ---- } ! /*-------- ! * SetDSNAttributes ! * ! * Description: Write data source attributes to ODBC.INI ! * Input : hwnd - Parent window handle (plus globals) ! * Output : TRUE if successful, FALSE otherwise ! *-------- ! */ BOOL INTFUNC SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg) { *************** *** 425,434 **** return FALSE; } - /* Update ODBC.INI */ writeDSNinfo(&lpsetupdlg->ci); - /* If the data source name has changed, remove the old name */ if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn)) --- 423,430 ---- Index: src/interfaces/odbc/socket.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/socket.c,v retrieving revision 1.22 diff -c -r1.22 socket.c *** src/interfaces/odbc/socket.c 2001/03/27 04:00:55 1.22 --- src/interfaces/odbc/socket.c 2001/03/28 16:53:22 *************** *** 1,4 **** ! /* Module: socket.c * * Description: This module contains functions for low level socket * operations (connecting/reading/writing to the backend) --- 1,5 ---- ! /*------- ! * Module: socket.c * * Description: This module contains functions for low level socket * operations (connecting/reading/writing to the backend) *************** *** 8,14 **** * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 9,15 ---- * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #ifdef HAVE_CONFIG_H *************** *** 70,83 **** free(rv); return NULL; } - rv->errormsg = NULL; rv->errornumber = 0; - rv->reverse = FALSE; } return rv; - } void --- 71,81 ---- *************** *** 97,103 **** free(self->buffer_out); free(self); - } --- 95,100 ---- *************** *** 149,155 **** if (connect(self->socket, (struct sockaddr *) & (sadr), sizeof(sadr)) < 0) { - self->errornumber = SOCKET_COULD_NOT_CONNECT; self->errormsg = "Could not connect to remote socket."; closesocket(self->socket); --- 146,151 ---- *************** *** 194,202 **** } ! /* bufsize must include room for the null terminator ! will read at most bufsize-1 characters + null. ! */ void SOCK_get_string(SocketClass *self, char *buffer, int bufsize) { --- 190,199 ---- } ! /* ! * bufsize must include room for the null terminator ! * will read at most bufsize-1 characters + null. ! */ void SOCK_get_string(SocketClass *self, char *buffer, int bufsize) { *************** *** 300,311 **** unsigned char SOCK_get_next_byte(SocketClass *self) { - if (self->buffer_read_in >= self->buffer_filled_in) { ! /* 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); --- 297,308 ---- unsigned char SOCK_get_next_byte(SocketClass *self) { if (self->buffer_read_in >= self->buffer_filled_in) { ! /* ! * 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); Index: src/interfaces/odbc/statement.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/statement.c,v retrieving revision 1.35 diff -c -r1.35 statement.c *** src/interfaces/odbc/statement.c 2001/03/27 04:00:55 1.35 --- src/interfaces/odbc/statement.c 2001/03/28 16:53:22 *************** *** 1,4 **** ! /* Module: statement.c * * Description: This module contains functions related to creating * and manipulating a statement. --- 1,5 ---- ! /*------- ! * Module: statement.c * * Description: This module contains functions related to creating * and manipulating a statement. *************** *** 8,14 **** * API functions: SQLAllocStmt, SQLFreeStmt * * Comments: See "notice.txt" for copyright and license information. ! * */ #ifdef HAVE_CONFIG_H --- 9,15 ---- * API functions: SQLAllocStmt, SQLFreeStmt * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #ifdef HAVE_CONFIG_H *************** *** 126,137 **** *phstmt = (HSTMT) stmt; ! /* ! * Copy default statement options based from Connection options ! */ stmt->options = conn->stmtOptions; - /* Save the handle for later */ stmt->phstmt = phstmt; --- 127,135 ---- *phstmt = (HSTMT) stmt; ! /* Copy default statement options based from Connection options */ stmt->options = conn->stmtOptions; /* Save the handle for later */ stmt->phstmt = phstmt; *************** *** 180,208 **** /* Destroy the statement and free any results, cursors, etc. */ SC_Destructor(stmt); - } else if (fOption == SQL_UNBIND) { SC_unbind_cols(stmt); - } else if (fOption == SQL_CLOSE) { ! /* this should discard all the results, but leave the statement */ ! /* itself in place (it can be executed again) */ if (!SC_recycle_statement(stmt)) { /* errormsg passed in above */ SC_log_error(func, "", stmt); return SQL_ERROR; } - } else if (fOption == SQL_RESET_PARAMS) { SC_free_params(stmt, STMT_FREE_PARAMS_ALL); - } else { --- 178,204 ---- /* Destroy the statement and free any results, cursors, etc. */ SC_Destructor(stmt); } else if (fOption == SQL_UNBIND) { SC_unbind_cols(stmt); } else if (fOption == SQL_CLOSE) { ! /* ! * this should discard all the results, but leave the statement ! * itself in place (it can be executed again) ! */ if (!SC_recycle_statement(stmt)) { /* errormsg passed in above */ SC_log_error(func, "", stmt); return SQL_ERROR; } } else if (fOption == SQL_RESET_PARAMS) { SC_free_params(stmt, STMT_FREE_PARAMS_ALL); } else { *************** *** 216,223 **** } ! ! /********************************************************************** * StatementClass implementation */ void --- 212,218 ---- } ! /* * StatementClass implementation */ void *************** *** 288,294 **** rv->nfld = 0; rv->parse_status = STMT_PARSE_NONE; - /* Clear Statement Options -- defaults will be set in AllocStmt */ memset(&rv->options, 0, sizeof(StatementOptions)); } --- 283,288 ---- *************** *** 298,304 **** char SC_Destructor(StatementClass *self) { - mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc); if (STMT_EXECUTING == self->status) { --- 292,297 ---- *************** *** 322,339 **** /* * the memory pointed to by the bindings is not deallocated by the ! * driver ! */ ! ! /* ! * by by the application that uses that driver, so we don't have to * care */ /* about that here. */ if (self->bindings) free(self->bindings); - /* Free the parsed table information */ if (self->ti) { --- 315,327 ---- /* * the memory pointed to by the bindings is not deallocated by the ! * driver but by the application that uses that driver, so we don't have to * care */ /* about that here. */ if (self->bindings) free(self->bindings); /* Free the parsed table information */ if (self->ti) { *************** *** 355,361 **** free(self->fi); } - free(self); mylog("SC_Destructor: EXIT\n"); --- 343,348 ---- *************** *** 363,371 **** return TRUE; } ! /* Free parameters and free the memory from the ! data-at-execution parameters that was allocated in SQLPutData. ! */ void SC_free_params(StatementClass *self, char option) { --- 350,359 ---- return TRUE; } ! /* ! * Free parameters and free the memory from the ! * data-at-execution parameters that was allocated in SQLPutData. ! */ void SC_free_params(StatementClass *self, char option) { *************** *** 380,386 **** { if (self->parameters[i].data_at_exec == TRUE) { - if (self->parameters[i].EXEC_used) { free(self->parameters[i].EXEC_used); --- 368,373 ---- *************** *** 427,435 **** } ! /* Called from SQLPrepare if STMT_PREMATURE, or ! from SQLExecute if STMT_FINISHED, or ! from SQLFreeStmt(SQL_CLOSE) */ char SC_recycle_statement(StatementClass *self) --- 414,423 ---- } ! /* ! * Called from SQLPrepare if STMT_PREMATURE, or ! * from SQLExecute if STMT_FINISHED, or ! * from SQLFreeStmt(SQL_CLOSE) */ char SC_recycle_statement(StatementClass *self) *************** *** 469,475 **** conn = SC_get_conn(self); if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) { - QResultClass *res = CC_send_query(conn, "ABORT", NULL); QR_Destructor(res); --- 457,462 ---- *************** *** 518,528 **** QR_Destructor(self->result); self->result = NULL; } - - /****************************************************************/ - /* Reset only parameters that have anything to do with results */ - /****************************************************************/ self->status = STMT_READY; self->manual_result = FALSE;/* very important */ --- 505,514 ---- QR_Destructor(self->result); self->result = NULL; } + /* + * Reset only parameters that have anything to do with results + */ self->status = STMT_READY; self->manual_result = FALSE;/* very important */ *************** *** 538,546 **** self->lobj_fd = -1; ! /* Free any data at exec params before the statement is executed */ ! /* again. If not, then there will be a memory leak when */ ! /* the next SQLParamData/SQLPutData is called. */ SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY); return TRUE; --- 524,534 ---- self->lobj_fd = -1; ! /* ! * Free any data at exec params before the statement is executed ! * again. If not, then there will be a memory leak when ! * the next SQLParamData/SQLPutData is called. ! */ SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY); return TRUE; *************** *** 550,556 **** void SC_pre_execute(StatementClass *self) { - mylog("SC_pre_execute: status = %d\n", self->status); if (self->status == STMT_READY) --- 538,543 ---- *************** *** 597,604 **** } ! /* This function creates an error msg which is the concatenation */ ! /* of the result, statement, connection, and socket messages. */ char * SC_create_errormsg(StatementClass *self) { --- 584,593 ---- } ! /* ! * This function creates an error msg which is the concatenation ! * of the result, statement, connection, and socket messages. ! */ char * SC_create_errormsg(StatementClass *self) { *************** *** 640,646 **** { char rv; ! /* Create a very informative errormsg if it hasn't been done yet. */ if (!self->errormsg_created) { self->errormsg = SC_create_errormsg(self); --- 629,635 ---- { char rv; ! /* Create a very informative errormsg if it hasn't been done yet. */ if (!self->errormsg_created) { self->errormsg = SC_create_errormsg(self); *************** *** 660,669 **** return rv; } ! /* Currently, the driver offers very simple bookmark support -- it is ! just the current row number. But it could be more sophisticated ! someday, such as mapping a key to a 32 bit value ! */ unsigned long SC_get_bookmark(StatementClass *self) { --- 649,659 ---- return rv; } ! /* ! * Currently, the driver offers very simple bookmark support -- it is ! * just the current row number. But it could be more sophisticated ! * someday, such as mapping a key to a 32 bit value ! */ unsigned long SC_get_bookmark(StatementClass *self) { *************** *** 683,689 **** char *value; ColumnInfoClass *ci; ! /* TupleField *tupleField; */ self->last_fetch_count = 0; ci = QR_get_fields(res); /* the column info */ --- 673,679 ---- char *value; ColumnInfoClass *ci; ! /* TupleField *tupleField; */ self->last_fetch_count = 0; ci = QR_get_fields(res); /* the column info */ *************** *** 692,702 **** if (self->manual_result || !globals.use_declarefetch) { - if (self->currTuple >= QR_get_num_tuples(res) - 1 || (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) { - /* * if at the end of the tuples, return "no data found" and set * the cursor past the end of the result set --- 682,690 ---- *************** *** 710,716 **** } else { - /* read from the cache or the physical next tuple */ retval = QR_next_tuple(res); if (retval < 0) --- 698,703 ---- *************** *** 720,726 **** } else if (retval > 0) (self->currTuple)++;/* all is well */ - else { mylog("SQLFetch: error\n"); --- 707,712 ---- *************** *** 753,759 **** for (lf = 0; lf < num_cols; lf++) { - mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer); /* reset for SQLGetData */ --- 739,744 ---- *************** *** 809,821 **** result = SQL_SUCCESS_WITH_INFO; break; ! case COPY_GENERAL_ERROR: /* error msg already ! * filled in */ SC_log_error(func, "", self); result = SQL_ERROR; break; ! /* This would not be meaningful in SQLFetch. */ case COPY_NO_DATA_FOUND: break; --- 794,806 ---- result = SQL_SUCCESS_WITH_INFO; break; ! /* error msg already filled in */ ! case COPY_GENERAL_ERROR: SC_log_error(func, "", self); result = SQL_ERROR; break; ! /* This would not be meaningful in SQLFetch. */ case COPY_NO_DATA_FOUND: break; *************** *** 889,901 **** CC_set_in_trans(conn); } - - oldstatus = conn->status; conn->status = CONN_EXECUTING; self->status = STMT_EXECUTING; - /* If it's a SELECT statement, use a cursor. */ /* --- 874,883 ---- *************** *** 905,923 **** /* in copy_statement... */ if (self->statement_type == STMT_TYPE_SELECT) { - char fetch[128]; mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name); - /* send the declare/select */ self->result = CC_send_query(conn, self->stmt_with_params, NULL); if (globals.use_declarefetch && self->result != NULL && QR_command_successful(self->result)) { - QR_Destructor(self->result); /* --- 887,902 ---- *************** *** 935,954 **** * will correct for any discrepancies in sizes and adjust the * cache accordingly. */ - sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name); self->result = CC_send_query(conn, fetch, &qi); } - mylog(" done sending the query:\n"); - - - } else ! { /* not a SELECT statement so don't use a ! * cursor */ mylog(" it's NOT a select statement: stmt=%u\n", self); self->result = CC_send_query(conn, self->stmt_with_params, NULL); --- 914,928 ---- * will correct for any discrepancies in sizes and adjust the * cache accordingly. */ sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name); self->result = CC_send_query(conn, fetch, &qi); } mylog(" done sending the query:\n"); } else ! { ! /* not a SELECT statement so don't use a cursor */ mylog(" it's NOT a select statement: stmt=%u\n", self); self->result = CC_send_query(conn, self->stmt_with_params, NULL); *************** *** 967,973 **** QR_Destructor(res); CC_set_no_trans(conn); } - } conn->status = oldstatus; --- 941,946 ---- *************** *** 976,982 **** /* Check the status of the result */ if (self->result) { - was_ok = QR_command_successful(self->result); was_nonfatal = QR_command_nonfatal(self->result); --- 949,954 ---- *************** *** 985,992 **** else self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND; ! self->currTuple = -1; /* set cursor before the first tuple in ! * the list */ self->current_col = -1; self->rowset_start = -1; --- 957,964 ---- else self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND; ! /* set cursor before the first tuple in the list */ ! self->currTuple = -1; self->current_col = -1; self->rowset_start = -1; *************** *** 1010,1018 **** CC_abort(conn); } else ! { /* Bad Error -- The error message will be ! * in the Connection */ ! if (self->statement_type == STMT_TYPE_CREATE) { self->errornumber = STMT_CREATE_TABLE_ERROR; --- 982,989 ---- CC_abort(conn); } else ! { ! /* Bad Error -- The error message will be in the Connection */ if (self->statement_type == STMT_TYPE_CREATE) { self->errornumber = STMT_CREATE_TABLE_ERROR; Index: src/interfaces/odbc/tuple.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/tuple.c,v retrieving revision 1.12 diff -c -r1.12 tuple.c *** src/interfaces/odbc/tuple.c 2001/03/27 04:00:55 1.12 --- src/interfaces/odbc/tuple.c 2001/03/28 16:53:22 *************** *** 1,17 **** ! /* Module: tuple.c * ! * Description: This module contains functions for setting the data for individual ! * fields (TupleField structure) of a manual result set. * - * Important Note: These functions are ONLY used in building manual result sets for - * info functions (SQLTables, SQLColumns, etc.) - * * Classes: n/a * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #include "tuple.h" --- 1,20 ---- ! /*------- ! * Module: tuple.c * ! * Description: This module contains functions for setting the data ! * for individual fields (TupleField structure) of a ! * manual result set. ! * ! * Important Note: These functions are ONLY used in building manual ! * result sets for info functions (SQLTables, ! * SQLColumns, etc.) * * Classes: n/a * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *------- */ #include "tuple.h" *************** *** 38,44 **** set_tuplefield_int2(TupleField *tuple_field, Int2 value) { char buffer[10]; - sprintf(buffer, "%d", value); --- 41,46 ---- Index: src/interfaces/odbc/tuplelist.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/tuplelist.c,v retrieving revision 1.11 diff -c -r1.11 tuplelist.c *** src/interfaces/odbc/tuplelist.c 2001/03/27 04:00:55 1.11 --- src/interfaces/odbc/tuplelist.c 2001/03/28 16:53:22 *************** *** 1,14 **** ! /* Module: tuplelist.c * ! * Description: This module contains functions for creating a manual result set ! * (the TupleList) and retrieving data from it for a specific row/column. * * Classes: TupleListClass (Functions prefix: "TL_") * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! * */ #include --- 1,16 ---- ! /*-------- ! * Module: tuplelist.c * ! * Description: This module contains functions for creating a manual ! * result set (the TupleList) and retrieving data from ! * it for a specific row/column. * * Classes: TupleListClass (Functions prefix: "TL_") * * API functions: none * * Comments: See "notice.txt" for copyright and license information. ! *-------- */ #include *************** *** 25,31 **** rv = (TupleListClass *) malloc(sizeof(TupleListClass)); if (rv) { - rv->num_fields = fieldcnt; rv->num_tuples = 0; rv->list_start = NULL; --- 27,32 ---- *************** *** 134,140 **** } else if (start_is_closer) { - /* * the shortest way is to start the search from the head of the * list --- 135,140 ---- *************** *** 177,187 **** } - char TL_add_tuple(TupleListClass *self, TupleNode *new_field) { - /* * we append the tuple at the end of the doubly linked list of the * tuples we have already read in --- 177,185 ---- *************** *** 200,206 **** } else { - /* * there is already an element in the list, so add the new one at * the end of the list --- 198,203 ----