From: Hiroshi Inoue Date: Fri, 11 Jan 2002 06:01:47 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: REL7_2_BETA5~21 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d91b4451175dcd1996e8b5fdaa375d2bcf74d9a5;p=postgresql *** empty log message *** --- diff --git a/src/interfaces/odbc/windev/README.txt b/src/interfaces/odbc/windev/README.txt deleted file mode 100644 index 1070c0d2c7..0000000000 --- a/src/interfaces/odbc/windev/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -This directory is to save the changes about psqlodbc driver under -win32 while the main development tree(the parent directory) is -nearly freezed(i.e. during beta, a while after the release until -the next branch is made etc). The changes would be reflected -to the main directory later after all. However note that the -trial binary version would be sometimes made using the source -and put on the ftp server for download. - - Hiroshi Inoue inoue@postgresql.org diff --git a/src/interfaces/odbc/windev/bind.c b/src/interfaces/odbc/windev/bind.c deleted file mode 100644 index e9f5cc3482..0000000000 --- a/src/interfaces/odbc/windev/bind.c +++ /dev/null @@ -1,487 +0,0 @@ -/*------- - * Module: bind.c - * - * Description: This module contains routines related to binding - * columns and parameters. - * - * Classes: BindInfoClass, ParameterInfoClass - * - * API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams, - * SQLParamOptions(NI) - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "bind.h" - -#include "environ.h" -#include "statement.h" -#include "qresult.h" -#include "pgtypes.h" -#include -#include - -#include "pgapifunc.h" - - -/* Bind parameters on a statement handle */ -RETCODE SQL_API -PGAPI_BindParameter( - HSTMT hstmt, - UWORD ipar, - SWORD fParamType, - SWORD fCType, - SWORD fSqlType, - UDWORD cbColDef, - SWORD ibScale, - PTR rgbValue, - SDWORD cbValueMax, - SDWORD FAR * pcbValue) -{ - StatementClass *stmt = (StatementClass *) hstmt; - static char *func = "PGAPI_BindParameter"; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - SC_clear_error(stmt); - - if (stmt->parameters_allocated < ipar) - { - ParameterInfoClass *old_parameters; - int i, - old_parameters_allocated; - - old_parameters = stmt->parameters; - old_parameters_allocated = stmt->parameters_allocated; - - stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass) * (ipar)); - if (!stmt->parameters) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Could not allocate memory for statement parameters"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - stmt->parameters_allocated = ipar; - - /* copy the old parameters over */ - for (i = 0; i < old_parameters_allocated; i++) - { - /* a structure copy should work */ - stmt->parameters[i] = old_parameters[i]; - } - - /* get rid of the old parameters, if there were any */ - if (old_parameters) - free(old_parameters); - - /* - * zero out the newly allocated parameters (in case they skipped - * some, - */ - /* so we don't accidentally try to use them later) */ - for (; i < stmt->parameters_allocated; i++) - { - stmt->parameters[i].buflen = 0; - stmt->parameters[i].buffer = 0; - stmt->parameters[i].used = 0; - stmt->parameters[i].paramType = 0; - stmt->parameters[i].CType = 0; - stmt->parameters[i].SQLType = 0; - stmt->parameters[i].precision = 0; - stmt->parameters[i].scale = 0; - stmt->parameters[i].data_at_exec = FALSE; - stmt->parameters[i].lobj_oid = 0; - stmt->parameters[i].EXEC_used = NULL; - stmt->parameters[i].EXEC_buffer = NULL; - } - } - - /* use zero based column numbers for the below part */ - ipar--; - - /* store the given info */ - stmt->parameters[ipar].buflen = cbValueMax; - stmt->parameters[ipar].buffer = rgbValue; - stmt->parameters[ipar].used = pcbValue; - stmt->parameters[ipar].paramType = fParamType; - stmt->parameters[ipar].CType = fCType; - stmt->parameters[ipar].SQLType = fSqlType; - stmt->parameters[ipar].precision = cbColDef; - stmt->parameters[ipar].scale = ibScale; - - /* - * If rebinding a parameter that had data-at-exec stuff in it, then - * free that stuff - */ - if (stmt->parameters[ipar].EXEC_used) - { - free(stmt->parameters[ipar].EXEC_used); - stmt->parameters[ipar].EXEC_used = NULL; - } - - if (stmt->parameters[ipar].EXEC_buffer) - { - if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY) - free(stmt->parameters[ipar].EXEC_buffer); - stmt->parameters[ipar].EXEC_buffer = NULL; - } - - /* Data at exec macro only valid for C char/binary data */ - if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC || - *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)) - stmt->parameters[ipar].data_at_exec = TRUE; - else - stmt->parameters[ipar].data_at_exec = FALSE; - - /* Clear premature result */ - if (stmt->status == STMT_PREMATURE) - SC_recycle_statement(stmt); - - mylog("PGAPI_BindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, stmt->parameters[ipar].data_at_exec); - - return SQL_SUCCESS; -} - - -/* Associate a user-supplied buffer with a database column. */ -RETCODE SQL_API -PGAPI_BindCol( - HSTMT hstmt, - UWORD icol, - SWORD fCType, - PTR rgbValue, - SDWORD cbValueMax, - SDWORD FAR * pcbValue) -{ - StatementClass *stmt = (StatementClass *) hstmt; - static char *func = "PGAPI_BindCol"; - - mylog("%s: entering...\n", func); - - mylog("**** PGAPI_BindCol: stmt = %u, icol = %d\n", stmt, icol); - mylog("**** : fCType=%d rgb=%x valusMax=%d pcb=%x\n", fCType, rgbValue, cbValueMax, pcbValue); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - - SC_clear_error(stmt); - - if (stmt->status == STMT_EXECUTING) - { - stmt->errormsg = "Can't bind columns while statement is still executing."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* If the bookmark column is being bound, then just save it */ - if (icol == 0) - { - if (rgbValue == NULL) - { - stmt->bookmark.buffer = NULL; - stmt->bookmark.used = NULL; - } - else - { - /* Make sure it is the bookmark data type */ - if (fCType != SQL_C_BOOKMARK) - { - stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK"; - stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - stmt->bookmark.buffer = rgbValue; - stmt->bookmark.used = pcbValue; - } - 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); - - /* check to see if the bindings were allocated */ - if (!stmt->bindings) - { - stmt->errormsg = "Could not allocate memory for bindings."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* use zero based col numbers from here out */ - icol--; - - /* Reset for SQLGetData */ - stmt->bindings[icol].data_left = -1; - - if (rgbValue == NULL) - { - /* we have to unbind the column */ - stmt->bindings[icol].buflen = 0; - stmt->bindings[icol].buffer = NULL; - stmt->bindings[icol].used = NULL; - stmt->bindings[icol].returntype = SQL_C_CHAR; - } - else - { - /* ok, bind that column */ - stmt->bindings[icol].buflen = cbValueMax; - stmt->bindings[icol].buffer = rgbValue; - stmt->bindings[icol].used = pcbValue; - stmt->bindings[icol].returntype = fCType; - - mylog(" bound buffer[%d] = %u\n", icol, stmt->bindings[icol].buffer); - } - - 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 -PGAPI_DescribeParam( - HSTMT hstmt, - UWORD ipar, - SWORD FAR * pfSqlType, - UDWORD FAR * pcbColDef, - SWORD FAR * pibScale, - SWORD FAR * pfNullable) -{ - StatementClass *stmt = (StatementClass *) hstmt; - static char *func = "PGAPI_DescribeParam"; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - SC_clear_error(stmt); - - if ((ipar < 1) || (ipar > stmt->parameters_allocated)) - { - stmt->errormsg = "Invalid parameter number for PGAPI_DescribeParam."; - stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - ipar--; - - /* - * This implementation is not very good, since it is supposed to - * describe - */ - /* parameter markers, not bound parameters. */ - if (pfSqlType) - *pfSqlType = stmt->parameters[ipar].SQLType; - - if (pcbColDef) - *pcbColDef = stmt->parameters[ipar].precision; - - if (pibScale) - *pibScale = stmt->parameters[ipar].scale; - - if (pfNullable) - *pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType); - - return SQL_SUCCESS; -} - - -/* Sets multiple values (arrays) for the set of parameter markers. */ -RETCODE SQL_API -PGAPI_ParamOptions( - HSTMT hstmt, - UDWORD crow, - UDWORD FAR * pirow) -{ - static char *func = "PGAPI_ParamOptions"; - StatementClass *stmt = (StatementClass *) hstmt; - - mylog("%s: entering... %d %x\n", func, crow, pirow); - - if (crow == 1) /* temporary solution and must be - * rewritten later */ - { - if (pirow) - *pirow = 1; - return SQL_SUCCESS; - } - stmt->errornumber = CONN_UNSUPPORTED_OPTION; - stmt->errormsg = "Function not implemented"; - SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); - 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 -PGAPI_NumParams( - HSTMT hstmt, - SWORD FAR * pcpar) -{ - StatementClass *stmt = (StatementClass *) hstmt; - char in_quote = FALSE; - unsigned int i; - static char *func = "PGAPI_NumParams"; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - SC_clear_error(stmt); - - if (pcpar) - *pcpar = 0; - else - { - SC_log_error(func, "pcpar was null", stmt); - return SQL_ERROR; - } - - - if (!stmt->statement) - { - /* no statement has been allocated */ - stmt->errormsg = "PGAPI_NumParams called with no statement ready."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - else - { - for (i = 0; i < strlen(stmt->statement); i++) - { - if (stmt->statement[i] == '?' && !in_quote) - (*pcpar)++; - else - { - if (stmt->statement[i] == '\'') - in_quote = (in_quote ? FALSE : TRUE); - } - } - return SQL_SUCCESS; - } -} - - -/* - * Bindings Implementation - */ -BindInfoClass * -create_empty_bindings(int num_columns) -{ - BindInfoClass *new_bindings; - int i; - - new_bindings = (BindInfoClass *) malloc(num_columns * sizeof(BindInfoClass)); - if (!new_bindings) - return 0; - - for (i = 0; i < num_columns; i++) - { - new_bindings[i].buflen = 0; - new_bindings[i].buffer = NULL; - new_bindings[i].used = NULL; - new_bindings[i].data_left = -1; - new_bindings[i].ttlbuf = NULL; - new_bindings[i].ttlbuflen = 0; - } - - return new_bindings; -} - - -void -extend_bindings(StatementClass *stmt, int num_columns) -{ - static char *func = "extend_bindings"; - BindInfoClass *new_bindings; - int i; - - 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) - { - mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, stmt->bindings_allocated); - - if (stmt->bindings) - { - free(stmt->bindings); - stmt->bindings = NULL; - } - stmt->bindings_allocated = 0; - return; - } - - if (stmt->bindings) - { - for (i = 0; i < stmt->bindings_allocated; i++) - new_bindings[i] = stmt->bindings[i]; - - free(stmt->bindings); - } - - 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 */ - /* SQLExecDirect(...) # returns 10 cols (now OK) */ - - mylog("exit extend_bindings\n"); -} diff --git a/src/interfaces/odbc/windev/bind.h b/src/interfaces/odbc/windev/bind.h deleted file mode 100644 index 34b9e1d399..0000000000 --- a/src/interfaces/odbc/windev/bind.h +++ /dev/null @@ -1,55 +0,0 @@ -/* File: bind.h - * - * Description: See "bind.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __BIND_H__ -#define __BIND_H__ - -#include "psqlodbc.h" - -/* - * BindInfoClass -- stores information about a bound column - */ -struct BindInfoClass_ -{ - Int4 buflen; /* size of buffer */ - Int4 data_left; /* amount of data left to read - * (SQLGetData) */ - char *buffer; /* pointer to the buffer */ - Int4 *used; /* used space in the buffer (for strings - * not counting the '\0') */ - char *ttlbuf; /* to save the large result */ - Int4 ttlbuflen; /* the buffer length */ - Int2 returntype; /* kind of conversion to be applied when - * returning (SQL_C_DEFAULT, - * SQL_C_CHAR...) */ -}; - -/* - * ParameterInfoClass -- stores information about a bound parameter - */ -struct ParameterInfoClass_ -{ - Int4 buflen; - char *buffer; - Int4 *used; - Int2 paramType; - Int2 CType; - Int2 SQLType; - UInt4 precision; - Int2 scale; - Oid lobj_oid; - Int4 *EXEC_used; /* amount of data OR the oid of the large - * object */ - char *EXEC_buffer; /* the data or the FD of the large object */ - char data_at_exec; -}; - -BindInfoClass *create_empty_bindings(int num_columns); -void extend_bindings(StatementClass *stmt, int num_columns); - -#endif diff --git a/src/interfaces/odbc/windev/columninfo.c b/src/interfaces/odbc/windev/columninfo.c deleted file mode 100644 index 7fe72d3f6d..0000000000 --- a/src/interfaces/odbc/windev/columninfo.c +++ /dev/null @@ -1,191 +0,0 @@ -/*------- - * Module: columninfo.c - * - * Description: This module contains routines related to - * reading and storing the field information from a query. - * - * Classes: ColumnInfoClass (Functions prefix: "CI_") - * - * API functions: none - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "pgtypes.h" -#include "columninfo.h" - -#include "connection.h" -#include "socket.h" -#include -#include -#include "pgapifunc.h" - -ColumnInfoClass * -CI_Constructor() -{ - ColumnInfoClass *rv; - - rv = (ColumnInfoClass *) malloc(sizeof(ColumnInfoClass)); - - if (rv) - { - rv->num_fields = 0; - rv->name = NULL; - rv->adtid = NULL; - rv->adtsize = NULL; - rv->display_size = NULL; - rv->atttypmod = NULL; - } - - return rv; -} - - -void -CI_Destructor(ColumnInfoClass *self) -{ - CI_free_memory(self); - - 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) -{ - Int2 lf; - int new_num_fields; - Oid new_adtid; - Int2 new_adtsize; - Int4 new_atttypmod = -1; - - /* MAX_COLUMN_LEN may be sufficient but for safety */ - char new_field_name[2 * MAX_COLUMN_LEN + 1]; - SocketClass *sock; - ConnInfo *ci; - - sock = CC_get_socket(conn); - ci = &conn->connInfo; - - /* at first read in the number of fields that are in the query */ - new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2)); - - mylog("num_fields = %d\n", new_num_fields); - - if (self) - /* according to that allocate memory */ - CI_set_num_fields(self, new_num_fields); - - /* now read in the descriptions */ - for (lf = 0; lf < new_num_fields; lf++) - { - SOCK_get_string(sock, new_field_name, 2 * MAX_COLUMN_LEN); - new_adtid = (Oid) SOCK_get_int(sock, 4); - new_adtsize = (Int2) SOCK_get_int(sock, 2); - - /* 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); - - /* Subtract the header length */ - switch (new_adtid) - { - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP_NO_TMZONE: - case PG_TYPE_TIME: - case PG_TYPE_TIME_WITH_TMZONE: - break; - default: - new_atttypmod -= 4; - } - if (new_atttypmod < 0) - new_atttypmod = -1; - - } - - mylog("CI_read_fields: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d\n", new_field_name, new_adtid, new_adtsize, new_atttypmod); - - if (self) - CI_set_field_info(self, lf, new_field_name, new_adtid, new_adtsize, new_atttypmod); - } - - return (SOCK_get_errcode(sock) == 0); -} - - -void -CI_free_memory(ColumnInfoClass *self) -{ - register Int2 lf; - int num_fields = self->num_fields; - - for (lf = 0; lf < num_fields; lf++) - { - if (self->name[lf]) - { - free(self->name[lf]); - self->name[lf] = NULL; - } - } - - /* Safe to call even if null */ - self->num_fields = 0; - if (self->name) - free(self->name); - self->name = NULL; - if (self->adtid) - free(self->adtid); - self->adtid = NULL; - if (self->adtsize) - free(self->adtsize); - self->adtsize = NULL; - if (self->display_size) - free(self->display_size); - self->display_size = NULL; - - if (self->atttypmod) - free(self->atttypmod); - self->atttypmod = NULL; -} - - -void -CI_set_num_fields(ColumnInfoClass *self, int new_num_fields) -{ - CI_free_memory(self); /* always safe to call */ - - self->num_fields = new_num_fields; - - self->name = (char **) malloc(sizeof(char *) * self->num_fields); - memset(self->name, 0, sizeof(char *) * self->num_fields); - self->adtid = (Oid *) malloc(sizeof(Oid) * self->num_fields); - self->adtsize = (Int2 *) malloc(sizeof(Int2) * self->num_fields); - self->display_size = (Int2 *) malloc(sizeof(Int2) * self->num_fields); - self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields); -} - - -void -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; - - /* store the info */ - self->name[field_num] = strdup(new_name); - self->adtid[field_num] = new_adtid; - self->adtsize[field_num] = new_adtsize; - self->atttypmod[field_num] = new_atttypmod; - - self->display_size[field_num] = 0; -} diff --git a/src/interfaces/odbc/windev/columninfo.h b/src/interfaces/odbc/windev/columninfo.h deleted file mode 100644 index 41e9400dce..0000000000 --- a/src/interfaces/odbc/windev/columninfo.h +++ /dev/null @@ -1,42 +0,0 @@ -/* File: columninfo.h - * - * Description: See "columninfo.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __COLUMNINFO_H__ -#define __COLUMNINFO_H__ - -#include "psqlodbc.h" - -struct ColumnInfoClass_ -{ - Int2 num_fields; - char **name; /* list of type names */ - Oid *adtid; /* list of type ids */ - Int2 *adtsize; /* list type sizes */ - Int2 *display_size; /* the display size (longest row) */ - Int4 *atttypmod; /* the length of bpchar/varchar */ -}; - -#define CI_get_num_fields(self) (self->num_fields) -#define CI_get_oid(self, col) (self->adtid[col]) -#define CI_get_fieldname(self, col) (self->name[col]) -#define CI_get_fieldsize(self, col) (self->adtsize[col]) -#define CI_get_display_size(self, col) (self->display_size[col]) -#define CI_get_atttypmod(self, col) (self->atttypmod[col]) - -ColumnInfoClass *CI_Constructor(void); -void CI_Destructor(ColumnInfoClass *self); -void CI_free_memory(ColumnInfoClass *self); -char CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn); - -/* functions for setting up the fields from within the program, */ -/* without reading from a socket */ -void CI_set_num_fields(ColumnInfoClass *self, int new_num_fields); -void CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, - Oid new_adtid, Int2 new_adtsize, Int4 atttypmod); - -#endif diff --git a/src/interfaces/odbc/windev/connection.c b/src/interfaces/odbc/windev/connection.c deleted file mode 100644 index e057d7b73f..0000000000 --- a/src/interfaces/odbc/windev/connection.c +++ /dev/null @@ -1,1839 +0,0 @@ -/*------ - * Module: connection.c - * - * Description: This module contains routines related to - * connecting to and disconnecting from the Postgres DBMS. - * - * Classes: ConnectionClass (Functions prefix: "CC_") - * - * API functions: SQLAllocConnect, SQLConnect, SQLDisconnect, SQLFreeConnect, - * SQLBrowseConnect(NI) - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ -/* Multibyte support Eiji Tokuya 2001-03-15 */ - -#include "connection.h" - -#include -#include -#include - -#include "environ.h" -#include "socket.h" -#include "statement.h" -#include "qresult.h" -#include "lobj.h" -#include "dlg_specific.h" - -#ifdef MULTIBYTE -#include "multibyte.h" -#endif - -#include "pgapifunc.h" -#include "md5.h" - -#define STMT_INCREMENT 16 /* how many statement holders to allocate - * at a time */ - -#define PRN_NULLCHECK - -extern GLOBAL_VALUES globals; - - -RETCODE SQL_API -PGAPI_AllocConnect( - HENV henv, - HDBC FAR * phdbc) -{ - EnvironmentClass *env = (EnvironmentClass *) henv; - ConnectionClass *conn; - static char *func = "PGAPI_AllocConnect"; - - mylog("%s: entering...\n", func); - - conn = CC_Constructor(); - mylog("**** %s: henv = %u, conn = %u\n", func, henv, conn); - - if (!conn) - { - env->errormsg = "Couldn't allocate memory for Connection object."; - env->errornumber = ENV_ALLOC_ERROR; - *phdbc = SQL_NULL_HDBC; - EN_log_error(func, "", env); - return SQL_ERROR; - } - - if (!EN_add_connection(env, conn)) - { - env->errormsg = "Maximum number of connections exceeded."; - env->errornumber = ENV_ALLOC_ERROR; - CC_Destructor(conn); - *phdbc = SQL_NULL_HDBC; - EN_log_error(func, "", env); - return SQL_ERROR; - } - - *phdbc = (HDBC) conn; - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_Connect( - HDBC hdbc, - UCHAR FAR * szDSN, - SWORD cbDSN, - UCHAR FAR * szUID, - SWORD cbUID, - UCHAR FAR * szAuthStr, - SWORD cbAuthStr) -{ - ConnectionClass *conn = (ConnectionClass *) hdbc; - ConnInfo *ci; - static char *func = "PGAPI_Connect"; - - mylog("%s: entering...\n", func); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - ci = &conn->connInfo; - - make_string(szDSN, cbDSN, ci->dsn); - - /* get the values for the DSN from the registry */ - getDSNinfo(ci, CONN_OVERWRITE); - logs_on_off(1, ci->drivers.debug, ci->drivers.commlog); - /* initialize pg_version from connInfo.protocol */ - CC_initialize_pg_version(conn); - - /* - * override values from DSN info with UID and authStr(pwd) This only - * occurs if the values are actually there. - */ - make_string(szUID, cbUID, ci->username); - make_string(szAuthStr, cbAuthStr, ci->password); - - /* fill in any defaults */ - getDSNdefaults(ci); - - qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password); - - if (CC_connect(conn, FALSE) <= 0) - { - /* Error messages are filled in */ - CC_log_error(func, "Error on CC_connect", conn); - return SQL_ERROR; - } - - mylog("%s: returning...\n", func); - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_BrowseConnect( - HDBC hdbc, - UCHAR FAR * szConnStrIn, - SWORD cbConnStrIn, - UCHAR FAR * szConnStrOut, - SWORD cbConnStrOutMax, - SWORD FAR * pcbConnStrOut) -{ - static char *func = "PGAPI_BrowseConnect"; - - mylog("%s: entering...\n", func); - - return SQL_SUCCESS; -} - - -/* Drop any hstmts open on hdbc and disconnect from database */ -RETCODE SQL_API -PGAPI_Disconnect( - HDBC hdbc) -{ - ConnectionClass *conn = (ConnectionClass *) hdbc; - static char *func = "PGAPI_Disconnect"; - - - mylog("%s: entering...\n", func); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - qlog("conn=%u, %s\n", conn, func); - - if (conn->status == CONN_EXECUTING) - { - conn->errornumber = CONN_IN_USE; - conn->errormsg = "A transaction is currently being executed"; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - logs_on_off(-1, conn->connInfo.drivers.debug, conn->connInfo.drivers.commlog); - mylog("%s: about to CC_cleanup\n", func); - - /* Close the connection and free statements */ - CC_cleanup(conn); - - mylog("%s: done CC_cleanup\n", func); - mylog("%s: returning...\n", func); - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_FreeConnect( - HDBC hdbc) -{ - ConnectionClass *conn = (ConnectionClass *) hdbc; - static char *func = "PGAPI_FreeConnect"; - - mylog("%s: entering...\n", func); - mylog("**** in %s: hdbc=%u\n", func, hdbc); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - /* Remove the connection from the environment */ - if (!EN_remove_connection(conn->henv, conn)) - { - conn->errornumber = CONN_IN_USE; - conn->errormsg = "A transaction is currently being executed"; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - CC_Destructor(conn); - - mylog("%s: returning...\n", func); - - return SQL_SUCCESS; -} - - -/* - * IMPLEMENTATION CONNECTION CLASS - */ -ConnectionClass * -CC_Constructor() -{ - ConnectionClass *rv; - - rv = (ConnectionClass *) malloc(sizeof(ConnectionClass)); - - if (rv != NULL) - { - rv->henv = NULL; /* not yet associated with an environment */ - - rv->errormsg = NULL; - rv->errornumber = 0; - rv->errormsg_created = FALSE; - - rv->status = CONN_NOT_CONNECTED; - rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */ - - memset(&rv->connInfo, 0, sizeof(ConnInfo)); -#ifdef DRIVER_CURSOR_IMPLEMENT - rv->connInfo.updatable_cursors = 1; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals)); - rv->sock = SOCK_Constructor(rv); - if (!rv->sock) - return NULL; - - rv->stmts = (StatementClass **) malloc(sizeof(StatementClass *) * STMT_INCREMENT); - if (!rv->stmts) - return NULL; - memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT); - - rv->num_stmts = STMT_INCREMENT; - - rv->lobj_type = PG_TYPE_LO; - - rv->ntables = 0; - rv->col_info = NULL; - - rv->translation_option = 0; - rv->translation_handle = NULL; - rv->DataSourceToDriver = NULL; - rv->DriverToDataSource = NULL; - rv->driver_version = ODBCVER; - memset(rv->pg_version, 0, sizeof(rv->pg_version)); - rv->pg_version_number = .0; - rv->pg_version_major = 0; - rv->pg_version_minor = 0; - rv->ms_jet = 0; -#ifdef MULTIBYTE - rv->client_encoding = NULL; - rv->server_encoding = NULL; -#endif /* MULTIBYTE */ - - - /* Initialize statement options to defaults */ - /* Statements under this conn will inherit these options */ - - InitializeStatementOptions(&rv->stmtOptions); - - - } - return rv; -} - - -char -CC_Destructor(ConnectionClass *self) -{ - mylog("enter CC_Destructor, self=%u\n", self); - - if (self->status == CONN_EXECUTING) - return 0; - - CC_cleanup(self); /* cleanup socket and statements */ - - mylog("after CC_Cleanup\n"); - -#ifdef MULTIBYTE - if (self->client_encoding) - free(self->client_encoding); - if (self->server_encoding) - free(self->server_encoding); -#endif /* MULTIBYTE */ - /* Free up statement holders */ - if (self->stmts) - { - free(self->stmts); - self->stmts = NULL; - } - mylog("after free statement holders\n"); - - /* Free cached table info */ - if (self->col_info) - { - int i; - - for (i = 0; i < self->ntables; i++) - { - if (self->col_info[i]->result) /* Free the SQLColumns - * result structure */ - QR_Destructor(self->col_info[i]->result); - - free(self->col_info[i]); - } - free(self->col_info); - } - - - free(self); - - mylog("exit CC_Destructor\n"); - - return 1; -} - - -/* Return how many cursors are opened on this connection */ -int -CC_cursor_count(ConnectionClass *self) -{ - StatementClass *stmt; - int i, - count = 0; - - mylog("CC_cursor_count: self=%u, num_stmts=%d\n", self, self->num_stmts); - - for (i = 0; i < self->num_stmts; i++) - { - stmt = self->stmts[i]; - if (stmt && stmt->result && stmt->result->cursor) - count++; - } - - mylog("CC_cursor_count: returning %d\n", count); - - return count; -} - - -void -CC_clear_error(ConnectionClass *self) -{ - self->errornumber = 0; - self->errormsg = NULL; - self->errormsg_created = FALSE; -} - - -/* - * Used to cancel a transaction. - * We are almost always in the middle of a transaction. - */ -char -CC_abort(ConnectionClass *self) -{ - QResultClass *res; - - if (CC_is_in_trans(self)) - { - res = NULL; - - mylog("CC_abort: sending ABORT!\n"); - - res = CC_send_query(self, "ABORT", NULL); - CC_set_no_trans(self); - - if (res != NULL) - QR_Destructor(res); - else - return FALSE; - - } - - return TRUE; -} - - -/* This is called by SQLDisconnect also */ -char -CC_cleanup(ConnectionClass *self) -{ - int i; - StatementClass *stmt; - - if (self->status == CONN_EXECUTING) - return FALSE; - - mylog("in CC_Cleanup, self=%u\n", self); - - /* Cancel an ongoing transaction */ - /* We are always in the middle of a transaction, */ - /* even if we are in auto commit. */ - if (self->sock) - CC_abort(self); - - mylog("after CC_abort\n"); - - /* This actually closes the connection to the dbase */ - if (self->sock) - { - SOCK_Destructor(self->sock); - self->sock = NULL; - } - - mylog("after SOCK destructor\n"); - - /* Free all the stmts on this connection */ - for (i = 0; i < self->num_stmts; i++) - { - stmt = self->stmts[i]; - if (stmt) - { - stmt->hdbc = NULL; /* prevent any more dbase interactions */ - - SC_Destructor(stmt); - - self->stmts[i] = NULL; - } - } - - /* Check for translation dll */ -#ifdef WIN32 - if (self->translation_handle) - { - FreeLibrary(self->translation_handle); - self->translation_handle = NULL; - } -#endif - - mylog("exit CC_Cleanup\n"); - return TRUE; -} - - -int -CC_set_translation(ConnectionClass *self) -{ - -#ifdef WIN32 - - if (self->translation_handle != NULL) - { - FreeLibrary(self->translation_handle); - self->translation_handle = NULL; - } - - if (self->connInfo.translation_dll[0] == 0) - return TRUE; - - self->translation_option = atoi(self->connInfo.translation_option); - self->translation_handle = LoadLibrary(self->connInfo.translation_dll); - - if (self->translation_handle == NULL) - { - self->errornumber = CONN_UNABLE_TO_LOAD_DLL; - self->errormsg = "Could not load the translation DLL."; - return FALSE; - } - - self->DataSourceToDriver - = (DataSourceToDriverProc) GetProcAddress(self->translation_handle, - "SQLDataSourceToDriver"); - - self->DriverToDataSource - = (DriverToDataSourceProc) GetProcAddress(self->translation_handle, - "SQLDriverToDataSource"); - - if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL) - { - self->errornumber = CONN_UNABLE_TO_LOAD_DLL; - self->errormsg = "Could not find translation DLL functions."; - return FALSE; - } -#endif - return TRUE; -} - -static int -md5_auth_send(ConnectionClass *self, const char *salt) -{ - char *pwd1 = NULL, *pwd2 = NULL; - ConnInfo *ci = &(self->connInfo); - SocketClass *sock = self->sock; - -mylog("MD5 user=%s password=%s\n", ci->username, ci->password); - if (!(pwd1 = malloc(MD5_PASSWD_LEN + 1))) - return 1; - if (!EncryptMD5(ci->password, ci->username, strlen(ci->username), pwd1)) - { - free(pwd1); - return 1; - } - if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1))) - { - free(pwd1); - return 1; - } - if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2)) - { - free(pwd2); - free(pwd1); - return 1; - } - free(pwd1); - SOCK_put_int(sock, 4 + strlen(pwd2) + 1, 4); - SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1); - SOCK_flush_output(sock); - free(pwd2); - return 0; -} - -char -CC_connect(ConnectionClass *self, char do_password) -{ - StartupPacket sp; - StartupPacket6_2 sp62; - QResultClass *res; - SocketClass *sock; - ConnInfo *ci = &(self->connInfo); - int areq = -1; - int beresp; - char msgbuffer[ERROR_MSG_LENGTH]; - char salt[5]; - static char *func = "CC_connect"; - -#ifdef MULTIBYTE - char *encoding; -#endif /* MULTIBYTE */ - - mylog("%s: entering...\n", func); - - if (do_password) - - sock = self->sock; /* already connected, just authenticate */ - - else - { - qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n", - POSTGRESDRIVERVERSION, - ci->drivers.fetch_max, - ci->drivers.socket_buffersize, - ci->drivers.unknown_sizes, - ci->drivers.max_varchar_size, - ci->drivers.max_longvarchar_size); - qlog(" disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n", - ci->drivers.disable_optimizer, - ci->drivers.ksqo, - ci->drivers.unique_index, - ci->drivers.use_declarefetch); - qlog(" text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d\n", - ci->drivers.text_as_longvarchar, - ci->drivers.unknowns_as_longvarchar, - ci->drivers.bools_as_char); - -#ifdef MULTIBYTE - encoding = check_client_encoding(ci->conn_settings); - if (encoding && strcmp(encoding, "OTHER")) - self->client_encoding = strdup(encoding); - else - { - encoding = check_client_encoding(ci->drivers.conn_settings); - if (encoding && strcmp(encoding, "OTHER")) - self->client_encoding = strdup(encoding); - } - qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n", - ci->drivers.extra_systable_prefixes, - ci->drivers.conn_settings, - encoding ? encoding : ""); -#else - qlog(" extra_systable_prefixes='%s', conn_settings='%s'\n", - ci->drivers.extra_systable_prefixes, - ci->drivers.conn_settings); -#endif - - if (self->status != CONN_NOT_CONNECTED) - { - self->errormsg = "Already connected."; - self->errornumber = CONN_OPENDB_ERROR; - return 0; - } - - if (ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\0') - { - self->errornumber = CONN_INIREAD_ERROR; - self->errormsg = "Missing server name, port, or database name in call to CC_connect."; - return 0; - } - - mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password); - -another_version_retry: - - /* - * If the socket was closed for some reason (like a SQLDisconnect, - * but no SQLFreeConnect then create a socket now. - */ - if (!self->sock) - { - self->sock = SOCK_Constructor(self); - if (!self->sock) - { - self->errornumber = CONNECTION_SERVER_NOT_REACHED; - self->errormsg = "Could not open a socket to the server"; - return 0; - } - } - - sock = self->sock; - - mylog("connecting to the server socket...\n"); - - SOCK_connect_to(sock, (short) atoi(ci->port), ci->server); - if (SOCK_get_errcode(sock) != 0) - { - mylog("connection to the server socket failed.\n"); - self->errornumber = CONNECTION_SERVER_NOT_REACHED; - self->errormsg = "Could not connect to the server"; - return 0; - } - mylog("connection to the server socket succeeded.\n"); - - if (PROTOCOL_62(ci)) - { - sock->reverse = TRUE; /* make put_int and get_int work - * for 6.2 */ - - memset(&sp62, 0, sizeof(StartupPacket6_2)); - SOCK_put_int(sock, htonl(4 + sizeof(StartupPacket6_2)), 4); - sp62.authtype = htonl(NO_AUTHENTICATION); - strncpy(sp62.database, ci->database, PATH_SIZE); - strncpy(sp62.user, ci->username, NAMEDATALEN); - SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2)); - SOCK_flush_output(sock); - } - else - { - memset(&sp, 0, sizeof(StartupPacket)); - - mylog("sizeof startup packet = %d\n", sizeof(StartupPacket)); - - /* Send length of Authentication Block */ - SOCK_put_int(sock, 4 + sizeof(StartupPacket), 4); - - if (PROTOCOL_63(ci)) - sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_63); - else - sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST); - - strncpy(sp.database, ci->database, SM_DATABASE); - strncpy(sp.user, ci->username, SM_USER); - - SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket)); - SOCK_flush_output(sock); - } - - mylog("sent the authentication block.\n"); - - if (sock->errornumber != 0) - { - mylog("couldn't send the authentication block properly.\n"); - self->errornumber = CONN_INVALID_AUTHENTICATION; - self->errormsg = "Sending the authentication packet failed"; - return 0; - } - mylog("sent the authentication block successfully.\n"); - } - - - mylog("gonna do authentication\n"); - - - /* - * Now get the authentication request from backend - */ - - if (!PROTOCOL_62(ci)) - { - BOOL before_64 = PG_VERSION_LT(self, 6.4), - ReadyForQuery = FALSE; - - do - { - if (do_password) - beresp = 'R'; - else - { - beresp = SOCK_get_char(sock); - mylog("auth got '%c'\n", beresp); - } - - switch (beresp) - { - case 'E': - - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - self->errornumber = CONN_INVALID_AUTHENTICATION; - self->errormsg = msgbuffer; - qlog("ERROR from backend during authentication: '%s'\n", self->errormsg); - if (strncmp(msgbuffer, "Unsupported frontend protocol", 29) == 0) - { /* retry older version */ - if (PROTOCOL_63(ci)) - strcpy(ci->protocol, PG62); - else - strcpy(ci->protocol, PG63); - SOCK_Destructor(sock); - self->sock = (SocketClass *) 0; - CC_initialize_pg_version(self); - goto another_version_retry; - } - - return 0; - case 'R': - - if (do_password) - { - mylog("in 'R' do_password\n"); - areq = AUTH_REQ_PASSWORD; - do_password = FALSE; - } - else - { - - areq = SOCK_get_int(sock, 4); - if (areq == AUTH_REQ_MD5) - SOCK_get_n_char(sock, salt, 4); - if (areq == AUTH_REQ_CRYPT) - SOCK_get_n_char(sock, salt, 2); - - mylog("areq = %d\n", areq); - } - switch (areq) - { - case AUTH_REQ_OK: - break; - - case AUTH_REQ_KRB4: - self->errormsg = "Kerberos 4 authentication not supported"; - self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED; - return 0; - - case AUTH_REQ_KRB5: - self->errormsg = "Kerberos 5 authentication not supported"; - self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED; - return 0; - - case AUTH_REQ_PASSWORD: - mylog("in AUTH_REQ_PASSWORD\n"); - - if (ci->password[0] == '\0') - { - self->errornumber = CONNECTION_NEED_PASSWORD; - self->errormsg = "A password is required for this connection."; - return -1; /* need password */ - } - - mylog("past need password\n"); - - SOCK_put_int(sock, 4 + strlen(ci->password) + 1, 4); - SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1); - SOCK_flush_output(sock); - - mylog("past flush\n"); - break; - - case AUTH_REQ_CRYPT: - self->errormsg = "Password crypt authentication not supported"; - self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED; - return 0; - case AUTH_REQ_MD5: - mylog("in AUTH_REQ_MD5\n"); - if (ci->password[0] == '\0') - { - self->errornumber = CONNECTION_NEED_PASSWORD; - self->errormsg = "A password is required for this connection."; - return -1; /* need password */ - } - if (md5_auth_send(self, salt)) - { - self->errormsg = "md5 hashing failed"; - self->errornumber = CONN_INVALID_AUTHENTICATION; - return 0; - } - break; - - case AUTH_REQ_SCM_CREDS: - self->errormsg = "Unix socket credential authentication not supported"; - self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED; - return 0; - - default: - self->errormsg = "Unknown authentication type"; - self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED; - return 0; - } - break; - case 'K': /* Secret key (6.4 protocol) */ - (void) SOCK_get_int(sock, 4); /* pid */ - (void) SOCK_get_int(sock, 4); /* key */ - - break; - case 'Z': /* Backend is ready for new query (6.4) */ - ReadyForQuery = TRUE; - break; - default: - self->errormsg = "Unexpected protocol character during authentication"; - self->errornumber = CONN_INVALID_AUTHENTICATION; - return 0; - } - - /* - * There were no ReadyForQuery responce before 6.4. - */ - if (before_64 && areq == AUTH_REQ_OK) - ReadyForQuery = TRUE; - } while (!ReadyForQuery); - } - - - CC_clear_error(self); /* clear any password error */ - - /* - * 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); - if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY) - { - mylog("got no result from the empty query. (probably database does not exist)\n"); - self->errornumber = CONNECTION_NO_SUCH_DATABASE; - self->errormsg = "The database does not exist on the server\nor user authentication failed."; - if (res != NULL) - QR_Destructor(res); - return 0; - } - if (res) - QR_Destructor(res); - - mylog("empty query seems to be OK.\n"); - - CC_set_translation(self); - - /* - * Send any initial settings - */ - - /* - * Since these functions allocate statements, and since the connection - * is not established yet, it would violate odbc state transition - * rules. Therefore, these functions call the corresponding local - * function instead. - */ - CC_send_settings(self); - CC_lookup_lo(self); /* a hack to get the oid of our large - * object oid type */ - CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo - * use */ - - CC_clear_error(self); /* clear any initial command errors */ - self->status = CONN_CONNECTED; - - mylog("%s: returning...\n", func); - - return 1; - -} - - -char -CC_add_statement(ConnectionClass *self, StatementClass *stmt) -{ - int i; - - mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt); - - for (i = 0; i < self->num_stmts; i++) - { - if (!self->stmts[i]) - { - stmt->hdbc = self; - self->stmts[i] = stmt; - return TRUE; - } - } - - /* no more room -- allocate more memory */ - self->stmts = (StatementClass **) realloc(self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts)); - if (!self->stmts) - return FALSE; - - memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT); - - stmt->hdbc = self; - self->stmts[self->num_stmts] = stmt; - - self->num_stmts += STMT_INCREMENT; - - return TRUE; -} - - -char -CC_remove_statement(ConnectionClass *self, StatementClass *stmt) -{ - int i; - - for (i = 0; i < self->num_stmts; i++) - { - if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING) - { - self->stmts[i] = NULL; - return TRUE; - } - } - - 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) -{ - SocketClass *sock = self->sock; - int pos; - static char msg[4096]; - - mylog("enter CC_create_errormsg\n"); - - msg[0] = '\0'; - - if (self->errormsg) - strcpy(msg, self->errormsg); - - mylog("msg = '%s'\n", msg); - - if (sock && sock->errormsg && sock->errormsg[0] != '\0') - { - pos = strlen(msg); - sprintf(&msg[pos], ";\n%s", sock->errormsg); - } - - mylog("exit CC_create_errormsg\n"); - return msg; -} - - -char -CC_get_error(ConnectionClass *self, int *number, char **message) -{ - int rv; - - mylog("enter CC_get_error\n"); - - /* Create a very informative errormsg if it hasn't been done yet. */ - if (!self->errormsg_created) - { - self->errormsg = CC_create_errormsg(self); - self->errormsg_created = TRUE; - } - - if (self->errornumber) - { - *number = self->errornumber; - *message = self->errormsg; - } - rv = (self->errornumber != 0); - - self->errornumber = 0; /* clear the error */ - - mylog("exit CC_get_error\n"); - - return rv; -} - - -/* - * 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) -{ - QResultClass *result_in = NULL, - *res = NULL, - *retres = NULL; - char swallow, - *wq; - int id; - SocketClass *sock = self->sock; - int maxlen, - empty_reqs; - BOOL msg_truncated, - ReadyToReturn, - tuples_return = FALSE, - query_completed = FALSE, - before_64 = PG_VERSION_LT(self, 6.4); - - /* ERROR_MSG_LENGTH is suffcient */ - static char msgbuffer[ERROR_MSG_LENGTH + 1]; - - /* QR_set_command() dups this string so doesn't need static */ - char cmdbuffer[ERROR_MSG_LENGTH + 1]; - - mylog("send_query(): conn=%u, query='%s'\n", self, query); - qlog("conn=%u, query='%s'\n", self, query); - - /* Indicate that we are sending a query to the backend */ - maxlen = CC_get_max_query_len(self); - if (maxlen > 0 && maxlen < (int) strlen(query) + 1) - { - self->errornumber = CONNECTION_MSG_TOO_LONG; - self->errormsg = "Query string is too long"; - return NULL; - } - - if ((NULL == query) || (query[0] == '\0')) - return NULL; - - if (SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_COULD_NOT_SEND; - self->errormsg = "Could not send Query to backend"; - CC_set_no_trans(self); - return NULL; - } - - SOCK_put_char(sock, 'Q'); - if (SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_COULD_NOT_SEND; - self->errormsg = "Could not send Query to backend"; - CC_set_no_trans(self); - return NULL; - } - - SOCK_put_string(sock, query); - SOCK_flush_output(sock); - - if (SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_COULD_NOT_SEND; - self->errormsg = "Could not send Query to backend"; - CC_set_no_trans(self); - return NULL; - } - - mylog("send_query: done sending query\n"); - - ReadyToReturn = FALSE; - empty_reqs = 0; - for (wq = query; isspace((unsigned char) *wq); wq++) - ; - if (*wq == '\0') - empty_reqs = 1; - while (!ReadyToReturn) - { - /* what type of message is coming now ? */ - id = SOCK_get_char(sock); - - if ((SOCK_get_errcode(sock) != 0) || (id == EOF)) - { - self->errornumber = CONNECTION_NO_RESPONSE; - self->errormsg = "No response from the backend"; - - mylog("send_query: 'id' - %s\n", self->errormsg); - CC_set_no_trans(self); - ReadyToReturn = TRUE; - retres = NULL; - break; - } - - mylog("send_query: got id = '%c'\n", id); - - switch (id) - { - case 'A': /* Asynchronous Messages are ignored */ - (void) SOCK_get_int(sock, 4); /* id of notification */ - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - /* name of the relation the message comes from */ - break; - case 'C': /* portal query command, no tuples - * returned */ - /* read in the return message from the backend */ - SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); - if (SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_NO_RESPONSE; - self->errormsg = "No response from backend while receiving a portal query command"; - mylog("send_query: 'C' - %s\n", self->errormsg); - CC_set_no_trans(self); - ReadyToReturn = TRUE; - retres = NULL; - } - else - { - mylog("send_query: ok - 'C' - %s\n", cmdbuffer); - - if (res == NULL) /* allow for "show" style notices */ - res = QR_Constructor(); - - mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer); - - /* Only save the first command */ - if (QR_command_successful(res)) - QR_set_status(res, PGRES_COMMAND_OK); - QR_set_command(res, cmdbuffer); - query_completed = TRUE; - mylog("send_query: returning res = %u\n", res); - if (!before_64) - break; - - /* - * (Quotation from the original comments) since - * backend may produce more than one result for some - * commands we need to poll until clear so we send an - * empty query, and keep reading out of the pipe until - * an 'I' is received - */ - - if (empty_reqs == 0) - { - SOCK_put_string(sock, "Q "); - SOCK_flush_output(sock); - empty_reqs++; - } - } - break; - case 'Z': /* Backend is ready for new query (6.4) */ - if (empty_reqs == 0) - { - ReadyToReturn = TRUE; - if (res && QR_get_aborted(res)) - retres = res; - else if (tuples_return) - retres = result_in; - else if (query_completed) - retres = res; - else - ReadyToReturn = FALSE; - } - break; - case 'N': /* NOTICE: */ - msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); - if (!res) - res = QR_Constructor(); - if (QR_command_successful(res)) - QR_set_status(res, PGRES_NONFATAL_ERROR); - QR_set_notice(res, cmdbuffer); /* will dup this string */ - - mylog("~~~ NOTICE: '%s'\n", cmdbuffer); - qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer); - while (msg_truncated) - msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); - - continue; /* dont return a result -- continue - * reading */ - - case 'I': /* The server sends an empty query */ - /* There is a closing '\0' following the 'I', so we eat it */ - swallow = SOCK_get_char(sock); - if (!res) - res = QR_Constructor(); - if ((swallow != '\0') || SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_BACKEND_CRAZY; - self->errormsg = "Unexpected protocol character from backend (send_query - I)"; - QR_set_status(res, PGRES_FATAL_ERROR); - ReadyToReturn = TRUE; - retres = res; - break; - } - else - { - /* We return the empty query */ - QR_set_status(res, PGRES_EMPTY_QUERY); - } - if (empty_reqs > 0) - { - if (--empty_reqs == 0) - query_completed = TRUE; - } - break; - case 'E': - msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - - /* Remove a newline */ - if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer) - 1] == '\n') - msgbuffer[strlen(msgbuffer) - 1] = '\0'; - - self->errormsg = msgbuffer; - - mylog("send_query: 'E' - %s\n", self->errormsg); - qlog("ERROR from backend during send_query: '%s'\n", self->errormsg); - - /* We should report that an error occured. Zoltan */ - if (!res) - res = QR_Constructor(); - - if (!strncmp(self->errormsg, "FATAL", 5)) - { - self->errornumber = CONNECTION_SERVER_REPORTED_ERROR; - CC_set_no_trans(self); - } - else - self->errornumber = CONNECTION_SERVER_REPORTED_WARNING; - QR_set_status(res, PGRES_FATAL_ERROR); - QR_set_aborted(res, TRUE); - while (msg_truncated) - msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); - - query_completed = TRUE; - break; - - case 'P': /* get the Portal name */ - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - break; - case 'T': /* Tuple results start here */ - result_in = qi ? qi->result_in : NULL; - - if (result_in == NULL) - { - result_in = QR_Constructor(); - mylog("send_query: 'T' no result_in: res = %u\n", result_in); - if (!result_in) - { - self->errornumber = CONNECTION_COULD_NOT_RECEIVE; - self->errormsg = "Could not create result info in send_query."; - ReadyToReturn = TRUE; - retres = NULL; - break; - } - - if (qi) - QR_set_cache_size(result_in, qi->row_size); - - if (!QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL)) - { - self->errornumber = CONNECTION_COULD_NOT_RECEIVE; - self->errormsg = QR_get_message(result_in); - ReadyToReturn = TRUE; - retres = NULL; - break; - } - } - else - { /* next fetch, so reuse an existing result */ - - /* - * called from QR_next_tuple and must return - * immediately. - */ - ReadyToReturn = TRUE; - if (!QR_fetch_tuples(result_in, NULL, NULL)) - { - self->errornumber = CONNECTION_COULD_NOT_RECEIVE; - self->errormsg = QR_get_message(result_in); - retres = NULL; - break; - } - retres = result_in; - } - - tuples_return = TRUE; - break; - case 'D': /* Copy in command began successfully */ - if (!res) - res = QR_Constructor(); - if (QR_command_successful(res)) - QR_set_status(res, PGRES_COPY_IN); - ReadyToReturn = TRUE; - retres = res; - break; - case 'B': /* Copy out command began successfully */ - if (!res) - res = QR_Constructor(); - if (QR_command_successful(res)) - QR_set_status(res, PGRES_COPY_OUT); - ReadyToReturn = TRUE; - retres = res; - break; - default: - self->errornumber = CONNECTION_BACKEND_CRAZY; - self->errormsg = "Unexpected protocol character from backend (send_query)"; - CC_set_no_trans(self); - - mylog("send_query: error - %s\n", self->errormsg); - ReadyToReturn = TRUE; - retres = NULL; - break; - } - - /* - * There were no ReadyForQuery response before 6.4. - */ - if (before_64) - { - if (empty_reqs == 0 && (query_completed || tuples_return)) - break; - } - } - - /* - * Break before being ready to return. - */ - if (!ReadyToReturn) - { - if (res && QR_get_aborted(res)) - retres = res; - else if (tuples_return) - retres = result_in; - else - retres = res; - } - - /* - * set notice message to result_in. - */ - if (result_in && res && retres == result_in) - { - if (QR_command_successful(result_in)) - QR_set_status(result_in, QR_get_status(res)); - QR_set_notice(result_in, QR_get_notice(res)); - } - - /* - * Cleanup garbage results before returning. - */ - if (res && retres != res) - QR_Destructor(res); - if (result_in && retres != result_in) - { - if (qi && qi->result_in) - ; - else - QR_Destructor(result_in); - } - return retres; -} - - -int -CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs) -{ - char id, - c, - done; - SocketClass *sock = self->sock; - - /* ERROR_MSG_LENGTH is sufficient */ - static char msgbuffer[ERROR_MSG_LENGTH + 1]; - int i; - - mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs); - - if (SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_COULD_NOT_SEND; - self->errormsg = "Could not send function to backend"; - CC_set_no_trans(self); - return FALSE; - } - - SOCK_put_string(sock, "F "); - if (SOCK_get_errcode(sock) != 0) - { - self->errornumber = CONNECTION_COULD_NOT_SEND; - self->errormsg = "Could not send function to backend"; - CC_set_no_trans(self); - return FALSE; - } - - SOCK_put_int(sock, fnid, 4); - SOCK_put_int(sock, nargs, 4); - - - mylog("send_function: done sending function\n"); - - 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); - if (args[i].isint) - SOCK_put_int(sock, args[i].u.integer, 4); - else - SOCK_put_n_char(sock, (char *) args[i].u.ptr, args[i].len); - - - } - - mylog(" done sending args\n"); - - SOCK_flush_output(sock); - mylog(" after flush output\n"); - - done = FALSE; - while (!done) - { - id = SOCK_get_char(sock); - mylog(" got id = %c\n", id); - - switch (id) - { - case 'V': - done = TRUE; - break; /* ok */ - - case 'N': - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - mylog("send_function(V): 'N' - %s\n", msgbuffer); - /* continue reading */ - break; - - case 'E': - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - self->errormsg = msgbuffer; - - mylog("send_function(V): 'E' - %s\n", self->errormsg); - qlog("ERROR from backend during send_function: '%s'\n", self->errormsg); - - return FALSE; - - case 'Z': - break; - - default: - self->errornumber = CONNECTION_BACKEND_CRAZY; - self->errormsg = "Unexpected protocol character from backend (send_function, args)"; - CC_set_no_trans(self); - - mylog("send_function: error - %s\n", self->errormsg); - return FALSE; - } - } - - id = SOCK_get_char(sock); - for (;;) - { - switch (id) - { - case 'G': /* function returned properly */ - mylog(" got G!\n"); - - *actual_result_len = SOCK_get_int(sock, 4); - mylog(" actual_result_len = %d\n", *actual_result_len); - - if (result_is_int) - *((int *) result_buf) = SOCK_get_int(sock, 4); - else - SOCK_get_n_char(sock, (char *) result_buf, *actual_result_len); - - mylog(" after get result\n"); - - c = SOCK_get_char(sock); /* get the last '0' */ - - mylog(" after get 0\n"); - - return TRUE; - - case 'E': - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - self->errormsg = msgbuffer; - - mylog("send_function(G): 'E' - %s\n", self->errormsg); - qlog("ERROR from backend during send_function: '%s'\n", self->errormsg); - - return FALSE; - - case 'N': - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - - mylog("send_function(G): 'N' - %s\n", msgbuffer); - qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer); - - continue; /* dont return a result -- continue - * reading */ - - case '0': /* empty result */ - return TRUE; - - default: - self->errornumber = CONNECTION_BACKEND_CRAZY; - self->errormsg = "Unexpected protocol character from backend (send_function, result)"; - CC_set_no_trans(self); - - mylog("send_function: error - %s\n", self->errormsg); - return FALSE; - } - } -} - - -char -CC_send_settings(ConnectionClass *self) -{ - /* char ini_query[MAX_MESSAGE_LEN]; */ - ConnInfo *ci = &(self->connInfo); - -/* QResultClass *res; */ - HSTMT hstmt; - StatementClass *stmt; - RETCODE result; - char status = TRUE; - char *cs, - *ptr; - static char *func = "CC_send_settings"; - - - 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 = PGAPI_AllocStmt(self, &hstmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - return FALSE; - stmt = (StatementClass *) hstmt; - - stmt->internal = TRUE; /* ensure no BEGIN/COMMIT/ABORT stuff */ - - /* Set the Datestyle to the format the driver expects it to be in */ - result = PGAPI_ExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - status = FALSE; - - mylog("%s: result %d, status %d from set DateStyle\n", func, result, status); - - /* Disable genetic optimizer based on global flag */ - if (ci->drivers.disable_optimizer) - { - result = PGAPI_ExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - status = FALSE; - - mylog("%s: result %d, status %d from set geqo\n", func, result, status); - - } - - /* KSQO */ - if (ci->drivers.ksqo) - { - result = PGAPI_ExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - status = FALSE; - - mylog("%s: result %d, status %d from set ksqo\n", func, result, status); - - } - - /* Global settings */ - if (ci->drivers.conn_settings[0] != '\0') - { - cs = strdup(ci->drivers.conn_settings); - ptr = strtok(cs, ";"); - while (ptr) - { - result = PGAPI_ExecDirect(hstmt, ptr, SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - status = FALSE; - - mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr); - - ptr = strtok(NULL, ";"); - } - - free(cs); - } - - /* Per Datasource settings */ - if (ci->conn_settings[0] != '\0') - { - cs = strdup(ci->conn_settings); - ptr = strtok(cs, ";"); - while (ptr) - { - result = PGAPI_ExecDirect(hstmt, ptr, SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - status = FALSE; - - mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr); - - ptr = strtok(NULL, ";"); - } - - free(cs); - } - - - PGAPI_FreeStmt(hstmt, SQL_DROP); - - 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) -{ - HSTMT hstmt; - StatementClass *stmt; - RETCODE result; - static char *func = "CC_lookup_lo"; - - 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 = PGAPI_AllocStmt(self, &hstmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - return; - stmt = (StatementClass *) hstmt; - - result = PGAPI_ExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - PGAPI_FreeStmt(hstmt, SQL_DROP); - return; - } - - result = PGAPI_Fetch(hstmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - PGAPI_FreeStmt(hstmt, SQL_DROP); - return; - } - - result = PGAPI_GetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - PGAPI_FreeStmt(hstmt, SQL_DROP); - return; - } - - mylog("Got the large object oid: %d\n", self->lobj_type); - qlog(" [ Large Object oid = %d ]\n", self->lobj_type); - - result = PGAPI_FreeStmt(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) -{ - strcpy(self->pg_version, self->connInfo.protocol); - if (PROTOCOL_62(&self->connInfo)) - { - self->pg_version_number = (float) 6.2; - self->pg_version_major = 6; - self->pg_version_minor = 2; - } - else if (PROTOCOL_63(&self->connInfo)) - { - self->pg_version_number = (float) 6.3; - self->pg_version_major = 6; - self->pg_version_minor = 3; - } - else - { - self->pg_version_number = (float) 6.4; - self->pg_version_major = 6; - self->pg_version_minor = 4; - } -} - - -/* - * 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) -{ - HSTMT hstmt; - StatementClass *stmt; - RETCODE result; - char szVersion[32]; - int major, - minor; - static char *func = "CC_lookup_pg_version"; - - 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 = PGAPI_AllocStmt(self, &hstmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - return; - stmt = (StatementClass *) hstmt; - - /* get the server's version if possible */ - result = PGAPI_ExecDirect(hstmt, "select version()", SQL_NTS); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - PGAPI_FreeStmt(hstmt, SQL_DROP); - return; - } - - result = PGAPI_Fetch(hstmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - PGAPI_FreeStmt(hstmt, SQL_DROP); - return; - } - - result = PGAPI_GetData(hstmt, 1, SQL_C_CHAR, self->pg_version, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - PGAPI_FreeStmt(hstmt, SQL_DROP); - 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) - { - sprintf(szVersion, "%d.%d", major, minor); - self->pg_version_major = major; - self->pg_version_minor = minor; - } - self->pg_version_number = (float) atof(szVersion); - - mylog("Got the PostgreSQL version string: '%s'\n", self->pg_version); - mylog("Extracted PostgreSQL version number: '%1.1f'\n", self->pg_version_number); - qlog(" [ PostgreSQL version string = '%s' ]\n", self->pg_version); - qlog(" [ PostgreSQL version number = '%1.1f' ]\n", self->pg_version_number); - - result = PGAPI_FreeStmt(hstmt, SQL_DROP); -} - - -void -CC_log_error(char *func, char *desc, ConnectionClass *self) -{ -#ifdef PRN_NULLCHECK -#define nullcheck(a) (a ? a : "(NULL)") -#endif - - if (self) - { - qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); - mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); - qlog(" ------------------------------------------------------------\n"); - qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts); - qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type); - - qlog(" ---------------- Socket Info -------------------------------\n"); - if (self->sock) - { - SocketClass *sock = self->sock; - - qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg)); - qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out); - qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in); - } - } - else - qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc); -#undef PRN_NULLCHECK -} - -int -CC_get_max_query_len(const ConnectionClass *conn) -{ - int value; - - /* Long Queries in 7.0+ */ - if (PG_VERSION_GE(conn, 7.0)) - value = 0 /* 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; - return value; -} diff --git a/src/interfaces/odbc/windev/connection.h b/src/interfaces/odbc/windev/connection.h deleted file mode 100644 index a80c31b921..0000000000 --- a/src/interfaces/odbc/windev/connection.h +++ /dev/null @@ -1,312 +0,0 @@ -/* File: connection.h - * - * Description: See "connection.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __CONNECTION_H__ -#define __CONNECTION_H__ - -#include "psqlodbc.h" - -#include -#include - - -typedef enum -{ - CONN_NOT_CONNECTED, /* Connection has not been established */ - CONN_CONNECTED, /* Connection is up and has been - * established */ - CONN_DOWN, /* Connection is broken */ - CONN_EXECUTING /* the connection is currently executing a - * statement */ -} CONN_Status; - -/* These errors have general sql error state */ -#define CONNECTION_SERVER_NOT_REACHED 101 -#define CONNECTION_MSG_TOO_LONG 103 -#define CONNECTION_COULD_NOT_SEND 104 -#define CONNECTION_NO_SUCH_DATABASE 105 -#define CONNECTION_BACKEND_CRAZY 106 -#define CONNECTION_NO_RESPONSE 107 -#define CONNECTION_SERVER_REPORTED_ERROR 108 -#define CONNECTION_COULD_NOT_RECEIVE 109 -#define CONNECTION_SERVER_REPORTED_WARNING 110 -#define CONNECTION_NEED_PASSWORD 112 - -/* These errors correspond to specific SQL states */ -#define CONN_INIREAD_ERROR 201 -#define CONN_OPENDB_ERROR 202 -#define CONN_STMT_ALLOC_ERROR 203 -#define CONN_IN_USE 204 -#define CONN_UNSUPPORTED_OPTION 205 -/* Used by SetConnectoption to indicate unsupported options */ -#define CONN_INVALID_ARGUMENT_NO 206 -/* SetConnectOption: corresponds to ODBC--"S1009" */ -#define CONN_TRANSACT_IN_PROGRES 207 -#define CONN_NO_MEMORY_ERROR 208 -#define CONN_NOT_IMPLEMENTED_ERROR 209 -#define CONN_INVALID_AUTHENTICATION 210 -#define CONN_AUTH_TYPE_UNSUPPORTED 211 -#define CONN_UNABLE_TO_LOAD_DLL 212 - -#define CONN_OPTION_VALUE_CHANGED 213 -#define CONN_VALUE_OUT_OF_RANGE 214 - -#define CONN_TRUNCATED 215 - -/* Conn_status defines */ -#define CONN_IN_AUTOCOMMIT 0x01 -#define CONN_IN_TRANSACTION 0x02 - -/* AutoCommit functions */ -#define CC_set_autocommit_off(x) (x->transact_status &= ~CONN_IN_AUTOCOMMIT) -#define CC_set_autocommit_on(x) (x->transact_status |= CONN_IN_AUTOCOMMIT) -#define CC_is_in_autocommit(x) (x->transact_status & CONN_IN_AUTOCOMMIT) - -/* Transaction in/not functions */ -#define CC_set_in_trans(x) (x->transact_status |= CONN_IN_TRANSACTION) -#define CC_set_no_trans(x) (x->transact_status &= ~CONN_IN_TRANSACTION) -#define CC_is_in_trans(x) (x->transact_status & CONN_IN_TRANSACTION) - - -/* Authentication types */ -#define AUTH_REQ_OK 0 -#define AUTH_REQ_KRB4 1 -#define AUTH_REQ_KRB5 2 -#define AUTH_REQ_PASSWORD 3 -#define AUTH_REQ_CRYPT 4 -#define AUTH_REQ_MD5 5 -#define AUTH_REQ_SCM_CREDS 6 - -/* Startup Packet sizes */ -#define SM_DATABASE 64 -#define SM_USER 32 -#define SM_OPTIONS 64 -#define SM_UNUSED 64 -#define SM_TTY 64 - -/* Old 6.2 protocol defines */ -#define NO_AUTHENTICATION 7 -#define PATH_SIZE 64 -#define ARGV_SIZE 64 -#define NAMEDATALEN 16 - -typedef unsigned int ProtocolVersion; - -#define PG_PROTOCOL(major, minor) (((major) << 16) | (minor)) -#define PG_PROTOCOL_LATEST PG_PROTOCOL(2, 0) -#define PG_PROTOCOL_63 PG_PROTOCOL(1, 0) -#define PG_PROTOCOL_62 PG_PROTOCOL(0, 0) - -/* This startup packet is to support latest Postgres protocol (6.4, 6.3) */ -typedef struct _StartupPacket -{ - ProtocolVersion protoVersion; - char database[SM_DATABASE]; - char user[SM_USER]; - char options[SM_OPTIONS]; - char unused[SM_UNUSED]; - char tty[SM_TTY]; -} StartupPacket; - - -/* This startup packet is to support pre-Postgres 6.3 protocol */ -typedef struct _StartupPacket6_2 -{ - unsigned int authtype; - char database[PATH_SIZE]; - char user[NAMEDATALEN]; - char options[ARGV_SIZE]; - char execfile[ARGV_SIZE]; - char tty[PATH_SIZE]; -} StartupPacket6_2; - - -/* Structure to hold all the connection attributes for a specific - connection (used for both registry and file, DSN and DRIVER) -*/ -typedef struct -{ - char dsn[MEDIUM_REGISTRY_LEN]; - char desc[MEDIUM_REGISTRY_LEN]; - char driver[MEDIUM_REGISTRY_LEN]; - char server[MEDIUM_REGISTRY_LEN]; - char database[MEDIUM_REGISTRY_LEN]; - char username[MEDIUM_REGISTRY_LEN]; - char password[MEDIUM_REGISTRY_LEN]; - char conn_settings[LARGE_REGISTRY_LEN]; - char protocol[SMALL_REGISTRY_LEN]; - char port[SMALL_REGISTRY_LEN]; - char onlyread[SMALL_REGISTRY_LEN]; - char fake_oid_index[SMALL_REGISTRY_LEN]; - char show_oid_column[SMALL_REGISTRY_LEN]; - char row_versioning[SMALL_REGISTRY_LEN]; - char show_system_tables[SMALL_REGISTRY_LEN]; - char translation_dll[MEDIUM_REGISTRY_LEN]; - char translation_option[SMALL_REGISTRY_LEN]; - char focus_password; - char disallow_premature; - char updatable_cursors; - GLOBAL_VALUES drivers; /* moved from driver's option */ -} ConnInfo; - -/* Macro to determine is the connection using 6.2 protocol? */ -#define PROTOCOL_62(conninfo_) (strncmp((conninfo_)->protocol, PG62, strlen(PG62)) == 0) - -/* Macro to determine is the connection using 6.3 protocol? */ -#define PROTOCOL_63(conninfo_) (strncmp((conninfo_)->protocol, PG63, strlen(PG63)) == 0) - -/* - * Macros to compare the server's version with a specified version - * 1st parameter: pointer to a ConnectionClass object - * 2nd parameter: major version number - * 3rd parameter: minor version number - */ -#define SERVER_VERSION_GT(conn, major, minor) \ - ((conn)->pg_version_major > major || \ - ((conn)->pg_version_major == major && (conn)->pg_version_minor > minor)) -#define SERVER_VERSION_GE(conn, major, minor) \ - ((conn)->pg_version_major > major || \ - ((conn)->pg_version_major == major && (conn)->pg_version_minor >= minor)) -#define SERVER_VERSION_EQ(conn, major, minor) \ - ((conn)->pg_version_major == major && (conn)->pg_version_minor == minor) -#define SERVER_VERSION_LE(conn, major, minor) (! SERVER_VERSION_GT(conn, major, minor)) -#define SERVER_VERSION_LT(conn, major, minor) (! SERVER_VERSION_GE(conn, major, minor)) -/*#if ! defined(HAVE_CONFIG_H) || defined(HAVE_STRINGIZE)*/ -#define STRING_AFTER_DOT(string) (strchr(#string, '.') + 1) -/*#else -#define STRING_AFTER_DOT(str) (strchr("str", '.') + 1) -#endif*/ -/* - * Simplified macros to compare the server's version with a - * specified version - * Note: Never pass a variable as the second parameter. - * It must be a decimal constant of the form %d.%d . - */ -#define PG_VERSION_GT(conn, ver) \ - (SERVER_VERSION_GT(conn, (int) ver, atoi(STRING_AFTER_DOT(ver)))) -#define PG_VERSION_GE(conn, ver) \ - (SERVER_VERSION_GE(conn, (int) ver, atoi(STRING_AFTER_DOT(ver)))) -#define PG_VERSION_EQ(conn, ver) \ - (SERVER_VERSION_EQ(conn, (int) ver, atoi(STRING_AFTER_DOT(ver)))) -#define PG_VERSION_LE(conn, ver) (! PG_VERSION_GT(conn, ver)) -#define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver)) - -/* This is used to store cached table information in the connection */ -struct col_info -{ - QResultClass *result; - char name[MAX_TABLE_LEN + 1]; -}; - - /* Translation DLL entry points */ -#ifdef WIN32 -#define DLLHANDLE HINSTANCE -#else -#define WINAPI CALLBACK -#define DLLHANDLE void * -#define HINSTANCE void * -#endif - -typedef BOOL (FAR WINAPI * DataSourceToDriverProc) (UDWORD, - SWORD, - PTR, - SDWORD, - PTR, - SDWORD, - SDWORD FAR *, - UCHAR FAR *, - SWORD, - SWORD FAR *); - -typedef BOOL (FAR WINAPI * DriverToDataSourceProc) (UDWORD, - SWORD, - PTR, - SDWORD, - PTR, - SDWORD, - SDWORD FAR *, - UCHAR FAR *, - SWORD, - SWORD FAR *); - -/******* The Connection handle ************/ -struct ConnectionClass_ -{ - HENV henv; /* environment this connection was created - * on */ - StatementOptions stmtOptions; - char *errormsg; - int errornumber; - CONN_Status status; - ConnInfo connInfo; - StatementClass **stmts; - int num_stmts; - SocketClass *sock; - int lobj_type; - int ntables; - COL_INFO **col_info; - long translation_option; - HINSTANCE translation_handle; - DataSourceToDriverProc DataSourceToDriver; - DriverToDataSourceProc DriverToDataSource; - Int2 driver_version; /* prepared for ODBC3.0 */ - char transact_status;/* Is a transaction is currently in - * progress */ - char errormsg_created; /* has an informative error msg - * been created? */ - char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL - * we're connected to - - * DJP 25-1-2001 */ - float pg_version_number; - Int2 pg_version_major; - Int2 pg_version_minor; - char ms_jet; -#ifdef MULTIBYTE - char *client_encoding; - char *server_encoding; -#endif /* MULTIBYTE */ -}; - - -/* Accessor functions */ -#define CC_get_socket(x) (x->sock) -#define CC_get_database(x) (x->connInfo.database) -#define CC_get_server(x) (x->connInfo.server) -#define CC_get_DSN(x) (x->connInfo.dsn) -#define CC_get_username(x) (x->connInfo.username) -#define CC_is_onlyread(x) (x->connInfo.onlyread[0] == '1') - - -/* for CC_DSN_info */ -#define CONN_DONT_OVERWRITE 0 -#define CONN_OVERWRITE 1 - - -/* prototypes */ -ConnectionClass *CC_Constructor(void); -char CC_Destructor(ConnectionClass *self); -int CC_cursor_count(ConnectionClass *self); -char CC_cleanup(ConnectionClass *self); -char CC_abort(ConnectionClass *self); -int CC_set_translation(ConnectionClass *self); -char CC_connect(ConnectionClass *self, char do_password); -char CC_add_statement(ConnectionClass *self, StatementClass *stmt); -char CC_remove_statement(ConnectionClass *self, StatementClass *stmt); -char CC_get_error(ConnectionClass *self, int *number, char **message); -QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi); -void CC_clear_error(ConnectionClass *self); -char *CC_create_errormsg(ConnectionClass *self); -int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs); -char CC_send_settings(ConnectionClass *self); -void CC_lookup_lo(ConnectionClass *conn); -void CC_lookup_pg_version(ConnectionClass *conn); -void CC_initialize_pg_version(ConnectionClass *conn); -void CC_log_error(char *func, char *desc, ConnectionClass *self); -int CC_get_max_query_len(const ConnectionClass *self); - -#endif diff --git a/src/interfaces/odbc/windev/convert.c b/src/interfaces/odbc/windev/convert.c deleted file mode 100644 index 0b609a07db..0000000000 --- a/src/interfaces/odbc/windev/convert.c +++ /dev/null @@ -1,2655 +0,0 @@ -/*------- - * Module: convert.c - * - * Description: This module contains routines related to - * converting parameters and columns into requested data types. - * Parameters are converted from their SQL_C data types into - * the appropriate postgres type. Columns are converted from - * their postgres type (SQL type) into the appropriate SQL_C - * data type. - * - * Classes: n/a - * - * API functions: none - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ -/* Multibyte support Eiji Tokuya 2001-03-15 */ - -#include "convert.h" - -#include -#include -#include - -#ifdef MULTIBYTE -#include "multibyte.h" -#endif - -#include -#include -#include -#include "statement.h" -#include "qresult.h" -#include "bind.h" -#include "pgtypes.h" -#include "lobj.h" -#include "connection.h" -#include "pgapifunc.h" - -#ifdef __CYGWIN__ -#define TIMEZONE_GLOBAL _timezone -#elif defined(WIN32) || defined(HAVE_INT_TIMEZONE) -#define TIMEZONE_GLOBAL timezone -#endif - -/* - * 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" }, */ - {"CHAR", "chr"}, - {"CONCAT", "textcat"}, -/* { "DIFFERENCE", "difference" }, */ -/* { "INSERT", "insert" }, */ - {"LCASE", "lower"}, - {"LEFT", "ltrunc"}, - {"LOCATE", "strpos"}, - {"LENGTH", "char_length"}, -/* { "LTRIM", "ltrim" }, */ - {"RIGHT", "rtrunc"}, -/* { "REPEAT", "repeat" }, */ -/* { "REPLACE", "replace" }, */ -/* { "RTRIM", "rtrim" }, */ -/* { "SOUNDEX", "soundex" }, */ - {"SUBSTRING", "substr"}, - {"UCASE", "upper"}, - -/* { "ABS", "abs" }, */ -/* { "ACOS", "acos" }, */ -/* { "ASIN", "asin" }, */ -/* { "ATAN", "atan" }, */ -/* { "ATAN2", "atan2" }, */ - {"CEILING", "ceil"}, -/* { "COS", "cos" }, */ -/* { "COT", "cot" }, */ -/* { "DEGREES", "degrees" }, */ -/* { "EXP", "exp" }, */ -/* { "FLOOR", "floor" }, */ - {"LOG", "ln"}, - {"LOG10", "log"}, -/* { "MOD", "mod" }, */ -/* { "PI", "pi" }, */ - {"POWER", "pow"}, -/* { "RADIANS", "radians" }, */ - {"RAND", "random"}, -/* { "ROUND", "round" }, */ -/* { "SIGN", "sign" }, */ -/* { "SIN", "sin" }, */ -/* { "SQRT", "sqrt" }, */ -/* { "TAN", "tan" }, */ - {"TRUNCATE", "trunc"}, - - {"CURRENT_DATE", "curdate"}, - {"CURRENT_TIME", "curtime"}, - {"CURRENT_TIMESTAMP", "odbc_timestamp"}, - {"CURRENT_USER", "odbc_current_user"}, - {"SESSION_USER", "odbc_session_user"}, -/* { "CURDATE", "curdate" }, */ -/* { "CURTIME", "curtime" }, */ -/* { "DAYNAME", "dayname" }, */ -/* { "DAYOFMONTH", "dayofmonth" }, */ -/* { "DAYOFWEEK", "dayofweek" }, */ -/* { "DAYOFYEAR", "dayofyear" }, */ -/* { "HOUR", "hour" }, */ -/* { "MINUTE", "minute" }, */ -/* { "MONTH", "month" }, */ -/* { "MONTHNAME", "monthname" }, */ -/* { "NOW", "now" }, */ -/* { "QUARTER", "quarter" }, */ -/* { "SECOND", "second" }, */ -/* { "WEEK", "week" }, */ -/* { "YEAR", "year" }, */ - -/* { "DATABASE", "database" }, */ - {"IFNULL", "coalesce"}, - {"USER", "odbc_user"}, - {0, 0} -}; - -static char *mapFunction(const char *func); -static unsigned int conv_from_octal(const unsigned char *s); -static unsigned int conv_from_hex(const unsigned char *s); -static char *conv_to_octal(unsigned char val); - -/*--------- - * A Guide for date/time/timestamp conversions - * - * 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 - *--------- - */ - - - -/* - * TIMESTAMP <-----> SIMPLE_TIME - * precision support since 7.2. - * time zone support is unavailable(the stuff is unreliable) - */ -static BOOL -timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone) -{ - char rest[64], - *ptr; - int scnt, - i; - long timediff; - BOOL withZone = *bZone; - - *bZone = FALSE; - *zone = 0; - st->fr = 0; - if ((scnt = sscanf(str, "%4d-%2d-%2d %2d:%2d:%2d%s", &st->y, &st->m, &st->d, &st->hh, &st->mm, &st->ss, rest)) < 6) - return FALSE; - else if (scnt == 6) - return TRUE; - switch (rest[0]) - { - case '+': - *bZone = TRUE; - *zone = atoi(&rest[1]); - break; - case '-': - *bZone = TRUE; - *zone = -atoi(&rest[1]); - break; - case '.': - if ((ptr = strchr(rest, '+')) != NULL) - { - *bZone = TRUE; - *zone = atoi(&ptr[1]); - *ptr = '\0'; - } - else if ((ptr = strchr(rest, '-')) != NULL) - { - *bZone = TRUE; - *zone = -atoi(&ptr[1]); - *ptr = '\0'; - } - for (i = 1; i < 10; i++) - { - if (!isdigit((unsigned char) rest[i])) - break; - } - for (; i < 10; i++) - rest[i] = '0'; - rest[i] = '\0'; - st->fr = atoi(&rest[1]); - break; - default: - return TRUE; - } - if (!withZone || !*bZone || st->y < 1970) - return TRUE; -#if defined(WIN32) || defined(HAVE_INT_TIMEZONE) - if (!tzname[0] || !tzname[0][0]) - { - *bZone = FALSE; - return TRUE; - } - timediff = TIMEZONE_GLOBAL + (*zone) * 3600; - if (!daylight && timediff == 0) /* the same timezone */ - return TRUE; - else - { - struct tm tm, - *tm2; - time_t time0; - - *bZone = FALSE; - tm.tm_year = st->y - 1900; - tm.tm_mon = st->m - 1; - tm.tm_mday = st->d; - tm.tm_hour = st->hh; - tm.tm_min = st->mm; - tm.tm_sec = st->ss; - tm.tm_isdst = -1; - time0 = mktime(&tm); - if (time0 < 0) - return TRUE; - if (tm.tm_isdst > 0) - timediff -= 3600; - if (timediff == 0) /* the same time zone */ - return TRUE; - time0 -= timediff; - if (time0 >= 0 && (tm2 = localtime(&time0)) != NULL) - { - st->y = tm2->tm_year + 1900; - st->m = tm2->tm_mon + 1; - st->d = tm2->tm_mday; - st->hh = tm2->tm_hour; - st->mm = tm2->tm_min; - st->ss = tm2->tm_sec; - *bZone = TRUE; - } - } -#endif /* WIN32 */ - return TRUE; -} - -static BOOL -stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision) -{ - char precstr[16], - zonestr[16]; - int i; - - precstr[0] = '\0'; - if (precision && st->fr) - { - sprintf(precstr, ".%09d", st->fr); - for (i = 9; i > 0; i--) - { - if (precstr[i] != '0') - break; - precstr[i] = '\0'; - } - } - zonestr[0] = '\0'; -#if defined(WIN32) || defined(HAVE_INT_TIMEZONE) - if (bZone && tzname[0] && tzname[0][0] && st->y >= 1970) - { - long zoneint; - struct tm tm; - time_t time0; - - zoneint = TIMEZONE_GLOBAL; - if (daylight && st->y >= 1900) - { - tm.tm_year = st->y - 1900; - tm.tm_mon = st->m - 1; - tm.tm_mday = st->d; - tm.tm_hour = st->hh; - tm.tm_min = st->mm; - tm.tm_sec = st->ss; - tm.tm_isdst = -1; - time0 = mktime(&tm); - if (time0 >= 0 && tm.tm_isdst > 0) - zoneint -= 3600; - } - if (zoneint > 0) - sprintf(zonestr, "-%02d", (int) zoneint / 3600); - else - sprintf(zonestr, "+%02d", -(int) zoneint / 3600); - } -#endif /* WIN32 */ - sprintf(str, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d%s%s", st->y, st->m, st->d, st->hh, st->mm, st->ss, precstr, zonestr); - return TRUE; -} - -/* This is called by SQLFetch() */ -int -copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col) -{ - BindInfoClass *bic = &(stmt->bindings[col]); - - return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) bic->buffer, - (SDWORD) bic->buflen, (SDWORD *) bic->used); -} - - -/* This is called by SQLGetData() */ -int -copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType, - PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue) -{ - Int4 len = 0, - copy_len = 0; - SIMPLE_TIME st; - time_t t = time(NULL); - struct tm *tim; - int pcbValueOffset, - rgbValueOffset; - char *rgbValueBindRow; - const char *ptr; - int bind_row = stmt->bind_row; - int bind_size = stmt->options.bind_size; - int result = COPY_OK; - BOOL changed; - const char *neut_str = value; - char midtemp[2][32]; - int mtemp_cnt = 0; - static BindInfoClass sbic; - BindInfoClass *pbic; - - if (stmt->current_col >= 0) - { - pbic = &stmt->bindings[stmt->current_col]; - if (pbic->data_left == -2) - pbic->data_left = (cbValueMax > 0) ? 0 : -1; /* This seems to be * - * needed for ADO ? */ - if (pbic->data_left == 0) - { - if (pbic->ttlbuf != NULL) - { - free(pbic->ttlbuf); - pbic->ttlbuf = NULL; - pbic->ttlbuflen = 0; - } - pbic->data_left = -2; /* needed by ADO ? */ - return COPY_NO_DATA_FOUND; - } - } - /*--------- - * 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; - - } - - memset(&st, 0, sizeof(SIMPLE_TIME)); - - /* Initialize current date */ - tim = localtime(&t); - st.m = tim->tm_mon + 1; - st.d = tim->tm_mday; - st.y = tim->tm_year + 1900; - - mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "" : value, cbValueMax); - - 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); - - stmt->hdbc->DataSourceToDriver(stmt->hdbc->translation_option, - SQL_CHAR, - value, length, - value, length, NULL, - 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; - - case PG_TYPE_TIME: - sscanf(value, "%2d:%2d:%2d", &st.hh, &st.mm, &st.ss); - break; - - case PG_TYPE_ABSTIME: - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP: - st.fr = 0; - if (strnicmp(value, "invalid", 7) != 0) - { - BOOL bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(SC_get_conn(stmt), 7.2)); - int zone; - - /* - * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, - * &st.d, &st.hh, &st.mm, &st.ss); - */ - bZone = FALSE; /* time zone stuff is unreliable */ - timestamp2stime(value, &st, &bZone, &zone); - } - else - { - /* - * The timestamp is invalid so set something conspicuous, - * like the epoch - */ - t = 0; - tim = localtime(&t); - st.m = tim->tm_mon + 1; - st.d = tim->tm_mday; - st.y = tim->tm_year + 1900; - st.hh = tim->tm_hour; - st.mm = tim->tm_min; - st.ss = tim->tm_sec; - } - break; - - case PG_TYPE_BOOL: - { /* change T/F to 1/0 */ - char *s; - - s = midtemp[mtemp_cnt]; - strcpy(s, (char *) value); - if (s[0] == 'f' || s[0] == 'F' || s[0] == 'n' || s[0] == 'N' || s[0] == '0') - s[0] = '0'; - else - s[0] = '1'; - s[1] = '\0'; - neut_str = midtemp[mtemp_cnt]; - mtemp_cnt++; - - } - break; - - /* This is for internal use by SQLStatistics() */ - case PG_TYPE_INT2VECTOR: - { - int nval, - i; - const char *vp; - - /* this is an array of eight integers */ - short *short_array = (short *) ((char *) rgbValue + rgbValueOffset); - - len = 32; - vp = value; - nval = 0; - mylog("index=("); - for (i = 0; i < 16; i++) - { - if (sscanf(vp, "%hd", &short_array[i]) != 1) - break; - - mylog(" %d", short_array[i]); - nval++; - - /* skip the current token */ - while ((*vp != '\0') && (!isspace((unsigned char) *vp))) - vp++; - /* and skip the space to the next token */ - while ((*vp != '\0') && (isspace((unsigned char) *vp))) - vp++; - if (*vp == '\0') - break; - } - mylog(") nval = %d\n", nval); - - for (i = nval; i < 16; i++) - short_array[i] = 0; - -#if 0 - sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd", - &short_array[0], - &short_array[1], - &short_array[2], - &short_array[3], - &short_array[4], - &short_array[5], - &short_array[6], - &short_array[7]); -#endif - - /* There is no corresponding fCType for this. */ - if (pcbValue) - *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len; - - return COPY_OK; /* dont go any further or the data will be - * trashed */ - } - - /* - * This is a large object OID, which is used to store - * LONGVARBINARY objects. - */ - case PG_TYPE_LO: - - return convert_lo(stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset)); - - default: - - if (field_type == stmt->hdbc->lobj_type) /* hack until permanent - * type available */ - return convert_lo(stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset)); - } - - /* Change default into something useable */ - if (fCType == SQL_C_DEFAULT) - { - fCType = pgtype_to_ctype(stmt, field_type); - - 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. - */ - switch (field_type) - { - case PG_TYPE_DATE: - len = 10; - if (cbValueMax > len) - sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", st.y, st.m, st.d); - break; - - case PG_TYPE_TIME: - len = 8; - if (cbValueMax > len) - sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", st.hh, st.mm, st.ss); - break; - - case PG_TYPE_ABSTIME: - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP: - len = 19; - if (cbValueMax > len) - sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d", - st.y, st.m, st.d, st.hh, st.mm, st.ss); - break; - - case PG_TYPE_BOOL: - len = 1; - if (cbValueMax > len) - { - strcpy(rgbValueBindRow, neut_str); - mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow); - } - break; - - /* - * Currently, data is SILENTLY TRUNCATED for BYTEA and - * character data types if there is not enough room in - * cbValueMax because the driver can't handle multiple - * calls to SQLGetData for these, yet. Most likely, the - * buffer passed in will be big enough to handle the - * maximum limit of postgres, anyway. - * - * LongVarBinary types are handled correctly above, observing - * truncation and all that stuff since there is - * essentially no limit on the large object used to store - * those. - */ - case PG_TYPE_BYTEA:/* convert binary data to hex strings - * (i.e, 255 = "FF") */ - len = convert_pgbinary_to_char(neut_str, rgbValueBindRow, cbValueMax); - - /***** THIS IS NOT PROPERLY IMPLEMENTED *****/ - break; - - default: - if (stmt->current_col < 0) - { - pbic = &sbic; - pbic->data_left = -1; - } - else - pbic = &stmt->bindings[stmt->current_col]; - if (pbic->data_left < 0) - { - /* convert linefeeds to carriage-return/linefeed */ - len = convert_linefeeds(neut_str, NULL, 0, &changed); - if (cbValueMax == 0) /* just returns length - * info */ - { - result = COPY_RESULT_TRUNCATED; - break; - } - if (!pbic->ttlbuf) - pbic->ttlbuflen = 0; - if (changed || len >= cbValueMax) - { - if (len >= (int) pbic->ttlbuflen) - { - pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1); - pbic->ttlbuflen = len + 1; - } - convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, &changed); - ptr = pbic->ttlbuf; - } - else - { - if (pbic->ttlbuf) - { - free(pbic->ttlbuf); - pbic->ttlbuf = NULL; - } - ptr = neut_str; - } - } - else - ptr = pbic->ttlbuf; - - mylog("DEFAULT: len = %d, ptr = '%s'\n", len, ptr); - - if (stmt->current_col >= 0) - { - if (pbic->data_left > 0) - { - ptr += strlen(ptr) - pbic->data_left; - len = pbic->data_left; - } - else - pbic->data_left = len; - } - - if (cbValueMax > 0) - { - copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len; - - /* Copy the data */ - memcpy(rgbValueBindRow, ptr, copy_len); - rgbValueBindRow[copy_len] = '\0'; - - /* Adjust data_left for next time */ - if (stmt->current_col >= 0) - pbic->data_left -= copy_len; - } - - /* - * Finally, check for truncation so that proper status can - * be returned - */ - if (cbValueMax > 0 && len >= cbValueMax) - result = COPY_RESULT_TRUNCATED; - else - { - if (pbic->ttlbuf != NULL) - { - free(pbic->ttlbuf); - pbic->ttlbuf = NULL; - } - } - - - mylog(" SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow); - break; - } - - - } - 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 - * those. - */ - if (field_type == PG_TYPE_MONEY) - { - if (convert_money(neut_str, midtemp[mtemp_cnt], sizeof(midtemp[0]))) - { - neut_str = midtemp[mtemp_cnt]; - mtemp_cnt++; - } - else - return COPY_UNSUPPORTED_TYPE; - } - - switch (fCType) - { - case SQL_C_DATE: -#if (ODBCVER >= 0x0300) - case SQL_C_TYPE_DATE: /* 91 */ -#endif - len = 6; - { - DATE_STRUCT *ds; - - if (bind_size > 0) - ds = (DATE_STRUCT *) ((char *) rgbValue + (bind_row * bind_size)); - else - ds = (DATE_STRUCT *) rgbValue + bind_row; - ds->year = st.y; - ds->month = st.m; - ds->day = st.d; - } - break; - - case SQL_C_TIME: -#if (ODBCVER >= 0x0300) - case SQL_C_TYPE_TIME: /* 92 */ -#endif - len = 6; - { - TIME_STRUCT *ts; - - if (bind_size > 0) - ts = (TIME_STRUCT *) ((char *) rgbValue + (bind_row * bind_size)); - else - ts = (TIME_STRUCT *) rgbValue + bind_row; - ts->hour = st.hh; - ts->minute = st.mm; - ts->second = st.ss; - } - break; - - case SQL_C_TIMESTAMP: -#if (ODBCVER >= 0x0300) - case SQL_C_TYPE_TIMESTAMP: /* 93 */ -#endif - len = 16; - { - TIMESTAMP_STRUCT *ts; - - if (bind_size > 0) - ts = (TIMESTAMP_STRUCT *) ((char *) rgbValue + (bind_row * bind_size)); - else - ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row; - ts->year = st.y; - ts->month = st.m; - ts->day = st.d; - ts->hour = st.hh; - ts->minute = st.mm; - ts->second = st.ss; - ts->fraction = st.fr; - } - break; - - case SQL_C_BIT: - len = 1; - if (bind_size > 0) - *(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neut_str); - else - *((UCHAR *) rgbValue + bind_row) = atoi(neut_str); - - /* - * mylog("SQL_C_BIT: bind_row = %d val = %d, cb = %d, - * rgb=%d\n", bind_row, atoi(neut_str), cbValueMax, - * *((UCHAR *)rgbValue)); - */ - break; - - case SQL_C_STINYINT: - case SQL_C_TINYINT: - len = 1; - if (bind_size > 0) - *(SCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neut_str); - else - *((SCHAR *) rgbValue + bind_row) = atoi(neut_str); - break; - - case SQL_C_UTINYINT: - len = 1; - if (bind_size > 0) - *(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neut_str); - else - *((UCHAR *) rgbValue + bind_row) = atoi(neut_str); - break; - - case SQL_C_FLOAT: - len = 4; - if (bind_size > 0) - *(SFLOAT *) ((char *) rgbValue + (bind_row * bind_size)) = (float) atof(neut_str); - else - *((SFLOAT *) rgbValue + bind_row) = (float) atof(neut_str); - break; - - case SQL_C_DOUBLE: - len = 8; - if (bind_size > 0) - *(SDOUBLE *) ((char *) rgbValue + (bind_row * bind_size)) = atof(neut_str); - else - *((SDOUBLE *) rgbValue + bind_row) = atof(neut_str); - break; - - case SQL_C_SSHORT: - case SQL_C_SHORT: - len = 2; - if (bind_size > 0) - *(SWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neut_str); - else - *((SWORD *) rgbValue + bind_row) = atoi(neut_str); - break; - - case SQL_C_USHORT: - len = 2; - if (bind_size > 0) - *(UWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neut_str); - else - *((UWORD *) rgbValue + bind_row) = atoi(neut_str); - break; - - case SQL_C_SLONG: - case SQL_C_LONG: - len = 4; - if (bind_size > 0) - *(SDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(neut_str); - else - *((SDWORD *) rgbValue + bind_row) = atol(neut_str); - break; - - case SQL_C_ULONG: - len = 4; - if (bind_size > 0) - *(UDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(neut_str); - else - *((UDWORD *) rgbValue + bind_row) = atol(neut_str); - break; - - case SQL_C_BINARY: - - /* truncate if necessary */ - /* convert octal escapes to bytes */ - - if (stmt->current_col < 0) - { - pbic = &sbic; - pbic->data_left = -1; - } - else - pbic = &stmt->bindings[stmt->current_col]; - if (!pbic->ttlbuf) - pbic->ttlbuflen = 0; - if (len = strlen(neut_str), len >= (int) pbic->ttlbuflen) - { - pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1); - pbic->ttlbuflen = len + 1; - } - len = convert_from_pgbinary(neut_str, pbic->ttlbuf, pbic->ttlbuflen); - ptr = pbic->ttlbuf; - - if (stmt->current_col >= 0) - { - /* - * Second (or more) call to SQLGetData so move the - * pointer - */ - if (pbic->data_left > 0) - { - ptr += len - pbic->data_left; - len = pbic->data_left; - } - - /* First call to SQLGetData so initialize data_left */ - else - pbic->data_left = len; - - } - - if (cbValueMax > 0) - { - copy_len = (len > cbValueMax) ? cbValueMax : len; - - /* Copy the data */ - memcpy(rgbValueBindRow, ptr, copy_len); - - /* Adjust data_left for next time */ - if (stmt->current_col >= 0) - pbic->data_left -= copy_len; - } - - /* - * Finally, check for truncation so that proper status can - * be returned - */ - if (len > cbValueMax) - result = COPY_RESULT_TRUNCATED; - - if (pbic->ttlbuf) - { - free(pbic->ttlbuf); - pbic->ttlbuf = NULL; - } - mylog("SQL_C_BINARY: len = %d, copy_len = %d\n", len, copy_len); - break; - - default: - return COPY_UNSUPPORTED_TYPE; - } - } - - /* store the length of what was copied, if there's a place for it */ - if (pcbValue) - *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len; - - if (result == COPY_OK && stmt->current_col >= 0) - stmt->bindings[stmt->current_col].data_left = 0; - return result; - -} - - -/*-------------------------------------------------------------------- - * Functions/Macros to get rid of query size limit. - * - * I always used the follwoing macros to convert from - * old_statement to new_statement. Please improve it - * if you have a better way. Hiroshi 2001/05/22 - *-------------------------------------------------------------------- - */ -#define INIT_MIN_ALLOC 4096 -static int -enlarge_statement(StatementClass *stmt, unsigned int newsize) -{ - unsigned int newalsize = INIT_MIN_ALLOC; - static char *func = "enlarge_statement"; - - if (stmt->stmt_size_limit > 0 && stmt->stmt_size_limit < (int) newsize) - { - stmt->errormsg = "Query buffer overflow in copy_statement_with_parameters"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return -1; - } - while (newalsize <= newsize) - newalsize *= 2; - if (!(stmt->stmt_with_params = realloc(stmt->stmt_with_params, newalsize))) - { - stmt->errormsg = "Query buffer allocate error in copy_statement_with_parameters"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return 0; - } - return newalsize; -} - -/*---------- - * Enlarge stmt_with_params if necessary. - *---------- - */ -#define ENLARGE_NEWSTATEMENT(newpos) \ - if (newpos >= new_stsize) \ - { \ - if ((new_stsize = enlarge_statement(stmt, newpos)) <= 0) \ - return SQL_ERROR; \ - new_statement = stmt->stmt_with_params; \ - } -/*---------- - * Initialize stmt_with_params, new_statement etc. - *---------- - */ -#define CVT_INIT(size) \ -do { \ - if (stmt->stmt_with_params) \ - free(stmt->stmt_with_params); \ - if (stmt->stmt_size_limit > 0) \ - new_stsize = stmt->stmt_size_limit; \ - else \ - { \ - new_stsize = INIT_MIN_ALLOC; \ - while (new_stsize <= size) \ - new_stsize *= 2; \ - } \ - new_statement = malloc(new_stsize); \ - stmt->stmt_with_params = new_statement; \ - npos = 0; \ - new_statement[0] = '\0'; \ -} while (0) - -/*---------- - * Terminate the stmt_with_params string with NULL. - *---------- - */ -#define CVT_TERMINATE \ -do { \ - new_statement[npos] = '\0'; \ -} while (0) - -/*---------- - * Append a data. - *---------- - */ -#define CVT_APPEND_DATA(s, len) \ -do { \ - unsigned int newpos = npos + len; \ - ENLARGE_NEWSTATEMENT(newpos) \ - memcpy(&new_statement[npos], s, len); \ - npos = newpos; \ - new_statement[npos] = '\0'; \ -} while (0) - -/*---------- - * Append a string. - *---------- - */ -#define CVT_APPEND_STR(s) \ -do { \ - unsigned int len = strlen(s); \ - CVT_APPEND_DATA(s, len); \ -} while (0) - -/*---------- - * Append a char. - *---------- - */ -#define CVT_APPEND_CHAR(c) \ -do { \ - ENLARGE_NEWSTATEMENT(npos + 1); \ - new_statement[npos++] = c; \ -} while (0) - -/*---------- - * Append a binary data. - * Newly reqeuired size may be overestimated currently. - *---------- - */ -#define CVT_APPEND_BINARY(buf, used) \ -do { \ - unsigned int newlimit = npos + 5 * used; \ - ENLARGE_NEWSTATEMENT(newlimit); \ - npos += convert_to_pgbinary(buf, &new_statement[npos], used); \ -} while (0) - -/*---------- - * - *---------- - */ -#define CVT_SPECIAL_CHARS(buf, used) \ -do { \ - int cnvlen = convert_special_chars(buf, NULL, used); \ - unsigned int newlimit = npos + cnvlen; \ -\ - ENLARGE_NEWSTATEMENT(newlimit); \ - convert_special_chars(buf, &new_statement[npos], used); \ - npos += cnvlen; \ -} while (0) - -/*---------- - * Check if the statement is - * SELECT ... INTO table FROM ..... - * This isn't really a strict check but ... - *---------- - */ -static BOOL -into_table_from(const char *stmt) -{ - if (strnicmp(stmt, "into", 4)) - return FALSE; - stmt += 4; - if (!isspace((unsigned char) *stmt)) - return FALSE; - while (isspace((unsigned char) *(++stmt))); - switch (*stmt) - { - case '\0': - case ',': - case '\'': - return FALSE; - case '\"': /* double quoted table name ? */ - do - { - do - while (*(++stmt) != '\"' && *stmt); - while (*stmt && *(++stmt) == '\"'); - while (*stmt && !isspace((unsigned char) *stmt) && *stmt != '\"') - stmt++; - } - while (*stmt == '\"'); - break; - default: - while (!isspace((unsigned char) *(++stmt))); - break; - } - if (!*stmt) - return FALSE; - while (isspace((unsigned char) *(++stmt))); - if (strnicmp(stmt, "from", 4)) - return FALSE; - return isspace((unsigned char) stmt[4]); -} - -/*---------- - * Check if the statement is - * SELECT ... FOR UPDATE ..... - * This isn't really a strict check but ... - *---------- - */ -static BOOL -table_for_update(const char *stmt, int *endpos) -{ - const char *wstmt = stmt; - - while (isspace((unsigned char) *(++wstmt))); - if (!*wstmt) - return FALSE; - if (strnicmp(wstmt, "update", 6)) - return FALSE; - wstmt += 6; - *endpos = wstmt - stmt; - return !wstmt[0] || isspace((unsigned char) wstmt[0]); -} - -/* - * This function inserts parameters into an SQL statements. - * It will also modify a SELECT statement for use with declare/fetch cursors. - * This function does a dynamic memory allocation to get rid of query size limit! - */ -int -copy_statement_with_parameters(StatementClass *stmt) -{ - static char *func = "copy_statement_with_parameters"; - unsigned int opos, - npos, - oldstmtlen; - char param_string[128], - tmp[256], - cbuf[PG_NUMERIC_MAX_PRECISION * 2]; /* seems big enough to - * handle the data in - * this function */ - int param_number; - Int2 param_ctype, - param_sqltype; - char *old_statement = stmt->statement, - oldchar; - char *new_statement = stmt->stmt_with_params; - unsigned int new_stsize = 0; - SIMPLE_TIME st; - time_t t = time(NULL); - struct tm *tim; - SDWORD used; - char *buffer, - *buf; - BOOL in_quote = FALSE, - in_dquote = FALSE, - in_escape = FALSE; - Oid lobj_oid; - int lobj_fd, - retval; - BOOL check_cursor_ok = FALSE; /* check cursor - * restriction */ - BOOL proc_no_param = TRUE; - unsigned int declare_pos = 0; - ConnectionClass *conn = SC_get_conn(stmt); - ConnInfo *ci = &(conn->connInfo); - BOOL prepare_dummy_cursor = FALSE, - begin_first = FALSE; - char token_save[64]; - int token_len; - BOOL prev_token_end; - -#ifdef DRIVER_CURSOR_IMPLEMENT - BOOL search_from_pos = FALSE; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - if (ci->disallow_premature) - prepare_dummy_cursor = stmt->pre_executing; - - if (!old_statement) - { - SC_log_error(func, "No statement string", stmt); - return SQL_ERROR; - } - - memset(&st, 0, sizeof(SIMPLE_TIME)); - - /* Initialize current date */ - tim = localtime(&t); - st.m = tim->tm_mon + 1; - st.d = tim->tm_mday; - st.y = tim->tm_year + 1900; - -#ifdef DRIVER_CURSOR_IMPLEMENT - if (stmt->statement_type != STMT_TYPE_SELECT) - { - stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY; - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - } - else if (stmt->options.cursor_type == SQL_CURSOR_FORWARD_ONLY) - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - else if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY) - { - if (stmt->parse_status == STMT_PARSE_NONE) - parse_statement(stmt); - if (stmt->parse_status != STMT_PARSE_COMPLETE) - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - else if (!stmt->ti || stmt->ntab != 1) - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - else - search_from_pos = TRUE; - } -#endif /* DRIVER_CURSOR_IMPLEMENT */ - - /* If the application hasn't set a cursor name, then generate one */ - if (stmt->cursor_name[0] == '\0') - sprintf(stmt->cursor_name, "SQL_CUR%p", stmt); - oldstmtlen = strlen(old_statement); - CVT_INIT(oldstmtlen); - - stmt->miscinfo = 0; - token_len = 0; - prev_token_end = TRUE; - /* For selects, prepend a declare cursor to the statement */ - if (stmt->statement_type == STMT_TYPE_SELECT) - { - SC_set_pre_executable(stmt); - if (prepare_dummy_cursor || ci->drivers.use_declarefetch) - { - if (prepare_dummy_cursor) - { - if (!CC_is_in_trans(conn) && PG_VERSION_GE(conn, 7.1)) - { - strcpy(new_statement, "BEGIN;"); - begin_first = TRUE; - } - } - else if (ci->drivers.use_declarefetch) - SC_set_fetchcursor(stmt); - sprintf(new_statement, "%sdeclare %s cursor for ", - new_statement, stmt->cursor_name); - npos = strlen(new_statement); - check_cursor_ok = TRUE; - declare_pos = npos; - } - } - param_number = -1; -#ifdef MULTIBYTE - multibyte_init(); -#endif - - for (opos = 0; opos < oldstmtlen; opos++) - { - oldchar = old_statement[opos]; -#ifdef MULTIBYTE - if (multibyte_char_check(oldchar) != 0) - { - CVT_APPEND_CHAR(oldchar); - continue; - } - - /* - * From here we are guaranteed to handle a 1-byte character. - */ -#endif - - if (in_escape) /* escape check */ - { - in_escape = FALSE; - CVT_APPEND_CHAR(oldchar); - continue; - } - else if (in_quote || in_dquote) /* quote/double quote check */ - { - if (oldchar == '\\') - in_escape = TRUE; - else if (oldchar == '\'' && in_quote) - in_quote = FALSE; - else if (oldchar == '\"' && in_dquote) - in_dquote = FALSE; - CVT_APPEND_CHAR(oldchar); - continue; - } - - /* - * From here we are guranteed to be in neither an escape, a quote - * nor a double quote. - */ - /* Squeeze carriage-return/linefeed pairs to linefeed only */ - else if (oldchar == '\r' && opos + 1 < oldstmtlen && - old_statement[opos + 1] == '\n') - continue; - - /* - * Handle literals (date, time, timestamp) and ODBC scalar - * functions - */ - else if (oldchar == '{') - { - char *esc; - char *begin = &old_statement[opos + 1]; - -#ifdef MULTIBYTE - char *end = multibyte_strchr(begin, '}'); - -#else - char *end = strchr(begin, '}'); -#endif - - if (!end) - continue; - /* procedure calls */ - if (stmt->statement_type == STMT_TYPE_PROCCALL) - { - int lit_call_len = 4; - - while (isspace((unsigned char) old_statement[++opos])); - /* '=?' to accept return values exists ? */ - if (old_statement[opos] == '?') - { - param_number++; - while (isspace((unsigned char) old_statement[++opos])); - if (old_statement[opos] != '=') - { - opos--; - continue; - } - while (isspace((unsigned char) old_statement[++opos])); - } - if (strnicmp(&old_statement[opos], "call", lit_call_len) || - !isspace((unsigned char) old_statement[opos + lit_call_len])) - { - opos--; - continue; - } - opos += lit_call_len; - CVT_APPEND_STR("SELECT "); -#ifdef MULTIBYTE - if (multibyte_strchr(&old_statement[opos], '(')) -#else - if (strchr(&old_statement[opos], '(')) -#endif /* MULTIBYTE */ - proc_no_param = FALSE; - continue; - } - *end = '\0'; - - esc = convert_escape(begin); - if (esc) - CVT_APPEND_STR(esc); - else - { /* it's not a valid literal so just copy */ - *end = '}'; - CVT_APPEND_CHAR(oldchar); - continue; - } - - opos += end - begin + 1; - *end = '}'; - continue; - } - /* End of a procedure call */ - else if (oldchar == '}' && stmt->statement_type == STMT_TYPE_PROCCALL) - { - if (proc_no_param) - CVT_APPEND_STR("()"); - continue; - } - - /* - * Can you have parameter markers inside of quotes? I dont think - * so. All the queries I've seen expect the driver to put quotes - * if needed. - */ - else if (oldchar == '?') - ; /* ok */ - else - { - if (oldchar == '\'') - in_quote = TRUE; - else if (oldchar == '\\') - in_escape = TRUE; - else if (oldchar == '\"') - in_dquote = TRUE; - else - { - if (isspace((unsigned char) oldchar)) - { - if (!prev_token_end) - { - prev_token_end = TRUE; - token_save[token_len] = '\0'; - if (token_len == 4) - { - if (check_cursor_ok && - into_table_from(&old_statement[opos - token_len])) - { - stmt->statement_type = STMT_TYPE_CREATE; - SC_no_pre_executable(stmt); - SC_no_fetchcursor(stmt); - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - memmove(new_statement, new_statement + declare_pos, npos - declare_pos); - npos -= declare_pos; - } -#ifdef DRIVER_CURSOR_IMPLEMENT - else if (search_from_pos && /* where's from clause */ - strnicmp(token_save, "from", 4) == 0) - { - search_from_pos = FALSE; - npos -= 5; - CVT_APPEND_STR(", CTID, OID from"); - } -#endif /* DRIVER_CURSOR_IMPLEMENT */ - } - if (token_len == 3) - { - int endpos; - - if (check_cursor_ok && - strnicmp(token_save, "for", 3) == 0 && - table_for_update(&old_statement[opos], &endpos)) - { - SC_no_fetchcursor(stmt); - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - if (prepare_dummy_cursor) - { - npos -= 4; - opos += endpos; - } - else - { - memmove(new_statement, new_statement + declare_pos, npos - declare_pos); - npos -= declare_pos; - } - } - } - } - } - else if (prev_token_end) - { - prev_token_end = FALSE; - token_save[0] = oldchar; - token_len = 1; - } - else if (token_len + 1 < sizeof(token_save)) - token_save[token_len++] = oldchar; - } - CVT_APPEND_CHAR(oldchar); - continue; - } - - /* - * Its a '?' parameter alright - */ - param_number++; - - if (param_number >= stmt->parameters_allocated) - { - if (stmt->pre_executing) - { - CVT_APPEND_STR("NULL"); - stmt->inaccurate_result = TRUE; - continue; - } - else - { - CVT_APPEND_CHAR('?'); - continue; - } - } - - /* Assign correct buffers based on data at exec param or not */ - if (stmt->parameters[param_number].data_at_exec) - { - used = stmt->parameters[param_number].EXEC_used ? *stmt->parameters[param_number].EXEC_used : SQL_NTS; - buffer = stmt->parameters[param_number].EXEC_buffer; - } - else - { - - - used = stmt->parameters[param_number].used ? *stmt->parameters[param_number].used : SQL_NTS; - - buffer = stmt->parameters[param_number].buffer; - } - - /* Handle NULL parameter data */ - if (used == SQL_NULL_DATA) - { - CVT_APPEND_STR("NULL"); - continue; - } - - /* - * If no buffer, and it's not null, then what the hell is it? Just - * leave it alone then. - */ - if (!buffer) - { - if (stmt->pre_executing) - { - CVT_APPEND_STR("NULL"); - stmt->inaccurate_result = TRUE; - continue; - } - else - { - CVT_APPEND_CHAR('?'); - continue; - } - } - - param_ctype = stmt->parameters[param_number].CType; - param_sqltype = stmt->parameters[param_number].SQLType; - - mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n", param_ctype, param_sqltype); - - /* replace DEFAULT with something we can use */ - if (param_ctype == SQL_C_DEFAULT) - param_ctype = sqltype_to_default_ctype(param_sqltype); - - buf = NULL; - param_string[0] = '\0'; - cbuf[0] = '\0'; - - /* Convert input C type to a neutral format */ - switch (param_ctype) - { - case SQL_C_BINARY: - case SQL_C_CHAR: - buf = buffer; - break; - - case SQL_C_DOUBLE: - sprintf(param_string, "%.15g", - *((SDOUBLE *) buffer)); - break; - - case SQL_C_FLOAT: - sprintf(param_string, "%.6g", - *((SFLOAT *) buffer)); - break; - - case SQL_C_SLONG: - case SQL_C_LONG: - sprintf(param_string, "%ld", - *((SDWORD *) buffer)); - break; - - case SQL_C_SSHORT: - case SQL_C_SHORT: - sprintf(param_string, "%d", - *((SWORD *) buffer)); - break; - - case SQL_C_STINYINT: - case SQL_C_TINYINT: - sprintf(param_string, "%d", - *((SCHAR *) buffer)); - break; - - case SQL_C_ULONG: - sprintf(param_string, "%lu", - *((UDWORD *) buffer)); - break; - - case SQL_C_USHORT: - sprintf(param_string, "%u", - *((UWORD *) buffer)); - break; - - case SQL_C_UTINYINT: - sprintf(param_string, "%u", - *((UCHAR *) buffer)); - break; - - case SQL_C_BIT: - { - int i = *((UCHAR *) buffer); - - sprintf(param_string, "%d", i ? 1 : 0); - break; - } - - case SQL_C_DATE: -#if (ODBCVER >= 0x0300) - case SQL_C_TYPE_DATE: /* 91 */ -#endif - { - DATE_STRUCT *ds = (DATE_STRUCT *) buffer; - - st.m = ds->month; - st.d = ds->day; - st.y = ds->year; - - break; - } - - case SQL_C_TIME: -#if (ODBCVER >= 0x0300) - case SQL_C_TYPE_TIME: /* 92 */ -#endif - { - TIME_STRUCT *ts = (TIME_STRUCT *) buffer; - - st.hh = ts->hour; - st.mm = ts->minute; - st.ss = ts->second; - - break; - } - - case SQL_C_TIMESTAMP: -#if (ODBCVER >= 0x0300) - case SQL_C_TYPE_TIMESTAMP: /* 93 */ -#endif - { - TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer; - - st.m = tss->month; - st.d = tss->day; - st.y = tss->year; - st.hh = tss->hour; - st.mm = tss->minute; - st.ss = tss->second; - st.fr = tss->fraction; - - mylog("m=%d,d=%d,y=%d,hh=%d,mm=%d,ss=%d\n", st.m, st.d, st.y, st.hh, st.mm, st.ss); - - break; - - } - default: - /* error */ - stmt->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters"; - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - CVT_TERMINATE; /* just in case */ - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* - * Now that the input data is in a neutral format, convert it to - * the desired output format (sqltype) - */ - - switch (param_sqltype) - { - case SQL_CHAR: - case SQL_VARCHAR: - case SQL_LONGVARCHAR: - - CVT_APPEND_CHAR('\''); /* Open Quote */ - - /* it was a SQL_C_CHAR */ - if (buf) - CVT_SPECIAL_CHARS(buf, used); - - /* it was a numeric type */ - else if (param_string[0] != '\0') - CVT_APPEND_STR(param_string); - - /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */ - else - { - sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d", - st.y, st.m, st.d, st.hh, st.mm, st.ss); - - CVT_APPEND_STR(tmp); - } - - CVT_APPEND_CHAR('\''); /* Close Quote */ - - break; - - case SQL_DATE: -#if (ODBCVER >= 0x0300) - case SQL_TYPE_DATE: /* 91 */ -#endif - if (buf) - { /* copy char data to time */ - my_strcpy(cbuf, sizeof(cbuf), buf, used); - parse_datetime(cbuf, &st); - } - - sprintf(tmp, "'%.4d-%.2d-%.2d'", st.y, st.m, st.d); - - CVT_APPEND_STR(tmp); - break; - - case SQL_TIME: -#if (ODBCVER >= 0x0300) - case SQL_TYPE_TIME: /* 92 */ -#endif - if (buf) - { /* copy char data to time */ - my_strcpy(cbuf, sizeof(cbuf), buf, used); - parse_datetime(cbuf, &st); - } - - sprintf(tmp, "'%.2d:%.2d:%.2d'", st.hh, st.mm, st.ss); - - CVT_APPEND_STR(tmp); - break; - - case SQL_TIMESTAMP: -#if (ODBCVER >= 0x0300) - case SQL_TYPE_TIMESTAMP: /* 93 */ -#endif - - if (buf) - { - my_strcpy(cbuf, sizeof(cbuf), buf, used); - parse_datetime(cbuf, &st); - } - - /* - * sprintf(tmp, "'%.4d-%.2d-%.2d %.2d:%.2d:%.2d'", st.y, - * st.m, st.d, st.hh, st.mm, st.ss); - */ - tmp[0] = '\''; - /* Time zone stuff is unreliable */ - stime2timestamp(&st, tmp + 1, FALSE, PG_VERSION_GE(conn, 7.2)); - strcat(tmp, "'"); - - CVT_APPEND_STR(tmp); - - break; - - case SQL_BINARY: - case SQL_VARBINARY:/* non-ascii characters should be - * converted to octal */ - CVT_APPEND_CHAR('\''); /* Open Quote */ - - mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used); - - CVT_APPEND_BINARY(buf, used); - - CVT_APPEND_CHAR('\''); /* Close Quote */ - - break; - - case SQL_LONGVARBINARY: - - 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(conn)) - { - QResultClass *res; - char ok; - - res = CC_send_query(conn, "BEGIN", NULL); - if (!res) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - CC_set_in_trans(conn); - } - - /* store the oid */ - lobj_oid = lo_creat(conn, INV_READ | INV_WRITE); - if (lobj_oid == 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt create (in-line) large object."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* store the fd */ - lobj_fd = lo_open(conn, lobj_oid, INV_WRITE); - if (lobj_fd < 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt open (in-line) large object for writing."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - retval = lo_write(conn, lobj_fd, buffer, used); - - lo_close(conn, lobj_fd); - - /* commit transaction if needed */ - if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn)) - { - QResultClass *res; - char ok; - - res = CC_send_query(conn, "COMMIT", NULL); - if (!res) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - CC_set_no_trans(conn); - } - } - - /* - * the oid of the large object -- just put that in for the - * parameter marker -- the data has already been sent to - * the large object - */ - sprintf(param_string, "'%d'", lobj_oid); - CVT_APPEND_STR(param_string); - - break; - - /* - * because of no conversion operator for bool and int4, - * SQL_BIT - */ - /* must be quoted (0 or 1 is ok to use inside the quotes) */ - - case SQL_REAL: - if (buf) - my_strcpy(param_string, sizeof(param_string), buf, used); - sprintf(tmp, "'%s'::float4", param_string); - CVT_APPEND_STR(tmp); - break; - case SQL_FLOAT: - case SQL_DOUBLE: - if (buf) - my_strcpy(param_string, sizeof(param_string), buf, used); - sprintf(tmp, "'%s'::float8", param_string); - CVT_APPEND_STR(tmp); - break; - case SQL_NUMERIC: - if (buf) - { - cbuf[0] = '\''; - my_strcpy(cbuf + 1, sizeof(cbuf) - 12, buf, used); /* 12 = 1('\'') + - * strlen("'::numeric") - * + 1('\0') */ - strcat(cbuf, "'::numeric"); - } - else - sprintf(cbuf, "'%s'::numeric", param_string); - CVT_APPEND_STR(cbuf); - break; - default: /* a numeric type or SQL_BIT */ - if (param_sqltype == SQL_BIT) - CVT_APPEND_CHAR('\''); /* Open Quote */ - - if (buf) - { - switch (used) - { - case SQL_NULL_DATA: - break; - case SQL_NTS: - CVT_APPEND_STR(buf); - break; - default: - CVT_APPEND_DATA(buf, used); - } - } - else - CVT_APPEND_STR(param_string); - - if (param_sqltype == SQL_BIT) - CVT_APPEND_CHAR('\''); /* Close Quote */ - - break; - } - } /* end, for */ - - /* make sure new_statement is always null-terminated */ - CVT_TERMINATE; - - if (conn->DriverToDataSource != NULL) - { - int length = strlen(new_statement); - - conn->DriverToDataSource(conn->translation_option, - SQL_CHAR, - new_statement, length, - new_statement, length, NULL, - NULL, 0, NULL); - } - -#ifdef DRIVER_CURSOR_IMPLEMENT - if (search_from_pos) - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - if (prepare_dummy_cursor && SC_is_pre_executable(stmt)) - { - char fetchstr[128]; - - sprintf(fetchstr, ";fetch backward in %s;close %s;", - stmt->cursor_name, stmt->cursor_name); - if (begin_first && CC_is_in_autocommit(conn)) - strcat(fetchstr, "COMMIT;"); - CVT_APPEND_STR(fetchstr); - stmt->inaccurate_result = TRUE; - } - - return SQL_SUCCESS; -} - - -static char * -mapFunction(const char *func) -{ - int i; - - for (i = 0; mapFuncs[i][0]; i++) - if (!stricmp(mapFuncs[i][0], func)) - return mapFuncs[i][1]; - - return NULL; -} - - -/* - * convert_escape() - * - * This function returns a pointer to static memory! - */ -char * -convert_escape(char *value) -{ - static char escape[1024]; - char key[33]; - - /* Separate off the key, skipping leading and trailing whitespace */ - while ((*value != '\0') && isspace((unsigned char) *value)) - value++; - sscanf(value, "%32s", key); - while ((*value != '\0') && (!isspace((unsigned char) *value))) - value++; - while ((*value != '\0') && isspace((unsigned char) *value)) - value++; - - mylog("convert_escape: key='%s', val='%s'\n", key, value); - - if ((strcmp(key, "d") == 0) || - (strcmp(key, "t") == 0) || - (strcmp(key, "oj") == 0) || /* {oj syntax support for 7.1 - * servers */ - (strcmp(key, "ts") == 0)) - { - /* Literal; return the escape part as-is */ - strncpy(escape, value, sizeof(escape) - 1); - } - else if (strcmp(key, "fn") == 0) - { - /* - * Function invocation Separate off the func name, skipping - * trailing whitespace. - */ - char *funcEnd = value; - char svchar; - char *mapFunc; - - while ((*funcEnd != '\0') && (*funcEnd != '(') && - (!isspace((unsigned char) *funcEnd))) - funcEnd++; - svchar = *funcEnd; - *funcEnd = '\0'; - sscanf(value, "%32s", key); - *funcEnd = svchar; - while ((*funcEnd != '\0') && isspace((unsigned char) *funcEnd)) - funcEnd++; - - /* - * We expect left parenthesis here, else return fn body as-is - * since it is one of those "function constants". - */ - if (*funcEnd != '(') - { - strncpy(escape, value, sizeof(escape) - 1); - return escape; - } - mapFunc = mapFunction(key); - - /* - * We could have mapFunction() return key if not in table... - - * thomas 2000-04-03 - */ - if (mapFunc == NULL) - { - /* If unrecognized function name, return fn body as-is */ - strncpy(escape, value, sizeof(escape) - 1); - return escape; - } - /* copy mapped name and remaining input string */ - strcpy(escape, mapFunc); - strncat(escape, funcEnd, sizeof(escape) - 1 - strlen(mapFunc)); - } - else - { - /* Bogus key, leave untranslated */ - return NULL; - } - - return escape; -} - - -BOOL -convert_money(const char *s, char *sout, size_t soutmax) -{ - size_t i = 0, - out = 0; - - for (i = 0; s[i]; i++) - { - if (s[i] == '$' || s[i] == ',' || s[i] == ')') - ; /* skip these characters */ - else - { - if (out + 1 >= soutmax) - return FALSE; /* sout is too short */ - if (s[i] == '(') - sout[out++] = '-'; - else - sout[out++] = s[i]; - } - } - sout[out] = '\0'; - return TRUE; -} - - -/* - * 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) -{ - int y, - m, - d, - hh, - mm, - ss; - int nf; - - y = m = d = hh = mm = ss = 0; - - /* escape sequence ? */ - if (buf[0] == '{') - { - while (*(++buf) && *buf != '\''); - if (!(*buf)) - return FALSE; - buf++; - } - if (buf[4] == '-') /* year first */ - nf = sscanf(buf, "%4d-%2d-%2d %2d:%2d:%2d", &y, &m, &d, &hh, &mm, &ss); - else - nf = sscanf(buf, "%2d-%2d-%4d %2d:%2d:%2d", &m, &d, &y, &hh, &mm, &ss); - - if (nf == 5 || nf == 6) - { - st->y = y; - st->m = m; - st->d = d; - st->hh = hh; - st->mm = mm; - st->ss = ss; - - return TRUE; - } - - if (buf[4] == '-') /* year first */ - nf = sscanf(buf, "%4d-%2d-%2d", &y, &m, &d); - else - nf = sscanf(buf, "%2d-%2d-%4d", &m, &d, &y); - - if (nf == 3) - { - st->y = y; - st->m = m; - st->d = d; - - return TRUE; - } - - nf = sscanf(buf, "%2d:%2d:%2d", &hh, &mm, &ss); - if (nf == 2 || nf == 3) - { - st->hh = hh; - st->mm = mm; - st->ss = ss; - - return TRUE; - } - - return FALSE; -} - - -/* Change linefeed to carriage-return/linefeed */ -int -convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed) -{ - size_t i = 0, - out = 0; - - if (max == 0) - max = 0xffffffff; - *changed = FALSE; - for (i = 0; si[i] && out < max - 1; i++) - { - if (si[i] == '\n') - { - /* Only add the carriage-return if needed */ - if (i > 0 && si[i - 1] == '\r') - { - if (dst) - dst[out++] = si[i]; - else - out++; - continue; - } - *changed = TRUE; - - if (dst) - { - dst[out++] = '\r'; - dst[out++] = '\n'; - } - else - out += 2; - } - else - { - if (dst) - dst[out++] = si[i]; - else - out++; - } - } - if (dst) - dst[out] = '\0'; - return out; -} - - -/* - * Change carriage-return/linefeed to just linefeed - * Plus, escape any special characters. - */ -int -convert_special_chars(const char *si, char *dst, int used) -{ - size_t i = 0, - out = 0, - max; - char *p = NULL; - - - if (used == SQL_NTS) - max = strlen(si); - else - max = used; - if (dst) - { - p = dst; - p[0] = '\0'; - } -#ifdef MULTIBYTE - multibyte_init(); -#endif - - for (i = 0; i < max; i++) - { -#ifdef MULTIBYTE - if (multibyte_char_check(si[i]) != 0) - { - if (p) - p[out] = si[i]; - out++; - continue; - } -#endif - if (si[i] == '\r' && si[i + 1] == '\n') - continue; - else if (si[i] == '\'' || si[i] == '\\') - { - if (p) - p[out++] = '\\'; - else - out++; - } - if (p) - p[out++] = si[i]; - else - out++; - } - if (p) - p[out] = '\0'; - return out; -} - - -/* !!! Need to implement this function !!! */ -int -convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax) -{ - mylog("convert_pgbinary_to_char: value = '%s'\n", value); - - strncpy_null(rgbValue, value, cbValueMax); - return 0; -} - - -static unsigned int -conv_from_octal(const unsigned char *s) -{ - int i, - y = 0; - - for (i = 1; i <= 3; i++) - y += (s[i] - 48) * (int) pow(8, 3 - i); - - return y; - -} - - -static unsigned int -conv_from_hex(const unsigned char *s) -{ - int i, - y = 0, - val; - - 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') - val = s[i] - 'A' + 10; - else - val = s[i] - '0'; - - y += val * (int) pow(16, 2 - i); - } - - return y; -} - - -/* convert octal escapes to bytes */ -int -convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax) -{ - size_t i, - ilen = strlen(value); - int o = 0; - - - for (i = 0; i < ilen;) - { - if (value[i] == '\\') - { - if (value[i + 1] == '\\') - { - rgbValue[o] = value[i]; - i += 2; - } - else - { - rgbValue[o] = conv_from_octal(&value[i]); - i += 4; - } - } - else - rgbValue[o] = value[i++]; - mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]); - o++; - } - - rgbValue[o] = '\0'; /* extra protection */ - - return o; -} - - -static char * -conv_to_octal(unsigned char val) -{ - int i; - static char x[6]; - - x[0] = '\\'; - x[1] = '\\'; - x[5] = '\0'; - - for (i = 4; i > 1; i--) - { - x[i] = (val & 7) + 48; - val >>= 3; - } - - return x; -} - - -/* convert non-ascii bytes to octal escape sequences */ -int -convert_to_pgbinary(const unsigned char *in, char *out, int len) -{ - int i, - o = 0; - - for (i = 0; i < len; i++) - { - mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]); - if (isalnum(in[i]) || in[i] == ' ') - out[o++] = in[i]; - else - { - strcpy(&out[o], conv_to_octal(in[i])); - o += 5; - } - } - - mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out); - - return o; -} - - -void -encode(const char *in, char *out) -{ - unsigned int i, - ilen = strlen(in), - o = 0; - - for (i = 0; i < ilen; i++) - { - if (in[i] == '+') - { - sprintf(&out[o], "%%2B"); - o += 3; - } - else if (isspace((unsigned char) in[i])) - out[o++] = '+'; - else if (!isalnum((unsigned char) in[i])) - { - sprintf(&out[o], "%%%02x", (unsigned char) in[i]); - o += 3; - } - else - out[o++] = in[i]; - } - out[o++] = '\0'; -} - - -void -decode(const char *in, char *out) -{ - unsigned int i, - ilen = strlen(in), - o = 0; - - for (i = 0; i < ilen; i++) - { - if (in[i] == '+') - out[o++] = ' '; - else if (in[i] == '%') - { - sprintf(&out[o++], "%c", conv_from_hex(&in[i])); - i += 2; - } - else - out[o++] = in[i]; - } - out[o++] = '\0'; -} - -static const char *hextbl = "0123456789ABCDEF"; -static int -pg_bin2hex(UCHAR *src, UCHAR *dst, int length) -{ - UCHAR chr, - *src_wk, - *dst_wk; - BOOL backwards; - int i; - - backwards = FALSE; - if (dst < src) - { - if (dst + length > src + 1) - return -1; - } - else if (dst < src + length) - backwards = TRUE; - if (backwards) - { - for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--) - { - chr = *src_wk; - *dst_wk-- = hextbl[chr % 16]; - *dst_wk-- = hextbl[chr >> 4]; - } - } - else - { - for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++) - { - chr = *src_wk; - *dst_wk++ = hextbl[chr >> 4]; - *dst_wk++ = hextbl[chr % 16]; - } - } - dst[2 * length] = '\0'; - return length; -} - -/*------- - * 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, const void *value, Int2 fCType, PTR rgbValue, - SDWORD cbValueMax, SDWORD *pcbValue) -{ - Oid oid; - int retval, - result, - left = -1; - BindInfoClass *bindInfo = NULL; - ConnectionClass *conn = SC_get_conn(stmt); - ConnInfo *ci = &(conn->connInfo); - int factor = (fCType == SQL_C_CHAR ? 2 : 1); - - /* If using SQLGetData, then current_col will be set */ - if (stmt->current_col >= 0) - { - bindInfo = &stmt->bindings[stmt->current_col]; - left = bindInfo->data_left; - } - - /* - * if this is the first call for this column, open the large object - * for reading - */ - - if (!bindInfo || bindInfo->data_left == -1) - { - /* begin transaction if needed */ - if (!CC_is_in_trans(conn)) - { - QResultClass *res; - char ok; - - res = CC_send_query(conn, "BEGIN", NULL); - if (!res) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - return COPY_GENERAL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - return COPY_GENERAL_ERROR; - } - - CC_set_in_trans(conn); - } - - oid = atoi(value); - stmt->lobj_fd = lo_open(conn, oid, INV_READ); - if (stmt->lobj_fd < 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt open large object for reading."; - return COPY_GENERAL_ERROR; - } - - /* Get the size */ - retval = lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_END); - if (retval >= 0) - { - left = lo_tell(conn, stmt->lobj_fd); - if (bindInfo) - bindInfo->data_left = left; - - /* return to beginning */ - lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET); - } - } - mylog("lo data left = %d\n", left); - - if (left == 0) - return COPY_NO_DATA_FOUND; - - if (stmt->lobj_fd < 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Large object FD undefined for multiple read."; - return COPY_GENERAL_ERROR; - } - - retval = lo_read(conn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax); - if (retval < 0) - { - lo_close(conn, stmt->lobj_fd); - - /* commit transaction if needed */ - if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn)) - { - QResultClass *res; - char ok; - - res = CC_send_query(conn, "COMMIT", NULL); - if (!res) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - return COPY_GENERAL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - return COPY_GENERAL_ERROR; - } - - CC_set_no_trans(conn); - } - - stmt->lobj_fd = -1; - - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Error reading from large object."; - return COPY_GENERAL_ERROR; - } - - if (factor > 1) - pg_bin2hex((char *) rgbValue, (char *) rgbValue, retval); - if (retval < left) - result = COPY_RESULT_TRUNCATED; - else - result = COPY_OK; - - if (pcbValue) - *pcbValue = left < 0 ? SQL_NO_TOTAL : left * factor; - - if (bindInfo && bindInfo->data_left > 0) - bindInfo->data_left -= retval; - - if (!bindInfo || bindInfo->data_left == 0) - { - lo_close(conn, stmt->lobj_fd); - - /* commit transaction if needed */ - if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn)) - { - QResultClass *res; - char ok; - - res = CC_send_query(conn, "COMMIT", NULL); - if (!res) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - return COPY_GENERAL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - return COPY_GENERAL_ERROR; - } - - CC_set_no_trans(conn); - } - - stmt->lobj_fd = -1; /* prevent further reading */ - } - - return result; -} diff --git a/src/interfaces/odbc/windev/convert.h b/src/interfaces/odbc/windev/convert.h deleted file mode 100644 index 565ce6bf19..0000000000 --- a/src/interfaces/odbc/windev/convert.h +++ /dev/null @@ -1,52 +0,0 @@ -/* File: convert.h - * - * Description: See "convert.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __CONVERT_H__ -#define __CONVERT_H__ - -#include "psqlodbc.h" - -/* copy_and_convert results */ -#define COPY_OK 0 -#define COPY_UNSUPPORTED_TYPE 1 -#define COPY_UNSUPPORTED_CONVERSION 2 -#define COPY_RESULT_TRUNCATED 3 -#define COPY_GENERAL_ERROR 4 -#define COPY_NO_DATA_FOUND 5 - -typedef struct -{ - int m; - int d; - int y; - int hh; - int mm; - int ss; - int fr; -} SIMPLE_TIME; - -int copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col); -int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType, - PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue); - -int copy_statement_with_parameters(StatementClass *stmt); -char *convert_escape(char *value); -BOOL convert_money(const char *s, char *sout, size_t soutmax); -char parse_datetime(char *buf, SIMPLE_TIME *st); -int convert_linefeeds(const char *s, char *dst, size_t max, BOOL *changed); -int convert_special_chars(const char *si, char *dst, int used); - -int convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax); -int convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax); -int convert_to_pgbinary(const unsigned char *in, char *out, int len); -void encode(const char *in, char *out); -void decode(const char *in, char *out); -int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue, - SDWORD cbValueMax, SDWORD *pcbValue); - -#endif diff --git a/src/interfaces/odbc/windev/dlg_specific.c b/src/interfaces/odbc/windev/dlg_specific.c deleted file mode 100644 index f23fb9c527..0000000000 --- a/src/interfaces/odbc/windev/dlg_specific.c +++ /dev/null @@ -1,1138 +0,0 @@ -/*------- - * Module: dlg_specific.c - * - * Description: This module contains any specific code for handling - * dialog boxes such as driver/datasource options. Both the - * ConfigDSN() and the SQLDriverConnect() functions use - * functions in this module. If you were to add a new option - * to any dialog box, you would most likely only have to change - * things in here rather than in 2 separate places as before. - * - * Classes: none - * - * API functions: none - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ -/* Multibyte support Eiji Tokuya 2001-03-15 */ - -#include "dlg_specific.h" - -#include "convert.h" - -#ifdef MULTIBYTE -#include "multibyte.h" -#endif -#include "pgapifunc.h" - -#ifndef BOOL -#define BOOL int -#endif -#ifndef FALSE -#define FALSE (BOOL)0 -#endif -#ifndef TRUE -#define TRUE (BOOL)1 -#endif - -extern GLOBAL_VALUES globals; - -#ifdef WIN32 -static int driver_optionsDraw(HWND, const ConnInfo *, int src, BOOL enable); -static int driver_options_update(HWND hdlg, ConnInfo *ci, BOOL); -static void updateCommons(const ConnInfo *ci); -#endif - -#ifdef WIN32 -void -SetDlgStuff(HWND hdlg, const ConnInfo *ci) -{ - /* - * If driver attribute NOT present, then set the datasource name and - * description - */ - if (ci->driver[0] == '\0') - { - SetDlgItemText(hdlg, IDC_DSNAME, ci->dsn); - SetDlgItemText(hdlg, IDC_DESC, ci->desc); - } - - SetDlgItemText(hdlg, IDC_DATABASE, ci->database); - SetDlgItemText(hdlg, IDC_SERVER, ci->server); - SetDlgItemText(hdlg, IDC_USER, ci->username); - SetDlgItemText(hdlg, IDC_PASSWORD, ci->password); - SetDlgItemText(hdlg, IDC_PORT, ci->port); -} - - -void -GetDlgStuff(HWND hdlg, ConnInfo *ci) -{ - GetDlgItemText(hdlg, IDC_DESC, ci->desc, sizeof(ci->desc)); - - GetDlgItemText(hdlg, IDC_DATABASE, ci->database, sizeof(ci->database)); - GetDlgItemText(hdlg, IDC_SERVER, ci->server, sizeof(ci->server)); - GetDlgItemText(hdlg, IDC_USER, ci->username, sizeof(ci->username)); - GetDlgItemText(hdlg, IDC_PASSWORD, ci->password, sizeof(ci->password)); - GetDlgItemText(hdlg, IDC_PORT, ci->port, sizeof(ci->port)); -} - - -static int -driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable) -{ - const GLOBAL_VALUES *comval; - static BOOL defset = FALSE; - static GLOBAL_VALUES defval; - - switch (src) - { - case 0: /* driver common */ - comval = &globals; - break; - case 1: /* dsn specific */ - comval = &(ci->drivers); - break; - case 2: /* default */ - if (!defset) - { - defval.commlog = DEFAULT_COMMLOG; - defval.disable_optimizer = DEFAULT_OPTIMIZER; - defval.ksqo = DEFAULT_KSQO; - defval.unique_index = DEFAULT_UNIQUEINDEX; - defval.onlyread = DEFAULT_READONLY; - defval.use_declarefetch = DEFAULT_USEDECLAREFETCH; - - defval.parse = DEFAULT_PARSE; - defval.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; - defval.debug = DEFAULT_DEBUG; - - /* Unknown Sizes */ - defval.unknown_sizes = DEFAULT_UNKNOWNSIZES; - defval.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR; - defval.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR; - defval.bools_as_char = DEFAULT_BOOLSASCHAR; - } - defset = TRUE; - comval = &defval; - break; - } - - CheckDlgButton(hdlg, DRV_COMMLOG, comval->commlog); - CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer); - CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo); - CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index); - EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable); - CheckDlgButton(hdlg, DRV_READONLY, comval->onlyread); - EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable); - CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch); - - /* Unknown Sizes clear */ - CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0); - CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0); - CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0); - /* Unknown (Default) Data Type sizes */ - switch (comval->unknown_sizes) - { - case UNKNOWNS_AS_DONTKNOW: - CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1); - break; - case UNKNOWNS_AS_LONGEST: - CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1); - break; - case UNKNOWNS_AS_MAX: - default: - CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1); - break; - } - - CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, comval->text_as_longvarchar); - CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, comval->unknowns_as_longvarchar); - CheckDlgButton(hdlg, DRV_BOOLS_CHAR, comval->bools_as_char); - CheckDlgButton(hdlg, DRV_PARSE, comval->parse); - CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, comval->cancel_as_freestmt); - CheckDlgButton(hdlg, DRV_DEBUG, comval->debug); - SetDlgItemInt(hdlg, DRV_CACHE_SIZE, comval->fetch_max, FALSE); - SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, comval->max_varchar_size, FALSE); - SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, comval->max_longvarchar_size, TRUE); - SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes); - - /* Driver Connection Settings */ - SetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings); - EnableWindow(GetDlgItem(hdlg, DRV_CONNSETTINGS), enable); - return 0; -} -static int -driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile) -{ - GLOBAL_VALUES *comval; - - if (ci) - comval = &(ci->drivers); - else - comval = &globals; - comval->commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG); - comval->disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER); - comval->ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO); - if (!ci) - { - comval->unique_index = IsDlgButtonChecked(hdlg, DRV_UNIQUEINDEX); - comval->onlyread = IsDlgButtonChecked(hdlg, DRV_READONLY); - } - comval->use_declarefetch = IsDlgButtonChecked(hdlg, DRV_USEDECLAREFETCH); - - /* Unknown (Default) Data Type sizes */ - if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_MAX)) - comval->unknown_sizes = UNKNOWNS_AS_MAX; - else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_DONTKNOW)) - comval->unknown_sizes = UNKNOWNS_AS_DONTKNOW; - else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_LONGEST)) - comval->unknown_sizes = UNKNOWNS_AS_LONGEST; - else - comval->unknown_sizes = UNKNOWNS_AS_MAX; - - comval->text_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_TEXT_LONGVARCHAR); - comval->unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR); - comval->bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR); - - comval->parse = IsDlgButtonChecked(hdlg, DRV_PARSE); - - comval->cancel_as_freestmt = IsDlgButtonChecked(hdlg, DRV_CANCELASFREESTMT); - comval->debug = IsDlgButtonChecked(hdlg, DRV_DEBUG); - - comval->fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE); - comval->max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE); - comval->max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for - * SQL_NO_TOTAL */ - - GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, sizeof(comval->extra_systable_prefixes)); - - /* Driver Connection Settings */ - if (!ci) - GetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings, sizeof(comval->conn_settings)); - - if (updateProfile) - updateCommons(ci); - - /* fall through */ - return 0; -} - -int CALLBACK -driver_optionsProc(HWND hdlg, - WORD wMsg, - WPARAM wParam, - LPARAM lParam) -{ - ConnInfo *ci; - - switch (wMsg) - { - case WM_INITDIALOG: - SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK etc */ - ci = (ConnInfo *) lParam; - CheckDlgButton(hdlg, DRV_OR_DSN, 0); - if (ci && ci->dsn && ci->dsn[0]) - SetWindowText(hdlg, "Advanced Options (per DSN)"); - else - { - SetWindowText(hdlg, "Advanced Options (Connection)"); - ShowWindow(GetDlgItem(hdlg, DRV_OR_DSN), SW_HIDE); - } - driver_optionsDraw(hdlg, ci, 1, FALSE); - break; - - case WM_COMMAND: - switch (GET_WM_COMMAND_ID(wParam, lParam)) - { - case IDOK: - ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); - driver_options_update(hdlg, IsDlgButtonChecked(hdlg, DRV_OR_DSN) ? NULL : ci, - ci && ci->dsn && ci->dsn[0]); - - case IDCANCEL: - EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); - return TRUE; - - case IDDEFAULTS: - if (IsDlgButtonChecked(hdlg, DRV_OR_DSN)) - driver_optionsDraw(hdlg, NULL, 2, TRUE); - else - { - ConnInfo *ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); - - driver_optionsDraw(hdlg, ci, 0, FALSE); - } - break; - - case DRV_OR_DSN: - if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED) - { - mylog("DRV_OR_DSN clicked\n"); - if (IsDlgButtonChecked(hdlg, DRV_OR_DSN)) - { - SetWindowText(hdlg, "Advanced Options (Common)"); - driver_optionsDraw(hdlg, NULL, 0, TRUE); - } - else - { - ConnInfo *ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); - - SetWindowText(hdlg, "Advanced Options (per DSN)"); - driver_optionsDraw(hdlg, ci, ci ? 1 : 0, ci == NULL); - } - } - break; - } - } - - return FALSE; -} - - -int CALLBACK -ds_optionsProc(HWND hdlg, - WORD wMsg, - WPARAM wParam, - LPARAM lParam) -{ - ConnInfo *ci; - char buf[128]; - - switch (wMsg) - { - case WM_INITDIALOG: - ci = (ConnInfo *) lParam; - SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK */ - - /* Change window caption */ - if (ci->driver[0]) - SetWindowText(hdlg, "Advanced Options (Connection)"); - else - { - sprintf(buf, "Advanced Options (%s)", ci->dsn); - SetWindowText(hdlg, buf); - } - - /* Readonly */ - CheckDlgButton(hdlg, DS_READONLY, atoi(ci->onlyread)); - - /* Protocol */ - if (strncmp(ci->protocol, PG62, strlen(PG62)) == 0) - CheckDlgButton(hdlg, DS_PG62, 1); - 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)); - CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables)); - CheckDlgButton(hdlg, DS_DISALLOWPREMATURE, ci->disallow_premature); - - EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column)); - - /* Datasource Connection Settings */ - SetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings); - break; - - case WM_COMMAND: - switch (GET_WM_COMMAND_ID(wParam, lParam)) - { - case DS_SHOWOIDCOLUMN: - mylog("WM_COMMAND: DS_SHOWOIDCOLUMN\n"); - 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); - - /* Readonly */ - sprintf(ci->onlyread, "%d", IsDlgButtonChecked(hdlg, DS_READONLY)); - - /* Protocol */ - if (IsDlgButtonChecked(hdlg, DS_PG62)) - strcpy(ci->protocol, PG62); - 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)); - - sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING)); - ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE); - - /* OID Options */ - sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX)); - sprintf(ci->show_oid_column, "%d", IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN)); - - /* Datasource Connection Settings */ - GetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings, sizeof(ci->conn_settings)); - - /* fall through */ - - case IDCANCEL: - EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); - return TRUE; - } - } - - return FALSE; -} - -/* - * This function writes any global parameters (that can be manipulated) - * to the ODBCINST.INI portion of the registry - */ -static void -updateCommons(const ConnInfo *ci) -{ - const char *sectionName; - const char *fileName; - const GLOBAL_VALUES *comval; - char tmp[128]; - - if (ci) - if (ci->dsn && ci->dsn[0]) - { - mylog("DSN=%s updating\n", ci->dsn); - comval = &(ci->drivers); - sectionName = ci->dsn; - fileName = ODBC_INI; - } - else - { - mylog("ci but dsn==NULL\n"); - return; - } - else - { - mylog("drivers updating\n"); - comval = &globals; - sectionName = DBMS_NAME; - fileName = ODBCINST_INI; - } - sprintf(tmp, "%d", comval->fetch_max); - SQLWritePrivateProfileString(sectionName, - INI_FETCH, tmp, fileName); - - sprintf(tmp, "%d", comval->commlog); - SQLWritePrivateProfileString(sectionName, - INI_COMMLOG, tmp, fileName); - - sprintf(tmp, "%d", comval->debug); - SQLWritePrivateProfileString(sectionName, - INI_DEBUG, tmp, fileName); - - sprintf(tmp, "%d", comval->disable_optimizer); - SQLWritePrivateProfileString(sectionName, - INI_OPTIMIZER, tmp, fileName); - - sprintf(tmp, "%d", comval->ksqo); - SQLWritePrivateProfileString(sectionName, - INI_KSQO, tmp, fileName); - - /* - * Never update the onlyread, unique_index from this module. - */ - if (!ci) - { - sprintf(tmp, "%d", comval->unique_index); - SQLWritePrivateProfileString(sectionName, INI_UNIQUEINDEX, tmp, - fileName); - - sprintf(tmp, "%d", comval->onlyread); - SQLWritePrivateProfileString(sectionName, INI_READONLY, tmp, - fileName); - } - - sprintf(tmp, "%d", comval->use_declarefetch); - SQLWritePrivateProfileString(sectionName, - INI_USEDECLAREFETCH, tmp, fileName); - - sprintf(tmp, "%d", comval->unknown_sizes); - SQLWritePrivateProfileString(sectionName, - INI_UNKNOWNSIZES, tmp, fileName); - - sprintf(tmp, "%d", comval->text_as_longvarchar); - SQLWritePrivateProfileString(sectionName, - INI_TEXTASLONGVARCHAR, tmp, fileName); - - sprintf(tmp, "%d", comval->unknowns_as_longvarchar); - SQLWritePrivateProfileString(sectionName, - INI_UNKNOWNSASLONGVARCHAR, tmp, fileName); - - sprintf(tmp, "%d", comval->bools_as_char); - SQLWritePrivateProfileString(sectionName, - INI_BOOLSASCHAR, tmp, fileName); - - sprintf(tmp, "%d", comval->parse); - SQLWritePrivateProfileString(sectionName, - INI_PARSE, tmp, fileName); - - sprintf(tmp, "%d", comval->cancel_as_freestmt); - SQLWritePrivateProfileString(sectionName, - INI_CANCELASFREESTMT, tmp, fileName); - - sprintf(tmp, "%d", comval->max_varchar_size); - SQLWritePrivateProfileString(sectionName, - INI_MAXVARCHARSIZE, tmp, fileName); - - sprintf(tmp, "%d", comval->max_longvarchar_size); - SQLWritePrivateProfileString(sectionName, - INI_MAXLONGVARCHARSIZE, tmp, fileName); - - SQLWritePrivateProfileString(sectionName, - INI_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, fileName); - - /* - * Never update the conn_setting from this module - * SQLWritePrivateProfileString(sectionName, INI_CONNSETTINGS, - * comval->conn_settings, fileName); - */ -} -#endif /* WIN32 */ - - -void -makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len) -{ - char got_dsn = (ci->dsn[0] != '\0'); - char encoded_conn_settings[LARGE_REGISTRY_LEN]; - UWORD hlen; - /*BOOL abbrev = (len <= 400);*/ - BOOL abbrev = (len < 1024); - - /* fundamental info */ - sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s", - got_dsn ? "DSN" : "DRIVER", - got_dsn ? ci->dsn : ci->driver, - ci->database, - ci->server, - ci->port, - ci->username, - ci->password); - - encode(ci->conn_settings, encoded_conn_settings); - - /* extra info */ - hlen = strlen(connect_string); - if (!abbrev) - sprintf(&connect_string[hlen], - ";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s;FETCH=%d;SOCKET=%d;UNKNOWNSIZES=%d;MAXVARCHARSIZE=%d;MAXLONGVARCHARSIZE=%d;DEBUG=%d;COMMLOG=%d;OPTIMIZER=%d;KSQO=%d;USEDECLAREFETCH=%d;TEXTASLONGVARCHAR=%d;UNKNOWNSASLONGVARCHAR=%d;BOOLSASCHAR=%d;PARSE=%d;CANCELASFREESTMT=%d;EXTRASYSTABLEPREFIXES=%s", - ci->onlyread, - ci->protocol, - ci->fake_oid_index, - ci->show_oid_column, - ci->row_versioning, - ci->show_system_tables, - encoded_conn_settings, - ci->drivers.fetch_max, - ci->drivers.socket_buffersize, - ci->drivers.unknown_sizes, - ci->drivers.max_varchar_size, - ci->drivers.max_longvarchar_size, - ci->drivers.debug, - ci->drivers.commlog, - ci->drivers.disable_optimizer, - ci->drivers.ksqo, - ci->drivers.use_declarefetch, - ci->drivers.text_as_longvarchar, - ci->drivers.unknowns_as_longvarchar, - ci->drivers.bools_as_char, - ci->drivers.parse, - ci->drivers.cancel_as_freestmt, - ci->drivers.extra_systable_prefixes); - /* Abbrebiation is needed ? */ - if (abbrev || strlen(connect_string) >= len) - sprintf(&connect_string[hlen], - ";A0=%s;A1=%s;A2=%s;A3=%s;A4=%s;A5=%s;A6=%s;A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s", - ci->onlyread, - ci->protocol, - ci->fake_oid_index, - ci->show_oid_column, - ci->row_versioning, - ci->show_system_tables, - encoded_conn_settings, - ci->drivers.fetch_max, - ci->drivers.socket_buffersize, - ci->drivers.unknown_sizes, - ci->drivers.max_varchar_size, - ci->drivers.max_longvarchar_size, - ci->drivers.debug, - ci->drivers.commlog, - ci->drivers.disable_optimizer, - ci->drivers.ksqo, - ci->drivers.use_declarefetch, - ci->drivers.text_as_longvarchar, - ci->drivers.unknowns_as_longvarchar, - ci->drivers.bools_as_char, - ci->drivers.parse, - ci->drivers.cancel_as_freestmt, - ci->drivers.extra_systable_prefixes); -} - - -void -copyAttributes(ConnInfo *ci, const char *attribute, const char *value) -{ - if (stricmp(attribute, "DSN") == 0) - strcpy(ci->dsn, value); - - else if (stricmp(attribute, "driver") == 0) - strcpy(ci->driver, value); - - else if (stricmp(attribute, INI_DATABASE) == 0) - strcpy(ci->database, value); - - else if (stricmp(attribute, INI_SERVER) == 0 || stricmp(attribute, "server") == 0) - strcpy(ci->server, value); - - else if (stricmp(attribute, INI_USER) == 0 || stricmp(attribute, "uid") == 0) - strcpy(ci->username, value); - - else if (stricmp(attribute, INI_PASSWORD) == 0 || stricmp(attribute, "pwd") == 0) - strcpy(ci->password, value); - - else if (stricmp(attribute, INI_PORT) == 0) - strcpy(ci->port, value); - - else if (stricmp(attribute, INI_READONLY) == 0 || stricmp(attribute, "A0") == 0) - strcpy(ci->onlyread, value); - - else if (stricmp(attribute, INI_PROTOCOL) == 0 || stricmp(attribute, "A1") == 0) - strcpy(ci->protocol, value); - - else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0 || stricmp(attribute, "A3") == 0) - strcpy(ci->show_oid_column, value); - - else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0 || stricmp(attribute, "A2") == 0) - strcpy(ci->fake_oid_index, value); - - else if (stricmp(attribute, INI_ROWVERSIONING) == 0 || stricmp(attribute, "A4") == 0) - strcpy(ci->row_versioning, value); - - else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0 || stricmp(attribute, "A5") == 0) - strcpy(ci->show_system_tables, value); - - else if (stricmp(attribute, INI_CONNSETTINGS) == 0 || stricmp(attribute, "A6") == 0) - { - decode(value, ci->conn_settings); - /* strcpy(ci->conn_settings, value); */ - } - else if (stricmp(attribute, INI_DISALLOWPREMATURE) == 0 || stricmp(attribute, "C3") == 0) - ci->disallow_premature = atoi(value); - else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, "C4") == 0) - ci->updatable_cursors = atoi(value); - - mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature); -} - -void -copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value) -{ - if (stricmp(attribute, INI_FETCH) == 0 || stricmp(attribute, "A7") == 0) - ci->drivers.fetch_max = atoi(value); - else if (stricmp(attribute, INI_SOCKET) == 0 || stricmp(attribute, "A8") == 0) - ci->drivers.socket_buffersize = atoi(value); - else if (stricmp(attribute, INI_DEBUG) == 0 || stricmp(attribute, "B2") == 0) - ci->drivers.debug = atoi(value); - else if (stricmp(attribute, INI_COMMLOG) == 0 || stricmp(attribute, "B3") == 0) - ci->drivers.commlog = atoi(value); - else if (stricmp(attribute, INI_OPTIMIZER) == 0 || stricmp(attribute, "B4") == 0) - ci->drivers.disable_optimizer = atoi(value); - else if (stricmp(attribute, INI_KSQO) == 0 || stricmp(attribute, "B5") == 0) - ci->drivers.ksqo = atoi(value); - - /* - * else if (stricmp(attribute, INI_UNIQUEINDEX) == 0 || - * stricmp(attribute, "UIX") == 0) ci->drivers.unique_index = - * atoi(value); - */ - else if (stricmp(attribute, INI_UNKNOWNSIZES) == 0 || stricmp(attribute, "A9") == 0) - ci->drivers.unknown_sizes = atoi(value); - else if (stricmp(attribute, INI_LIE) == 0) - ci->drivers.lie = atoi(value); - else if (stricmp(attribute, INI_PARSE) == 0 || stricmp(attribute, "C0") == 0) - ci->drivers.parse = atoi(value); - else if (stricmp(attribute, INI_CANCELASFREESTMT) == 0 || stricmp(attribute, "C1") == 0) - ci->drivers.cancel_as_freestmt = atoi(value); - else if (stricmp(attribute, INI_USEDECLAREFETCH) == 0 || stricmp(attribute, "B6") == 0) - ci->drivers.use_declarefetch = atoi(value); - else if (stricmp(attribute, INI_MAXVARCHARSIZE) == 0 || stricmp(attribute, "B0") == 0) - ci->drivers.max_varchar_size = atoi(value); - else if (stricmp(attribute, INI_MAXLONGVARCHARSIZE) == 0 || stricmp(attribute, "B1") == 0) - ci->drivers.max_longvarchar_size = atoi(value); - else if (stricmp(attribute, INI_TEXTASLONGVARCHAR) == 0 || stricmp(attribute, "B7") == 0) - ci->drivers.text_as_longvarchar = atoi(value); - else if (stricmp(attribute, INI_UNKNOWNSASLONGVARCHAR) == 0 || stricmp(attribute, "B8") == 0) - ci->drivers.unknowns_as_longvarchar = atoi(value); - else if (stricmp(attribute, INI_BOOLSASCHAR) == 0 || stricmp(attribute, "B9") == 0) - ci->drivers.bools_as_char = atoi(value); - else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, "C2") == 0) - strcpy(ci->drivers.extra_systable_prefixes, value); - mylog("CopyCommonAttributes: A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s", - ci->drivers.fetch_max, - ci->drivers.socket_buffersize, - ci->drivers.unknown_sizes, - ci->drivers.max_varchar_size, - ci->drivers.max_longvarchar_size, - ci->drivers.debug, - ci->drivers.commlog, - ci->drivers.disable_optimizer, - ci->drivers.ksqo, - ci->drivers.use_declarefetch, - ci->drivers.text_as_longvarchar, - ci->drivers.unknowns_as_longvarchar, - ci->drivers.bools_as_char, - ci->drivers.parse, - ci->drivers.cancel_as_freestmt, - ci->drivers.extra_systable_prefixes); -} - - -void -getDSNdefaults(ConnInfo *ci) -{ - if (ci->port[0] == '\0') - strcpy(ci->port, DEFAULT_PORT); - - if (ci->onlyread[0] == '\0') - sprintf(ci->onlyread, "%d", globals.onlyread); - - if (ci->protocol[0] == '\0') - strcpy(ci->protocol, globals.protocol); - - if (ci->fake_oid_index[0] == '\0') - sprintf(ci->fake_oid_index, "%d", DEFAULT_FAKEOIDINDEX); - - if (ci->show_oid_column[0] == '\0') - sprintf(ci->show_oid_column, "%d", DEFAULT_SHOWOIDCOLUMN); - - if (ci->show_system_tables[0] == '\0') - sprintf(ci->show_system_tables, "%d", DEFAULT_SHOWSYSTEMTABLES); - - if (ci->row_versioning[0] == '\0') - sprintf(ci->row_versioning, "%d", DEFAULT_ROWVERSIONING); -} - - -void -getDSNinfo(ConnInfo *ci, char overwrite) -{ - char *DSN = ci->dsn; - char encoded_conn_settings[LARGE_REGISTRY_LEN], - temp[SMALL_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. - */ - memcpy(&ci->drivers, &globals, sizeof(globals)); - if (DSN[0] == '\0') - { - if (ci->driver[0] != '\0') - return; - else - strcpy(DSN, INI_DSN); - } - - /* brute-force chop off trailing blanks... */ - while (*(DSN + strlen(DSN) - 1) == ' ') - *(DSN + strlen(DSN) - 1) = '\0'; - - /* Proceed with getting info for the given DSN. */ - - if (ci->desc[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_KDESC, "", ci->desc, sizeof(ci->desc), ODBC_INI); - - if (ci->server[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_SERVER, "", ci->server, sizeof(ci->server), ODBC_INI); - - if (ci->database[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_DATABASE, "", ci->database, sizeof(ci->database), ODBC_INI); - - if (ci->username[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_USER, "", ci->username, sizeof(ci->username), ODBC_INI); - - if (ci->password[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_PASSWORD, "", ci->password, sizeof(ci->password), ODBC_INI); - - if (ci->port[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_PORT, "", ci->port, sizeof(ci->port), ODBC_INI); - - if (ci->onlyread[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_READONLY, "", ci->onlyread, sizeof(ci->onlyread), ODBC_INI); - - if (ci->show_oid_column[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_SHOWOIDCOLUMN, "", ci->show_oid_column, sizeof(ci->show_oid_column), ODBC_INI); - - if (ci->fake_oid_index[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_FAKEOIDINDEX, "", ci->fake_oid_index, sizeof(ci->fake_oid_index), ODBC_INI); - - if (ci->row_versioning[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_ROWVERSIONING, "", ci->row_versioning, sizeof(ci->row_versioning), ODBC_INI); - - if (ci->show_system_tables[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_SHOWSYSTEMTABLES, "", ci->show_system_tables, sizeof(ci->show_system_tables), ODBC_INI); - - if (ci->protocol[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_PROTOCOL, "", ci->protocol, sizeof(ci->protocol), ODBC_INI); - - if (ci->conn_settings[0] == '\0' || overwrite) - { - SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, "", encoded_conn_settings, sizeof(encoded_conn_settings), ODBC_INI); - decode(encoded_conn_settings, ci->conn_settings); - } - - if (ci->translation_dll[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_TRANSLATIONDLL, "", ci->translation_dll, sizeof(ci->translation_dll), ODBC_INI); - - if (ci->translation_option[0] == '\0' || overwrite) - SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI); - - if (ci->disallow_premature == 0 || overwrite) - { - SQLGetPrivateProfileString(DSN, INI_DISALLOWPREMATURE, "", temp, sizeof(temp), ODBC_INI); - ci->disallow_premature = atoi(temp); - } - - if (ci->updatable_cursors == 0 || overwrite) - { - SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI); - ci->updatable_cursors = atoi(temp); - } - - /* Allow override of odbcinst.ini parameters here */ - getCommonDefaults(DSN, ODBC_INI, ci); - - qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n", - DSN, - ci->server, - ci->port, - ci->database, - ci->username, - ci->password); - qlog(" onlyread='%s',protocol='%s',showoid='%s',fakeoidindex='%s',showsystable='%s'\n", - ci->onlyread, - ci->protocol, - ci->show_oid_column, - ci->fake_oid_index, - ci->show_system_tables); - -#ifdef MULTIBYTE - check_client_encoding(ci->conn_settings); - qlog(" conn_settings='%s',conn_encoding='%s'\n", - ci->conn_settings, - check_client_encoding(ci->conn_settings)); -#else - qlog(" conn_settings='%s'\n", - ci->conn_settings); -#endif - - qlog(" translation_dll='%s',translation_option='%s'\n", - ci->translation_dll, - ci->translation_option); -} - - -/* This is for datasource based options only */ -void -writeDSNinfo(const ConnInfo *ci) -{ - const char *DSN = ci->dsn; - char encoded_conn_settings[LARGE_REGISTRY_LEN], - temp[SMALL_REGISTRY_LEN]; - - encode(ci->conn_settings, encoded_conn_settings); - - SQLWritePrivateProfileString(DSN, - INI_KDESC, - ci->desc, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_DATABASE, - ci->database, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_SERVER, - ci->server, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_PORT, - ci->port, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_USER, - ci->username, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_PASSWORD, - ci->password, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_READONLY, - ci->onlyread, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_SHOWOIDCOLUMN, - ci->show_oid_column, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_FAKEOIDINDEX, - ci->fake_oid_index, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_ROWVERSIONING, - ci->row_versioning, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_SHOWSYSTEMTABLES, - ci->show_system_tables, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_PROTOCOL, - ci->protocol, - ODBC_INI); - - SQLWritePrivateProfileString(DSN, - INI_CONNSETTINGS, - encoded_conn_settings, - ODBC_INI); - - sprintf(temp, "%d", ci->disallow_premature); - SQLWritePrivateProfileString(DSN, - INI_DISALLOWPREMATURE, - temp, - ODBC_INI); - sprintf(temp, "%d", ci->updatable_cursors); - SQLWritePrivateProfileString(DSN, - INI_UPDATABLECURSORS, - temp, - ODBC_INI); -} - - -/* - * This function reads the ODBCINST.INI portion of - * the registry and gets any driver defaults. - */ -void -getCommonDefaults(const char *section, const char *filename, ConnInfo *ci) -{ - char temp[256]; - GLOBAL_VALUES *comval; - - if (ci) - comval = &(ci->drivers); - else - comval = &globals; - /* Fetch Count is stored in driver section */ - SQLGetPrivateProfileString(section, INI_FETCH, "", - temp, sizeof(temp), filename); - if (temp[0]) - { - comval->fetch_max = atoi(temp); - /* sanity check if using cursors */ - if (comval->fetch_max <= 0) - comval->fetch_max = FETCH_MAX; - } - else if (!ci) - comval->fetch_max = FETCH_MAX; - - /* Socket Buffersize is stored in driver section */ - SQLGetPrivateProfileString(section, INI_SOCKET, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->socket_buffersize = atoi(temp); - else if (!ci) - comval->socket_buffersize = SOCK_BUFFER_SIZE; - - /* Debug is stored in the driver section */ - SQLGetPrivateProfileString(section, INI_DEBUG, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->debug = atoi(temp); - else if (!ci) - comval->debug = DEFAULT_DEBUG; - - /* CommLog is stored in the driver section */ - SQLGetPrivateProfileString(section, INI_COMMLOG, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->commlog = atoi(temp); - else if (!ci) - comval->commlog = DEFAULT_COMMLOG; - - if (!ci) - logs_on_off(0, 0, 0); - /* Optimizer is stored in the driver section only */ - SQLGetPrivateProfileString(section, INI_OPTIMIZER, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->disable_optimizer = atoi(temp); - else if (!ci) - comval->disable_optimizer = DEFAULT_OPTIMIZER; - - /* KSQO is stored in the driver section only */ - SQLGetPrivateProfileString(section, INI_KSQO, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->ksqo = atoi(temp); - else if (!ci) - comval->ksqo = DEFAULT_KSQO; - - /* Recognize Unique Index is stored in the driver section only */ - SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->unique_index = atoi(temp); - else if (!ci) - comval->unique_index = DEFAULT_UNIQUEINDEX; - - - /* Unknown Sizes is stored in the driver section only */ - SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->unknown_sizes = atoi(temp); - else if (!ci) - comval->unknown_sizes = DEFAULT_UNKNOWNSIZES; - - - /* Lie about supported functions? */ - SQLGetPrivateProfileString(section, INI_LIE, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->lie = atoi(temp); - else if (!ci) - comval->lie = DEFAULT_LIE; - - /* Parse statements */ - SQLGetPrivateProfileString(section, INI_PARSE, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->parse = atoi(temp); - else if (!ci) - comval->parse = DEFAULT_PARSE; - - /* SQLCancel calls SQLFreeStmt in Driver Manager */ - SQLGetPrivateProfileString(section, INI_CANCELASFREESTMT, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->cancel_as_freestmt = atoi(temp); - else if (!ci) - comval->cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; - - /* UseDeclareFetch is stored in the driver section only */ - SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->use_declarefetch = atoi(temp); - else if (!ci) - comval->use_declarefetch = DEFAULT_USEDECLAREFETCH; - - /* Max Varchar Size */ - SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->max_varchar_size = atoi(temp); - else if (!ci) - comval->max_varchar_size = MAX_VARCHAR_SIZE; - - /* Max TextField Size */ - SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->max_longvarchar_size = atoi(temp); - else if (!ci) - comval->max_longvarchar_size = TEXT_FIELD_SIZE; - - /* Text As LongVarchar */ - SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->text_as_longvarchar = atoi(temp); - else if (!ci) - comval->text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR; - - /* Unknowns As LongVarchar */ - SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->unknowns_as_longvarchar = atoi(temp); - else if (!ci) - comval->unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR; - - /* Bools As Char */ - SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->bools_as_char = atoi(temp); - else if (!ci) - comval->bools_as_char = DEFAULT_BOOLSASCHAR; - - /* Extra Systable prefixes */ - - /* - * Use @@@ to distinguish between blank extra prefixes and no key - * entry - */ - SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, "@@@", - temp, sizeof(temp), filename); - if (strcmp(temp, "@@@")) - strcpy(comval->extra_systable_prefixes, temp); - else if (!ci) - strcpy(comval->extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES); - - mylog("globals.extra_systable_prefixes = '%s'\n", comval->extra_systable_prefixes); - - - /* Dont allow override of an override! */ - if (!ci) - { - /* - * ConnSettings is stored in the driver section and per datasource - * for override - */ - SQLGetPrivateProfileString(section, INI_CONNSETTINGS, "", - comval->conn_settings, sizeof(comval->conn_settings), filename); - - /* Default state for future DSN's Readonly attribute */ - SQLGetPrivateProfileString(section, INI_READONLY, "", - temp, sizeof(temp), filename); - if (temp[0]) - comval->onlyread = atoi(temp); - else - comval->onlyread = DEFAULT_READONLY; - - /* - * Default state for future DSN's protocol attribute This isn't a - * real driver option YET. This is more intended for - * customization from the install. - */ - SQLGetPrivateProfileString(section, INI_PROTOCOL, "@@@", - temp, sizeof(temp), filename); - if (strcmp(temp, "@@@")) - strcpy(comval->protocol, temp); - else - strcpy(comval->protocol, DEFAULT_PROTOCOL); - } -} diff --git a/src/interfaces/odbc/windev/dlg_specific.h b/src/interfaces/odbc/windev/dlg_specific.h deleted file mode 100644 index b3192123d0..0000000000 --- a/src/interfaces/odbc/windev/dlg_specific.h +++ /dev/null @@ -1,147 +0,0 @@ -/* File: dlg_specific.h - * - * Description: See "dlg_specific.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __DLG_SPECIFIC_H__ -#define __DLG_SPECIFIC_H__ - -#include "psqlodbc.h" -#include "connection.h" - -#ifdef WIN32 -#include -#include "resource.h" -#endif - -/* Unknown data type sizes */ -#define UNKNOWNS_AS_MAX 0 -#define UNKNOWNS_AS_DONTKNOW 1 -#define UNKNOWNS_AS_LONGEST 2 - -/* ODBC initialization files */ -#ifndef WIN32 -#define ODBC_INI ".odbc.ini" -#define ODBCINST_INI "odbcinst.ini" -#else -#define ODBC_INI "ODBC.INI" -#define ODBCINST_INI "ODBCINST.INI" -#endif - - -#define INI_DSN DBMS_NAME /* Name of default - * Datasource in ini - * file (not used?) */ -#define INI_KDESC "Description" /* Data source - * description */ -#define INI_SERVER "Servername" /* Name of Server - * running the Postgres - * service */ -#define INI_PORT "Port" /* Port on which the - * Postmaster is listening */ -#define INI_DATABASE "Database" /* Database Name */ -#define INI_USER "Username" /* Default User Name */ -#define INI_PASSWORD "Password" /* Default Password */ -#define INI_DEBUG "Debug" /* Debug flag */ -#define INI_FETCH "Fetch" /* Fetch Max Count */ -#define INI_SOCKET "Socket" /* Socket buffer size */ -#define INI_READONLY "ReadOnly" /* Database is read only */ -#define INI_COMMLOG "CommLog" /* Communication to - * backend logging */ -#define INI_PROTOCOL "Protocol" /* What protocol (6.2) */ -#define INI_OPTIMIZER "Optimizer" /* Use backend genetic - * optimizer */ -#define INI_KSQO "Ksqo" /* Keyset query - * optimization */ -#define INI_CONNSETTINGS "ConnSettings" /* Anything to send to - * backend on successful - * connection */ -#define INI_UNIQUEINDEX "UniqueIndex" /* Recognize unique - * indexes */ -#define INI_UNKNOWNSIZES "UnknownSizes" /* How to handle unknown - * result set sizes */ - -#define INI_CANCELASFREESTMT "CancelAsFreeStmt" - -#define INI_USEDECLAREFETCH "UseDeclareFetch" /* Use Declare/Fetch - * cursors */ - -/* More ini stuff */ -#define INI_TEXTASLONGVARCHAR "TextAsLongVarchar" -#define INI_UNKNOWNSASLONGVARCHAR "UnknownsAsLongVarchar" -#define INI_BOOLSASCHAR "BoolsAsChar" -#define INI_MAXVARCHARSIZE "MaxVarcharSize" -#define INI_MAXLONGVARCHARSIZE "MaxLongVarcharSize" - -#define INI_FAKEOIDINDEX "FakeOidIndex" -#define INI_SHOWOIDCOLUMN "ShowOidColumn" -#define INI_ROWVERSIONING "RowVersioning" -#define INI_SHOWSYSTEMTABLES "ShowSystemTables" -#define INI_LIE "Lie" -#define INI_PARSE "Parse" -#define INI_EXTRASYSTABLEPREFIXES "ExtraSysTablePrefixes" - -#define INI_TRANSLATIONNAME "TranslationName" -#define INI_TRANSLATIONDLL "TranslationDLL" -#define INI_TRANSLATIONOPTION "TranslationOption" -#define INI_DISALLOWPREMATURE "DisallowPremature" -#define INI_UPDATABLECURSORS "UpdatableCursors" - - -/* Connection Defaults */ -#define DEFAULT_PORT "5432" -#define DEFAULT_READONLY 0 -#define DEFAULT_PROTOCOL "6.4" /* the latest protocol is - * the default */ -#define DEFAULT_USEDECLAREFETCH 0 -#define DEFAULT_TEXTASLONGVARCHAR 1 -#define DEFAULT_UNKNOWNSASLONGVARCHAR 0 -#define DEFAULT_BOOLSASCHAR 1 -#define DEFAULT_OPTIMIZER 1 /* disable */ -#define DEFAULT_KSQO 1 /* on */ -#define DEFAULT_UNIQUEINDEX 1 /* dont recognize */ -#define DEFAULT_COMMLOG 0 /* dont log */ -#define DEFAULT_DEBUG 0 -#define DEFAULT_UNKNOWNSIZES UNKNOWNS_AS_MAX - - -#define DEFAULT_FAKEOIDINDEX 0 -#define DEFAULT_SHOWOIDCOLUMN 0 -#define DEFAULT_ROWVERSIONING 0 -#define DEFAULT_SHOWSYSTEMTABLES 0 /* dont show system tables */ -#define DEFAULT_LIE 0 -#define DEFAULT_PARSE 0 - -#define DEFAULT_CANCELASFREESTMT 0 - -#define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;" - -/* prototypes */ -void getCommonDefaults(const char *section, const char *filename, ConnInfo *ci); - -#ifdef WIN32 -void SetDlgStuff(HWND hdlg, const ConnInfo *ci); -void GetDlgStuff(HWND hdlg, ConnInfo *ci); - -int CALLBACK driver_optionsProc(HWND hdlg, - WORD wMsg, - WPARAM wParam, - LPARAM lParam); -int CALLBACK ds_optionsProc(HWND hdlg, - WORD wMsg, - WPARAM wParam, - LPARAM lParam); -#endif /* WIN32 */ - -void updateGlobals(void); -void writeDSNinfo(const ConnInfo *ci); -void getDSNdefaults(ConnInfo *ci); -void getDSNinfo(ConnInfo *ci, char overwrite); -void makeConnectString(char *connect_string, const ConnInfo *ci, UWORD); -void copyAttributes(ConnInfo *ci, const char *attribute, const char *value); -void copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value); - -#endif diff --git a/src/interfaces/odbc/windev/drvconn.c b/src/interfaces/odbc/windev/drvconn.c deleted file mode 100644 index e369525ca0..0000000000 --- a/src/interfaces/odbc/windev/drvconn.c +++ /dev/null @@ -1,435 +0,0 @@ -/*------- - Module: drvconn.c - * - * Description: This module contains only routines related to - * implementing SQLDriverConnect. - * - * Classes: n/a - * - * API functions: SQLDriverConnect - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "psqlodbc.h" - -#include -#include - -#include "connection.h" - -#ifndef WIN32 -#include -#include -#define NEAR -#else -#include -#endif - -#include - -#ifdef WIN32 -#include -#include "resource.h" -#endif -#include "pgapifunc.h" - -#ifndef TRUE -#define TRUE (BOOL)1 -#endif -#ifndef FALSE -#define FALSE (BOOL)0 -#endif - -#include "dlg_specific.h" - -/* prototypes */ -void dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci); -static void dconn_get_common_attributes(const UCHAR FAR * connect_string, ConnInfo *ci); - -#ifdef WIN32 -BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam); -RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci); - -extern HINSTANCE NEAR s_hModule; /* Saved module handle. */ -#endif - - -RETCODE SQL_API -PGAPI_DriverConnect( - HDBC hdbc, - HWND hwnd, - UCHAR FAR * szConnStrIn, - SWORD cbConnStrIn, - UCHAR FAR * szConnStrOut, - SWORD cbConnStrOutMax, - SWORD FAR * pcbConnStrOut, - UWORD fDriverCompletion) -{ - static char *func = "PGAPI_DriverConnect"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - ConnInfo *ci; - -#ifdef WIN32 - RETCODE dialog_result; -#endif - RETCODE result; - char connStrIn[MAX_CONNECT_STRING]; - char connStrOut[MAX_CONNECT_STRING]; - int retval; - char password_required = FALSE; - int len = 0; - SWORD lenStrout; - - - mylog("%s: entering...\n", func); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - make_string(szConnStrIn, cbConnStrIn, connStrIn); - - mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn); - qlog("conn=%u, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion); - - ci = &(conn->connInfo); - - /* 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); - dconn_get_common_attributes(connStrIn, ci); - logs_on_off(1, ci->drivers.debug, ci->drivers.commlog); - - /* Fill in any default parameters if they are not there. */ - getDSNdefaults(ci); - /* initialize pg_version */ - CC_initialize_pg_version(conn); - -#ifdef WIN32 -dialog: -#endif - ci->focus_password = password_required; - - switch (fDriverCompletion) - { -#ifdef WIN32 - case SQL_DRIVER_PROMPT: - dialog_result = dconn_DoDialog(hwnd, ci); - if (dialog_result != SQL_SUCCESS) - return dialog_result; - break; - - case SQL_DRIVER_COMPLETE_REQUIRED: - - /* Fall through */ - - case SQL_DRIVER_COMPLETE: - - /* Password is not a required parameter. */ - if (ci->username[0] == '\0' || - ci->server[0] == '\0' || - ci->database[0] == '\0' || - ci->port[0] == '\0' || - password_required) - { - dialog_result = dconn_DoDialog(hwnd, ci); - if (dialog_result != SQL_SUCCESS) - return dialog_result; - } - break; -#else - case SQL_DRIVER_PROMPT: - case SQL_DRIVER_COMPLETE: - case SQL_DRIVER_COMPLETE_REQUIRED: -#endif - case SQL_DRIVER_NOPROMPT: - break; - } - - /* - * Password is not a required parameter unless authentication asks for - * it. For now, I think it's better to just let the application ask - * over and over until a password is entered (the user can always hit - * Cancel to get out) - */ - if (ci->username[0] == '\0' || - ci->server[0] == '\0' || - 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) - { /* need a password */ - if (fDriverCompletion == SQL_DRIVER_NOPROMPT) - { - CC_log_error(func, "Need password but Driver_NoPrompt", conn); - return SQL_ERROR; /* need a password but not allowed to - * prompt so error */ - } - else - { -#ifdef WIN32 - password_required = TRUE; - goto dialog; -#else - return SQL_ERROR; /* until a better solution is found. */ -#endif - } - } - else if (retval == 0) - { - /* error msg filled in above */ - CC_log_error(func, "Error from CC_Connect", conn); - return SQL_ERROR; - } - - /* - * Create the Output Connection String - */ - result = SQL_SUCCESS; - - lenStrout = cbConnStrOutMax; - if (conn->ms_jet && lenStrout > 255) - lenStrout = 255; - makeConnectString(connStrOut, ci, lenStrout); - len = strlen(connStrOut); - - 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, - * otherwise, it should just copy the connection input string to - * the output. However, it seems ok to just always construct an - * output string. There are possible bad side effects on working - * applications (Access) by implementing the correct behavior, - * anyway. - */ - strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax); - - if (len >= cbConnStrOutMax) - { - int clen; - - for (clen = strlen(szConnStrOut) - 1; clen >= 0 && szConnStrOut[clen] != ';'; clen--) - szConnStrOut[clen] = '\0'; - result = SQL_SUCCESS_WITH_INFO; - conn->errornumber = CONN_TRUNCATED; - conn->errormsg = "The buffer was too small for the ConnStrOut."; - } - } - - if (pcbConnStrOut) - *pcbConnStrOut = len; - - mylog("szConnStrOut = '%s' len=%d,%d\n", szConnStrOut, len, cbConnStrOutMax); - qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut); - - - mylog("PGAPI_DRiverConnect: returning %d\n", result); - return result; -} - - -#ifdef WIN32 -RETCODE -dconn_DoDialog(HWND hwnd, ConnInfo *ci) -{ - int dialog_result; - - mylog("dconn_DoDialog: ci = %u\n", ci); - - if (hwnd) - { - dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_CONFIG), - hwnd, dconn_FDriverConnectProc, (LPARAM) ci); - if (!dialog_result || (dialog_result == -1)) - return SQL_NO_DATA_FOUND; - else - return SQL_SUCCESS; - } - - return SQL_ERROR; -} - - -BOOL FAR PASCAL -dconn_FDriverConnectProc( - HWND hdlg, - UINT wMsg, - WPARAM wParam, - LPARAM lParam) -{ - ConnInfo *ci; - - switch (wMsg) - { - case WM_INITDIALOG: - ci = (ConnInfo *) lParam; - - /* Change the caption for the setup dialog */ - SetWindowText(hdlg, "PostgreSQL Connection"); - - SetWindowText(GetDlgItem(hdlg, IDC_DATASOURCE), "Connection"); - - /* Hide the DSN and description fields */ - ShowWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), SW_HIDE); - ShowWindow(GetDlgItem(hdlg, IDC_DSNAME), SW_HIDE); - ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE); - ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE); - - SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for - * the "OK" */ - SetDlgStuff(hdlg, ci); - - if (ci->database[0] == '\0') - ; /* default focus */ - else if (ci->server[0] == '\0') - SetFocus(GetDlgItem(hdlg, IDC_SERVER)); - else if (ci->port[0] == '\0') - SetFocus(GetDlgItem(hdlg, IDC_PORT)); - else if (ci->username[0] == '\0') - 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: - ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), - hdlg, driver_optionsProc, (LPARAM) ci); - break; - - case IDC_DATASOURCE: - ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS), - hdlg, ds_optionsProc, (LPARAM) ci); - break; - } - } - - return FALSE; -} -#endif /* WIN32 */ - - -void -dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci) -{ - char *our_connect_string; - char *pair, - *attribute, - *value, - *equals; - char *strtok_arg; - - memset(ci, 0, sizeof(ConnInfo)); -#ifdef DRIVER_CURSOR_IMPLEMENT - ci->updatable_cursors = 1; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - - our_connect_string = strdup(connect_string); - strtok_arg = our_connect_string; - - mylog("our_connect_string = '%s'\n", our_connect_string); - - while (1) - { - pair = strtok(strtok_arg, ";"); - if (strtok_arg) - strtok_arg = 0; - if (!pair) - break; - - equals = strchr(pair, '='); - if (!equals) - continue; - - *equals = '\0'; - attribute = pair; /* ex. DSN */ - value = equals + 1; /* ex. 'CEO co1' */ - - mylog("attribute = '%s', value = '%s'\n", attribute, value); - - if (!attribute || !value) - continue; - - /* Copy the appropriate value to the conninfo */ - copyAttributes(ci, attribute, value); - - } - - free(our_connect_string); -} - -static void -dconn_get_common_attributes(const UCHAR FAR * connect_string, ConnInfo *ci) -{ - char *our_connect_string; - char *pair, - *attribute, - *value, - *equals; - char *strtok_arg; - - our_connect_string = strdup(connect_string); - strtok_arg = our_connect_string; - - mylog("our_connect_string = '%s'\n", our_connect_string); - - while (1) - { - pair = strtok(strtok_arg, ";"); - if (strtok_arg) - strtok_arg = 0; - if (!pair) - break; - - equals = strchr(pair, '='); - if (!equals) - continue; - - *equals = '\0'; - attribute = pair; /* ex. DSN */ - value = equals + 1; /* ex. 'CEO co1' */ - - mylog("attribute = '%s', value = '%s'\n", attribute, value); - - if (!attribute || !value) - continue; - - /* Copy the appropriate value to the conninfo */ - copyCommonAttributes(ci, attribute, value); - - } - - free(our_connect_string); -} diff --git a/src/interfaces/odbc/windev/environ.c b/src/interfaces/odbc/windev/environ.c deleted file mode 100644 index 304d31d33e..0000000000 --- a/src/interfaces/odbc/windev/environ.c +++ /dev/null @@ -1,588 +0,0 @@ -/*------- - * Module: environ.c - * - * Description: This module contains routines related to - * the environment, such as storing connection handles, - * and returning errors. - * - * Classes: EnvironmentClass (Functions prefix: "EN_") - * - * API functions: SQLAllocEnv, SQLFreeEnv, SQLError - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "environ.h" - -#include "connection.h" -#include "dlg_specific.h" -#include "statement.h" -#include -#include -#include "pgapifunc.h" - -extern GLOBAL_VALUES globals; - -/* The one instance of the handles */ -ConnectionClass *conns[MAX_CONNECTIONS]; - - -RETCODE SQL_API -PGAPI_AllocEnv(HENV FAR * phenv) -{ - static char *func = "PGAPI_AllocEnv"; - - mylog("**** in PGAPI_AllocEnv ** \n"); - - /* - * Hack for systems on which none of the constructor-making techniques - * in psqlodbc.c work: if globals appears not to have been - * initialized, then cause it to be initialized. Since this should be - * the first function called in this shared library, doing it here - * should work. - */ - if (globals.socket_buffersize <= 0) - getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); - - *phenv = (HENV) EN_Constructor(); - if (!*phenv) - { - *phenv = SQL_NULL_HENV; - EN_log_error(func, "Error allocating environment", NULL); - return SQL_ERROR; - } - - mylog("** exit PGAPI_AllocEnv: phenv = %u **\n", *phenv); - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_FreeEnv(HENV henv) -{ - static char *func = "PGAPI_FreeEnv"; - EnvironmentClass *env = (EnvironmentClass *) henv; - - mylog("**** in PGAPI_FreeEnv: env = %u ** \n", env); - - if (env && EN_Destructor(env)) - { - mylog(" ok\n"); - return SQL_SUCCESS; - } - - mylog(" error\n"); - EN_log_error(func, "Error freeing environment", env); - return SQL_ERROR; -} - - -/* Returns the next SQL error information. */ -RETCODE SQL_API -PGAPI_Error( - HENV henv, - HDBC hdbc, - HSTMT hstmt, - UCHAR FAR * szSqlState, - SDWORD FAR * pfNativeError, - UCHAR FAR * szErrorMsg, - SWORD cbErrorMsgMax, - SWORD FAR * pcbErrorMsg) -{ - char *msg; - int status; - BOOL once_again = FALSE; - SWORD msglen; - - mylog("**** PGAPI_Error: henv=%u, hdbc=%u, hstmt=%u <%d>\n", henv, hdbc, hstmt, cbErrorMsgMax); - - if (cbErrorMsgMax < 0) - return SQL_ERROR; - if (SQL_NULL_HSTMT != hstmt) - { - /* CC: return an error of a hstmt */ - StatementClass *stmt = (StatementClass *) hstmt; - - if (SC_get_error(stmt, &status, &msg)) - { - mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg); - if (NULL == msg) - { - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - return SQL_NO_DATA_FOUND; - } - msglen = (SWORD) strlen(msg); - if (NULL != pcbErrorMsg) - { - *pcbErrorMsg = msglen; - if (cbErrorMsgMax == 0) - once_again = TRUE; - else if (msglen >= cbErrorMsgMax) - { - once_again = TRUE; - *pcbErrorMsg = cbErrorMsgMax - 1; - } - } - - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - strncpy_null(szErrorMsg, msg, cbErrorMsgMax); - - if (NULL != pfNativeError) - *pfNativeError = status; - - if (NULL != szSqlState) - - switch (status) - { - /* now determine the SQLSTATE to be returned */ - case STMT_ROW_VERSION_CHANGED: - strcpy(szSqlState, "01001"); - /* data truncated */ - break; - case STMT_TRUNCATED: - strcpy(szSqlState, "01004"); - /* data truncated */ - break; - case STMT_INFO_ONLY: - strcpy(szSqlState, "00000"); - /* just information that is returned, no error */ - break; - case STMT_BAD_ERROR: - strcpy(szSqlState, "08S01"); - /* communication link failure */ - break; - case STMT_CREATE_TABLE_ERROR: - strcpy(szSqlState, "S0001"); - /* table already exists */ - break; - case STMT_STATUS_ERROR: - case STMT_SEQUENCE_ERROR: - strcpy(szSqlState, "S1010"); - /* Function sequence error */ - break; - case STMT_NO_MEMORY_ERROR: - strcpy(szSqlState, "S1001"); - /* memory allocation failure */ - break; - case STMT_COLNUM_ERROR: - strcpy(szSqlState, "S1002"); - /* invalid column number */ - break; - case STMT_NO_STMTSTRING: - strcpy(szSqlState, "S1001"); - /* having no stmtstring is also a malloc problem */ - break; - case STMT_ERROR_TAKEN_FROM_BACKEND: - strcpy(szSqlState, "S1000"); - /* general error */ - break; - case STMT_INTERNAL_ERROR: - strcpy(szSqlState, "S1000"); - /* general error */ - break; - case STMT_ROW_OUT_OF_RANGE: - strcpy(szSqlState, "S1107"); - break; - - case STMT_OPERATION_CANCELLED: - strcpy(szSqlState, "S1008"); - break; - - case STMT_NOT_IMPLEMENTED_ERROR: - strcpy(szSqlState, "S1C00"); /* == 'driver not - * capable' */ - break; - case STMT_OPTION_OUT_OF_RANGE_ERROR: - strcpy(szSqlState, "S1092"); - break; - case STMT_BAD_PARAMETER_NUMBER_ERROR: - strcpy(szSqlState, "S1093"); - break; - case STMT_INVALID_COLUMN_NUMBER_ERROR: - strcpy(szSqlState, "S1002"); - break; - case STMT_RESTRICTED_DATA_TYPE_ERROR: - strcpy(szSqlState, "07006"); - break; - case STMT_INVALID_CURSOR_STATE_ERROR: - strcpy(szSqlState, "24000"); - break; - case STMT_OPTION_VALUE_CHANGED: - strcpy(szSqlState, "01S02"); - break; - case STMT_POS_BEFORE_RECORDSET: - strcpy(szSqlState, "01S06"); - break; - case STMT_INVALID_CURSOR_NAME: - strcpy(szSqlState, "34000"); - break; - case STMT_NO_CURSOR_NAME: - strcpy(szSqlState, "S1015"); - break; - case STMT_INVALID_ARGUMENT_NO: - strcpy(szSqlState, "S1009"); - /* invalid argument value */ - break; - 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_INVALID_OPTION_IDENTIFIER: - strcpy(szSqlState, "HY092"); - break; - case STMT_EXEC_ERROR: - default: - strcpy(szSqlState, "S1000"); - /* also a general error */ - break; - } - mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg); - } - else - { - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - mylog(" returning NO_DATA_FOUND\n"); - - return SQL_NO_DATA_FOUND; - } - - if (once_again) - { - int outlen; - - stmt->errornumber = status; - if (cbErrorMsgMax > 0) - outlen = *pcbErrorMsg; - else - outlen = 0; - if (!stmt->errormsg_malloced || !stmt->errormsg) - { - stmt->errormsg = malloc(msglen - outlen + 1); - stmt->errormsg_malloced = TRUE; - } - memmove(stmt->errormsg, msg + outlen, msglen - outlen + 1); - } - else if (stmt->errormsg_malloced) - SC_clear_error(stmt); - if (cbErrorMsgMax == 0) - return SQL_SUCCESS_WITH_INFO; - else - return SQL_SUCCESS; - } - else if (SQL_NULL_HDBC != hdbc) - { - ConnectionClass *conn = (ConnectionClass *) hdbc; - - mylog("calling CC_get_error\n"); - if (CC_get_error(conn, &status, &msg)) - { - mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg); - if (NULL == msg) - { - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - return SQL_NO_DATA_FOUND; - } - - msglen = strlen(msg); - if (NULL != pcbErrorMsg) - { - *pcbErrorMsg = msglen; - if (cbErrorMsgMax == 0) - once_again = TRUE; - else if (msglen >= cbErrorMsgMax) - *pcbErrorMsg = cbErrorMsgMax - 1; - } - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - strncpy_null(szErrorMsg, msg, cbErrorMsgMax); - if (NULL != pfNativeError) - *pfNativeError = status; - - if (NULL != szSqlState) - switch (status) - { - case STMT_OPTION_VALUE_CHANGED: - case CONN_OPTION_VALUE_CHANGED: - strcpy(szSqlState, "01S02"); - break; - case STMT_TRUNCATED: - case CONN_TRUNCATED: - strcpy(szSqlState, "01004"); - /* data truncated */ - break; - case CONN_INIREAD_ERROR: - strcpy(szSqlState, "IM002"); - /* data source not found */ - break; - case CONN_OPENDB_ERROR: - strcpy(szSqlState, "08001"); - /* unable to connect to data source */ - break; - case CONN_INVALID_AUTHENTICATION: - case CONN_AUTH_TYPE_UNSUPPORTED: - strcpy(szSqlState, "28000"); - break; - case CONN_STMT_ALLOC_ERROR: - strcpy(szSqlState, "S1001"); - /* memory allocation failure */ - break; - case CONN_IN_USE: - strcpy(szSqlState, "S1000"); - /* general error */ - break; - case CONN_UNSUPPORTED_OPTION: - strcpy(szSqlState, "IM001"); - /* driver does not support this function */ - case CONN_INVALID_ARGUMENT_NO: - strcpy(szSqlState, "S1009"); - /* invalid argument value */ - break; - case CONN_TRANSACT_IN_PROGRES: - strcpy(szSqlState, "S1010"); - - /* - * when the user tries to switch commit mode in a - * transaction - */ - /* -> function sequence error */ - break; - case CONN_NO_MEMORY_ERROR: - strcpy(szSqlState, "S1001"); - break; - case CONN_NOT_IMPLEMENTED_ERROR: - 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 - { - mylog("CC_Get_error returned nothing.\n"); - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - return SQL_NO_DATA_FOUND; - } - - if (once_again) - { - conn->errornumber = status; - return SQL_SUCCESS_WITH_INFO; - } - else - return SQL_SUCCESS; - } - else if (SQL_NULL_HENV != henv) - { - EnvironmentClass *env = (EnvironmentClass *) henv; - - if (EN_get_error(env, &status, &msg)) - { - mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg); - if (NULL == msg) - { - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - return SQL_NO_DATA_FOUND; - } - - if (NULL != pcbErrorMsg) - *pcbErrorMsg = (SWORD) strlen(msg); - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - strncpy_null(szErrorMsg, msg, cbErrorMsgMax); - if (NULL != pfNativeError) - *pfNativeError = status; - - if (szSqlState) - { - switch (status) - { - case ENV_ALLOC_ERROR: - /* memory allocation failure */ - strcpy(szSqlState, "S1001"); - break; - default: - strcpy(szSqlState, "S1000"); - /* general error */ - break; - } - } - } - else - { - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - return SQL_NO_DATA_FOUND; - } - - return SQL_SUCCESS; - } - - if (NULL != szSqlState) - strcpy(szSqlState, "00000"); - if (NULL != pcbErrorMsg) - *pcbErrorMsg = 0; - if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) - szErrorMsg[0] = '\0'; - - return SQL_NO_DATA_FOUND; -} - - -/* - * EnvironmentClass implementation - */ -EnvironmentClass * -EN_Constructor(void) -{ - EnvironmentClass *rv; - - rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass)); - if (rv) - { - rv->errormsg = 0; - rv->errornumber = 0; - } - - return rv; -} - - -char -EN_Destructor(EnvironmentClass *self) -{ - int lf; - char rv = 1; - - 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++) - { - if (conns[lf] && conns[lf]->henv == self) - rv = rv && CC_Destructor(conns[lf]); - } - free(self); - - mylog("exit EN_Destructor: rv = %d\n", rv); -#ifdef _MEMORY_DEBUG_ - debug_memory_inouecheck(); -#endif /* _MEMORY_DEBUG_ */ - return rv; -} - - -char -EN_get_error(EnvironmentClass *self, int *number, char **message) -{ - if (self && self->errormsg && self->errornumber) - { - *message = self->errormsg; - *number = self->errornumber; - self->errormsg = 0; - self->errornumber = 0; - return 1; - } - else - return 0; -} - - -char -EN_add_connection(EnvironmentClass *self, ConnectionClass *conn) -{ - int i; - - mylog("EN_add_connection: self = %u, conn = %u\n", self, conn); - - for (i = 0; i < MAX_CONNECTIONS; i++) - { - if (!conns[i]) - { - conn->henv = self; - conns[i] = conn; - - mylog(" added at i =%d, conn->henv = %u, conns[i]->henv = %u\n", i, conn->henv, conns[i]->henv); - - return TRUE; - } - } - - return FALSE; -} - - -char -EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn) -{ - int i; - - for (i = 0; i < MAX_CONNECTIONS; i++) - if (conns[i] == conn && conns[i]->status != CONN_EXECUTING) - { - conns[i] = NULL; - return TRUE; - } - - return FALSE; -} - - -void -EN_log_error(char *func, char *desc, EnvironmentClass *self) -{ - if (self) - qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg); - else - qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc); -} diff --git a/src/interfaces/odbc/windev/environ.h b/src/interfaces/odbc/windev/environ.h deleted file mode 100644 index 7b463b3e74..0000000000 --- a/src/interfaces/odbc/windev/environ.h +++ /dev/null @@ -1,31 +0,0 @@ -/* File: environ.h - * - * Description: See "environ.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __ENVIRON_H__ -#define __ENVIRON_H__ - -#include "psqlodbc.h" - -#define ENV_ALLOC_ERROR 1 - -/********** Environment Handle *************/ -struct EnvironmentClass_ -{ - char *errormsg; - int errornumber; -}; - -/* Environment prototypes */ -EnvironmentClass *EN_Constructor(void); -char EN_Destructor(EnvironmentClass *self); -char EN_get_error(EnvironmentClass *self, int *number, char **message); -char EN_add_connection(EnvironmentClass *self, ConnectionClass *conn); -char EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn); -void EN_log_error(char *func, char *desc, EnvironmentClass *self); - -#endif diff --git a/src/interfaces/odbc/windev/execute.c b/src/interfaces/odbc/windev/execute.c deleted file mode 100644 index 5a693b7163..0000000000 --- a/src/interfaces/odbc/windev/execute.c +++ /dev/null @@ -1,955 +0,0 @@ -/*------- - * Module: execute.c - * - * Description: This module contains routines related to - * preparing and executing an SQL statement. - * - * Classes: n/a - * - * API functions: SQLPrepare, SQLExecute, SQLExecDirect, SQLTransact, - * SQLCancel, SQLNativeSql, SQLParamData, SQLPutData - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "psqlodbc.h" - -#include -#include - -#include "connection.h" -#include "statement.h" -#include "qresult.h" -#include "convert.h" -#include "bind.h" -#include "pgtypes.h" -#include "lobj.h" -#include "pgapifunc.h" - -/*extern GLOBAL_VALUES globals;*/ - - -/* Perform a Prepare on the SQL statement */ -RETCODE SQL_API -PGAPI_Prepare(HSTMT hstmt, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStr) -{ - static char *func = "PGAPI_Prepare"; - StatementClass *self = (StatementClass *) hstmt; - - mylog("%s: entering...\n", func); - - if (!self) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - /* - * According to the ODBC specs it is valid to call SQLPrepare mulitple - * times. In that case, the bound SQL statement is replaced by the new - * one - */ - - switch (self->status) - { - case STMT_PREMATURE: - mylog("**** PGAPI_Prepare: STMT_PREMATURE, recycle\n"); - SC_recycle_statement(self); /* recycle the statement, but do - * not remove parameter bindings */ - break; - - case STMT_FINISHED: - mylog("**** PGAPI_Prepare: STMT_FINISHED, recycle\n"); - SC_recycle_statement(self); /* recycle the statement, but do - * not remove parameter bindings */ - break; - - case STMT_ALLOCATED: - mylog("**** PGAPI_Prepare: STMT_ALLOCATED, copy\n"); - self->status = STMT_READY; - break; - - case STMT_READY: - mylog("**** PGAPI_Prepare: STMT_READY, change SQL\n"); - break; - - case STMT_EXECUTING: - mylog("**** PGAPI_Prepare: STMT_EXECUTING, error!\n"); - - self->errornumber = STMT_SEQUENCE_ERROR; - self->errormsg = "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed"; - SC_log_error(func, "", self); - - return SQL_ERROR; - - default: - self->errornumber = STMT_INTERNAL_ERROR; - self->errormsg = "An Internal Error has occured -- Unknown statement status."; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - if (self->statement) - free(self->statement); - - self->statement = make_string(szSqlStr, cbSqlStr, NULL); - if (!self->statement) - { - self->errornumber = STMT_NO_MEMORY_ERROR; - self->errormsg = "No memory available to store statement"; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - self->prepare = TRUE; - self->statement_type = statement_type(self->statement); - - /* Check if connection is onlyread (only selects are allowed) */ - if (CC_is_onlyread(self->hdbc) && STMT_UPDATE(self)) - { - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "Connection is readonly, only select statements are allowed."; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - return SQL_SUCCESS; -} - - -/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */ -RETCODE SQL_API -PGAPI_ExecDirect( - HSTMT hstmt, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStr) -{ - StatementClass *stmt = (StatementClass *) hstmt; - RETCODE result; - static char *func = "PGAPI_ExecDirect"; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - 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) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "No memory available to store statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - mylog("**** %s: hstmt=%u, statement='%s'\n", func, hstmt, stmt->statement); - - 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; - - stmt->statement_type = statement_type(stmt->statement); - - /* Check if connection is onlyread (only selects are allowed) */ - if (CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt)) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Connection is readonly, only select statements are allowed."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - mylog("%s: calling PGAPI_Execute...\n", func); - - result = PGAPI_Execute(hstmt); - - mylog("%s: returned %hd from PGAPI_Execute\n", func, result); - return result; -} - - -/* Execute a prepared SQL statement */ -RETCODE SQL_API -PGAPI_Execute( - HSTMT hstmt) -{ - static char *func = "PGAPI_Execute"; - StatementClass *stmt = (StatementClass *) hstmt; - ConnectionClass *conn; - int i, - retval; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func); - return SQL_INVALID_HANDLE; - } - - /* - * If the statement is premature, it means we already executed it from - * an SQLPrepare/SQLDescribeCol type of scenario. So just return - * success. - */ - if (stmt->prepare && stmt->status == STMT_PREMATURE) - { - if (stmt->inaccurate_result) - SC_recycle_statement(stmt); - else - { - stmt->status = STMT_FINISHED; - if (stmt->errormsg == NULL) - { - mylog("%s: premature statement but return SQL_SUCCESS\n", func); - return SQL_SUCCESS; - } - else - { - SC_log_error(func, "", stmt); - mylog("%s: premature statement so return SQL_ERROR\n", func); - return SQL_ERROR; - } - } - } - - mylog("%s: clear errors...\n", func); - - SC_clear_error(stmt); - - conn = SC_get_conn(stmt); - if (conn->status == CONN_EXECUTING) - { - stmt->errormsg = "Connection is already in use."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - mylog("%s: problem with connection\n", func); - return SQL_ERROR; - } - - if (!stmt->statement) - { - stmt->errornumber = STMT_NO_STMTSTRING; - stmt->errormsg = "This handle does not have a SQL statement stored in it"; - SC_log_error(func, "", stmt); - mylog("%s: problem with handle\n", func); - return SQL_ERROR; - } - - /* - * If SQLExecute is being called again, recycle the statement. Note - * this should have been done by the application in a call to - * SQLFreeStmt(SQL_CLOSE) or SQLCancel. - */ - if (stmt->status == STMT_FINISHED) - { - mylog("%s: recycling statement (should have been done by app)...\n", func); - SC_recycle_statement(stmt); - } - - /* Check if the statement is in the correct state */ - 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); - mylog("%s: problem with statement\n", func); - return SQL_ERROR; - } - - /* - * Check if statement has any data-at-execute parameters when it is - * not in SC_pre_execute. - */ - if (!stmt->pre_executing) - { - /* - * The bound parameters could have possibly changed since the last - * execute of this statement? Therefore check for params and - * re-copy. - */ - stmt->data_at_exec = -1; - for (i = 0; i < stmt->parameters_allocated; i++) - { - Int4 *pcVal = stmt->parameters[i].used; - - if (pcVal && (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)) - stmt->parameters[i].data_at_exec = TRUE; - else - stmt->parameters[i].data_at_exec = FALSE; - /* Check for data at execution parameters */ - if (stmt->parameters[i].data_at_exec == TRUE) - { - if (stmt->data_at_exec < 0) - stmt->data_at_exec = 1; - else - stmt->data_at_exec++; - } - } - - /* - * If there are some data at execution parameters, return need - * data - */ - - /* - * SQLParamData and SQLPutData will be used to send params and - * execute the statement. - */ - if (stmt->data_at_exec > 0) - return SQL_NEED_DATA; - - } - - - mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement); - - /* Create the statement with parameters substituted. */ - retval = copy_statement_with_parameters(stmt); - if (retval != SQL_SUCCESS) - /* error msg passed from above */ - return retval; - - mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params); - - /* - * Get the field info for the prepared query using dummy backward - * fetch. - */ - if (stmt->inaccurate_result && conn->connInfo.disallow_premature) - { - if (SC_is_pre_executable(stmt)) - { - BOOL in_trans = CC_is_in_trans(conn); - BOOL issued_begin = FALSE, - begin_included = FALSE; - QResultClass *res; - - if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0) - begin_included = TRUE; - else if (!in_trans) - { - res = CC_send_query(conn, "BEGIN", NULL); - if (res && !QR_aborted(res)) - issued_begin = TRUE; - if (res) - QR_Destructor(res); - if (!issued_begin) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Handle prepare error"; - return SQL_ERROR; - } - } - /* we are now in a transaction */ - CC_set_in_trans(conn); - stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL); - if (!res || QR_aborted(res)) - { - CC_abort(conn); - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Handle prepare error"; - return SQL_ERROR; - } - else - { - if (CC_is_in_autocommit(conn)) - { - if (issued_begin) - { - res = CC_send_query(conn, "COMMIT", NULL); - CC_set_no_trans(conn); - if (res) - QR_Destructor(res); - } - else if (!in_trans && begin_included) - CC_set_no_trans(conn); - } - stmt->status = STMT_FINISHED; - return SQL_SUCCESS; - } - } - else - return SQL_SUCCESS; - } - - return SC_execute(stmt); -} - - -RETCODE SQL_API -PGAPI_Transact( - HENV henv, - HDBC hdbc, - UWORD fType) -{ - static char *func = "PGAPI_Transact"; - extern ConnectionClass *conns[]; - ConnectionClass *conn; - QResultClass *res; - char ok, - *stmt_string; - int lf; - - mylog("entering %s: hdbc=%u, henv=%u\n", func, hdbc, henv); - - if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - /* - * If hdbc is null and henv is valid, it means transact all - * connections on that henv. - */ - if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV) - { - for (lf = 0; lf < MAX_CONNECTIONS; lf++) - { - conn = conns[lf]; - - if (conn && conn->henv == henv) - if (PGAPI_Transact(henv, (HDBC) conn, fType) != SQL_SUCCESS) - return SQL_ERROR; - } - return SQL_SUCCESS; - } - - 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; - conn->errormsg = "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter"; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - /* If manual commit and in transaction, then proceed. */ - if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) - { - mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string); - - res = CC_send_query(conn, stmt_string, NULL); - CC_set_no_trans(conn); - - if (!res) - { - /* error msg will be in the connection */ - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - ok = QR_command_successful(res); - QR_Destructor(res); - - if (!ok) - { - CC_log_error(func, "", conn); - return SQL_ERROR; - } - } - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_Cancel( - HSTMT hstmt) /* Statement to cancel. */ -{ - static char *func = "PGAPI_Cancel"; - StatementClass *stmt = (StatementClass *) hstmt; - RETCODE result; - ConnInfo *ci; - -#ifdef WIN32 - HMODULE hmodule; - FARPROC addr; -#endif - - mylog("%s: entering...\n", func); - - /* Check if this can handle canceling in the middle of a SQLPutData? */ - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - - /* - * Not in the middle of SQLParamData/SQLPutData so cancel like a - * close. - */ - 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 - * manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as - * many applications depend on this behavior. So, this brute - * force method calls the driver manager's function on behalf of - * the application. - */ - -#ifdef WIN32 - if (ci->drivers.cancel_as_freestmt) - { - hmodule = GetModuleHandle("ODBC32"); - addr = GetProcAddress(hmodule, "SQLFreeStmt"); - result = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE); - } - else - result = PGAPI_FreeStmt(hstmt, SQL_CLOSE); -#else - result = PGAPI_FreeStmt(hstmt, SQL_CLOSE); -#endif - - mylog("PGAPI_Cancel: PGAPI_FreeStmt returned %d\n", result); - - SC_clear_error(hstmt); - return SQL_SUCCESS; - } - - /* In the middle of SQLParamData/SQLPutData, so cancel that. */ - - /* - * Note, any previous data-at-exec buffers will be freed in the - * recycle - */ - /* if they call SQLExecDirect or SQLExecute again. */ - - stmt->data_at_exec = -1; - stmt->current_exec_param = -1; - 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 -PGAPI_NativeSql( - HDBC hdbc, - UCHAR FAR * szSqlStrIn, - SDWORD cbSqlStrIn, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStrMax, - SDWORD FAR * pcbSqlStr) -{ - static char *func = "PGAPI_NativeSql"; - int len = 0; - char *ptr; - ConnectionClass *conn = (ConnectionClass *) hdbc; - RETCODE result; - - mylog("%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn); - - ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL); - if (!ptr) - { - conn->errornumber = CONN_NO_MEMORY_ERROR; - conn->errormsg = "No memory available to store native sql string"; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - result = SQL_SUCCESS; - len = strlen(ptr); - - if (szSqlStr) - { - strncpy_null(szSqlStr, ptr, cbSqlStrMax); - - if (len >= cbSqlStrMax) - { - result = SQL_SUCCESS_WITH_INFO; - conn->errornumber = STMT_TRUNCATED; - conn->errormsg = "The buffer was too small for the NativeSQL."; - } - } - - if (pcbSqlStr) - *pcbSqlStr = len; - - if (cbSqlStrIn) - free(ptr); - - return result; -} - - -/* - * Supplies parameter data at execution time. - * Used in conjuction with SQLPutData. - */ -RETCODE SQL_API -PGAPI_ParamData( - HSTMT hstmt, - PTR FAR * prgbValue) -{ - static char *func = "PGAPI_ParamData"; - StatementClass *stmt = (StatementClass *) hstmt; - int i, - retval; - ConnInfo *ci; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - - mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated); - - if (stmt->data_at_exec < 0) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "No execution-time parameters for this statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->data_at_exec > stmt->parameters_allocated) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "Too many execution-time parameters were present"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* close the large object */ - if (stmt->lobj_fd >= 0) - { - lo_close(stmt->hdbc, stmt->lobj_fd); - - /* commit transaction if needed */ - if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) - { - QResultClass *res; - char ok; - - res = CC_send_query(stmt->hdbc, "COMMIT", NULL); - if (!res) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - ok = QR_command_successful(res); - CC_set_no_trans(stmt->hdbc); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - stmt->lobj_fd = -1; - } - - /* Done, now copy the params and then execute the statement */ - if (stmt->data_at_exec == 0) - { - retval = copy_statement_with_parameters(stmt); - if (retval != SQL_SUCCESS) - return retval; - - stmt->current_exec_param = -1; - - return SC_execute(stmt); - } - - /* - * Set beginning param; if first time SQLParamData is called , start - * at 0. Otherwise, start at the last parameter + 1. - */ - i = stmt->current_exec_param >= 0 ? stmt->current_exec_param + 1 : 0; - - /* At least 1 data at execution parameter, so Fill in the token value */ - for (; i < stmt->parameters_allocated; i++) - { - if (stmt->parameters[i].data_at_exec == TRUE) - { - stmt->data_at_exec--; - stmt->current_exec_param = i; - stmt->put_data = FALSE; - *prgbValue = stmt->parameters[i].buffer; /* token */ - break; - } - } - - return SQL_NEED_DATA; -} - - -/* - * Supplies parameter data at execution time. - * Used in conjunction with SQLParamData. - */ -RETCODE SQL_API -PGAPI_PutData( - HSTMT hstmt, - PTR rgbValue, - SDWORD cbValue) -{ - static char *func = "PGAPI_PutData"; - StatementClass *stmt = (StatementClass *) hstmt; - int old_pos, - retval; - ParameterInfoClass *current_param; - char *buffer; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - if (stmt->current_exec_param < 0) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "Previous call was not SQLPutData or SQLParamData"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - current_param = &(stmt->parameters[stmt->current_exec_param]); - - if (!stmt->put_data) - { /* first call */ - mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue); - - stmt->put_data = TRUE; - - current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD)); - if (!current_param->EXEC_used) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (1)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - *current_param->EXEC_used = cbValue; - - 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)) - { - QResultClass *res; - char ok; - - res = CC_send_query(stmt->hdbc, "BEGIN", NULL); - if (!res) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - CC_set_in_trans(stmt->hdbc); - } - - /* store the oid */ - current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); - if (current_param->lobj_oid == 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt create large object."; - SC_log_error(func, "", stmt); - 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 */ - stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE); - if (stmt->lobj_fd < 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt open large object for writing."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); - mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval); - } - else - { - /* for handling fields */ - if (cbValue == SQL_NTS) - { - current_param->EXEC_buffer = strdup(rgbValue); - if (!current_param->EXEC_buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (2)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - else - { - Int2 ctype = current_param->CType; - - if (ctype == SQL_C_DEFAULT) - ctype = sqltype_to_default_ctype(current_param->SQLType); - if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY) - { - current_param->EXEC_buffer = malloc(cbValue + 1); - if (!current_param->EXEC_buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (2)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - memcpy(current_param->EXEC_buffer, rgbValue, cbValue); - current_param->EXEC_buffer[cbValue] = '\0'; - } - else - { - Int4 used = ctype_length(ctype); - - current_param->EXEC_buffer = malloc(used); - if (!current_param->EXEC_buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (2)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - memcpy(current_param->EXEC_buffer, rgbValue, used); - } - } - } - } - else - { - /* calling SQLPutData more than once */ - mylog("PGAPI_PutData: (>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) - { - buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1); - if (!buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (3)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - strcat(buffer, rgbValue); - - mylog(" cbValue = SQL_NTS: strlen(buffer) = %d\n", strlen(buffer)); - - *current_param->EXEC_used = cbValue; - - /* 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; - - mylog(" cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used); - - /* dont lose the old pointer in case out of memory */ - buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1); - if (!buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (3)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - memcpy(&buffer[old_pos], rgbValue, cbValue); - buffer[*current_param->EXEC_used] = '\0'; - - /* 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; -} diff --git a/src/interfaces/odbc/windev/info.c b/src/interfaces/odbc/windev/info.c deleted file mode 100644 index c77b3c5e89..0000000000 --- a/src/interfaces/odbc/windev/info.c +++ /dev/null @@ -1,3714 +0,0 @@ -/*-------- - * Module: info.c - * - * Description: This module contains routines related to - * ODBC informational functions. - * - * Classes: n/a - * - * API functions: SQLGetInfo, SQLGetTypeInfo, SQLGetFunctions, - * SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns, - * SQLPrimaryKeys, SQLForeignKeys, - * SQLProcedureColumns(NI), SQLProcedures(NI), - * SQLTablePrivileges(NI), SQLColumnPrivileges(NI) - * - * Comments: See "notice.txt" for copyright and license information. - *-------- - */ - -#include "psqlodbc.h" - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include "tuple.h" -#include "pgtypes.h" - -#include "environ.h" -#include "connection.h" -#include "statement.h" -#include "qresult.h" -#include "bind.h" -#include "misc.h" -#include "pgtypes.h" -#include "pgapifunc.h" - - -/* Trigger related stuff for SQLForeign Keys */ -#define TRIGGER_SHIFT 3 -#define TRIGGER_MASK 0x03 -#define TRIGGER_DELETE 0x01 -#define TRIGGER_UPDATE 0x02 - - -/* extern GLOBAL_VALUES globals; */ - - - -RETCODE SQL_API -PGAPI_GetInfo( - HDBC hdbc, - UWORD fInfoType, - PTR rgbInfoValue, - SWORD cbInfoValueMax, - SWORD FAR * pcbInfoValue) -{ - static char *func = "PGAPI_GetInfo"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - ConnInfo *ci; - char *p = NULL, - tmp[MAX_INFO_STRING]; - int len = 0, - value = 0; - RETCODE result; - - mylog("%s: entering...fInfoType=%d\n", func, fInfoType); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - ci = &(conn->connInfo); - - switch (fInfoType) - { - case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */ - p = "N"; - break; - - case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */ - p = "N"; - break; - - case SQL_ACTIVE_CONNECTIONS: /* ODBC 1.0 */ - len = 2; - value = MAX_CONNECTIONS; - break; - - case SQL_ACTIVE_STATEMENTS: /* ODBC 1.0 */ - len = 2; - value = 0; - break; - - case SQL_ALTER_TABLE: /* ODBC 2.0 */ - len = 4; - value = SQL_AT_ADD_COLUMN; - break; - - case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */ - /* very simple bookmark support */ - len = 4; - value = ci->drivers.use_declarefetch ? 0 : (SQL_BP_SCROLL); - break; - - case SQL_COLUMN_ALIAS: /* ODBC 2.0 */ - p = "N"; - break; - - case SQL_CONCAT_NULL_BEHAVIOR: /* ODBC 1.0 */ - len = 2; - value = SQL_CB_NON_NULL; - break; - - case SQL_CONVERT_BIGINT: - case SQL_CONVERT_BINARY: - case SQL_CONVERT_BIT: - case SQL_CONVERT_CHAR: - case SQL_CONVERT_DATE: - case SQL_CONVERT_DECIMAL: - case SQL_CONVERT_DOUBLE: - case SQL_CONVERT_FLOAT: - case SQL_CONVERT_INTEGER: - case SQL_CONVERT_LONGVARBINARY: - case SQL_CONVERT_LONGVARCHAR: - case SQL_CONVERT_NUMERIC: - case SQL_CONVERT_REAL: - case SQL_CONVERT_SMALLINT: - case SQL_CONVERT_TIME: - case SQL_CONVERT_TIMESTAMP: - case SQL_CONVERT_TINYINT: - case SQL_CONVERT_VARBINARY: - case SQL_CONVERT_VARCHAR: /* ODBC 1.0 */ - len = 4; - value = fInfoType; - break; - - case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */ - len = 4; - value = 0; - break; - - case SQL_CORRELATION_NAME: /* ODBC 1.0 */ - - /* - * Saying no correlation name makes Query not work right. - * value = SQL_CN_NONE; - */ - len = 2; - value = SQL_CN_ANY; - break; - - case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */ - len = 2; - value = SQL_CB_CLOSE; - if (ci->updatable_cursors) - if (!ci->drivers.use_declarefetch) - value = SQL_CB_PRESERVE; - break; - - case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */ - len = 2; - value = SQL_CB_CLOSE; - if (ci->updatable_cursors) - if (!ci->drivers.use_declarefetch) - value = SQL_CB_PRESERVE; - break; - - case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */ - p = CC_get_DSN(conn); - break; - - case SQL_DATA_SOURCE_READ_ONLY: /* ODBC 1.0 */ - p = CC_is_onlyread(conn) ? "Y" : "N"; - 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); - */ - p = ""; - break; - - case SQL_DBMS_NAME: /* ODBC 1.0 */ - p = DBMS_NAME; - break; - - case SQL_DBMS_VER: /* ODBC 1.0 */ - - /* - * The ODBC spec wants ##.##.#### ...whatever... so prepend - * the driver - */ - /* version number to the dbms version string */ - sprintf(tmp, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version); - p = tmp; - break; - - case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */ - len = 4; - value = SQL_TXN_READ_COMMITTED; /* SQL_TXN_SERIALIZABLE; */ - break; - - case SQL_DRIVER_NAME: /* ODBC 1.0 */ - p = DRIVER_FILE_NAME; - break; - - case SQL_DRIVER_ODBC_VER: - p = DRIVER_ODBC_VER; - break; - - case SQL_DRIVER_VER: /* ODBC 1.0 */ - p = POSTGRESDRIVERVERSION; - break; - - case SQL_EXPRESSIONS_IN_ORDERBY: /* ODBC 1.0 */ - p = "N"; - break; - - case SQL_FETCH_DIRECTION: /* ODBC 1.0 */ - len = 4; - value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT | - SQL_FD_FETCH_FIRST | - SQL_FD_FETCH_LAST | - SQL_FD_FETCH_PRIOR | - SQL_FD_FETCH_ABSOLUTE | - SQL_FD_FETCH_RELATIVE | - SQL_FD_FETCH_BOOKMARK); - break; - - case SQL_FILE_USAGE: /* ODBC 2.0 */ - len = 2; - value = SQL_FILE_NOT_SUPPORTED; - break; - - case SQL_GETDATA_EXTENSIONS: /* ODBC 2.0 */ - len = 4; - value = (SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND | SQL_GD_BLOCK); - break; - - case SQL_GROUP_BY: /* ODBC 2.0 */ - len = 2; - value = SQL_GB_GROUP_BY_EQUALS_SELECT; - break; - - case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */ - - /* - * are identifiers case-sensitive (yes, but only when quoted. - * If not quoted, they default to lowercase) - */ - len = 2; - value = SQL_IC_LOWER; - break; - - case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */ - /* the character used to quote "identifiers" */ - p = PG_VERSION_LE(conn, 6.2) ? " " : "\""; - break; - - case SQL_KEYWORDS: /* ODBC 2.0 */ - p = ""; - 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 - */ - p = "N"; - break; - - case SQL_LOCK_TYPES: /* ODBC 2.0 */ - len = 4; - value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE; - break; - - case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_MAX_CHAR_LITERAL_LEN: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */ - len = 2; - value = MAX_COLUMN_LEN; - break; - - case SQL_MAX_COLUMNS_IN_GROUP_BY: /* ODBC 2.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_COLUMNS_IN_INDEX: /* ODBC 2.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_COLUMNS_IN_ORDER_BY: /* ODBC 2.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_COLUMNS_IN_SELECT: /* ODBC 2.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_COLUMNS_IN_TABLE: /* ODBC 2.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */ - len = 2; - value = MAX_CURSOR_LEN; - break; - - case SQL_MAX_INDEX_SIZE: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_MAX_OWNER_NAME_LEN: /* ODBC 1.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_PROCEDURE_NAME_LEN: /* ODBC 1.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_QUALIFIER_NAME_LEN: /* ODBC 1.0 */ - len = 2; - value = 0; - break; - - 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, - * but not longvarbinary. - */ - p = "Y"; - break; - - case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */ - /* maybe this should be 0? */ - len = 4; - value = CC_get_max_query_len(conn); - break; - - case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */ - len = 2; - value = MAX_TABLE_LEN; - break; - - case SQL_MAX_TABLES_IN_SELECT: /* ODBC 2.0 */ - len = 2; - value = 0; - break; - - case SQL_MAX_USER_NAME_LEN: - len = 2; - value = 0; - break; - - case SQL_MULT_RESULT_SETS: /* ODBC 1.0 */ - /* Don't support multiple result sets but say yes anyway? */ - p = "Y"; - break; - - case SQL_MULTIPLE_ACTIVE_TXN: /* ODBC 1.0 */ - p = "Y"; - 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"; - break; - - case SQL_NON_NULLABLE_COLUMNS: /* ODBC 1.0 */ - len = 2; - value = SQL_NNC_NON_NULL; - break; - - case SQL_NULL_COLLATION: /* ODBC 2.0 */ - /* where are nulls sorted? */ - len = 2; - value = SQL_NC_END; - break; - - case SQL_NUMERIC_FUNCTIONS: /* ODBC 1.0 */ - len = 4; - value = 0; - break; - - case SQL_ODBC_API_CONFORMANCE: /* ODBC 1.0 */ - len = 2; - value = SQL_OAC_LEVEL1; - break; - - case SQL_ODBC_SAG_CLI_CONFORMANCE: /* ODBC 1.0 */ - len = 2; - value = SQL_OSCC_NOT_COMPLIANT; - break; - - case SQL_ODBC_SQL_CONFORMANCE: /* ODBC 1.0 */ - len = 2; - value = SQL_OSC_CORE; - break; - - case SQL_ODBC_SQL_OPT_IEF: /* ODBC 1.0 */ - p = "N"; - break; - - 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 | - SQL_OJ_NESTED | - SQL_OJ_NOT_ORDERED | - SQL_OJ_INNER | - SQL_OJ_ALL_COMPARISON_OPS); - } - else - /* OJs not in <7.1 */ - value = 0; - break; - - case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */ - p = (PG_VERSION_LE(conn, 6.3)) ? "Y" : "N"; - break; - - 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 */ - p = "owner"; - break; - - case SQL_OWNER_USAGE: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_POS_OPERATIONS: /* ODBC 2.0 */ - len = 4; - value = ci->drivers.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH); - if (ci->updatable_cursors) - value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD); - break; - - case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */ - len = 4; - value = ci->drivers.lie ? (SQL_PS_POSITIONED_DELETE | - SQL_PS_POSITIONED_UPDATE | - SQL_PS_SELECT_FOR_UPDATE) : 0; - break; - - case SQL_PROCEDURE_TERM: /* ODBC 1.0 */ - p = "procedure"; - break; - - case SQL_PROCEDURES: /* ODBC 1.0 */ - p = "Y"; - break; - - case SQL_QUALIFIER_LOCATION: /* ODBC 2.0 */ - len = 2; - value = SQL_QL_START; - break; - - case SQL_QUALIFIER_NAME_SEPARATOR: /* ODBC 1.0 */ - p = ""; - break; - - case SQL_QUALIFIER_TERM: /* ODBC 1.0 */ - p = ""; - break; - - case SQL_QUALIFIER_USAGE: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_QUOTED_IDENTIFIER_CASE: /* ODBC 2.0 */ - /* are "quoted" identifiers case-sensitive? YES! */ - len = 2; - value = SQL_IC_SENSITIVE; - 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 - */ - p = (ci->drivers.lie || ci->updatable_cursors) ? "Y" : "N"; - break; - - case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */ - len = 4; - value = ci->drivers.lie ? (SQL_SCCO_READ_ONLY | - SQL_SCCO_LOCK | - SQL_SCCO_OPT_ROWVER | - SQL_SCCO_OPT_VALUES) : - (SQL_SCCO_READ_ONLY); - if (ci->updatable_cursors) - value |= SQL_SCCO_OPT_ROWVER; - break; - - case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */ - len = 4; - value = ci->drivers.lie ? (SQL_SO_FORWARD_ONLY | - SQL_SO_STATIC | - SQL_SO_KEYSET_DRIVEN | - SQL_SO_DYNAMIC | - SQL_SO_MIXED) - : (ci->drivers.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC)); - if (ci->updatable_cursors) - value |= 0; /* SQL_SO_KEYSET_DRIVEN in the furure */ - break; - - case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */ - p = ""; - break; - - case SQL_SERVER_NAME: /* ODBC 1.0 */ - p = CC_get_server(conn); - break; - - case SQL_SPECIAL_CHARACTERS: /* ODBC 2.0 */ - p = "_"; - break; - - case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */ - len = 4; - value = ci->drivers.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0; - if (ci->updatable_cursors) - value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES); - break; - - case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */ - len = 4; - value = (SQL_FN_STR_CONCAT | - SQL_FN_STR_LCASE | - SQL_FN_STR_LENGTH | - SQL_FN_STR_LOCATE | - SQL_FN_STR_LTRIM | - SQL_FN_STR_RTRIM | - SQL_FN_STR_SUBSTRING | - SQL_FN_STR_UCASE); - break; - - case SQL_SUBQUERIES: /* ODBC 2.0 */ - /* postgres 6.3 supports subqueries */ - len = 4; - value = (SQL_SQ_QUANTIFIED | - SQL_SQ_IN | - SQL_SQ_EXISTS | - SQL_SQ_COMPARISON); - break; - - case SQL_SYSTEM_FUNCTIONS: /* ODBC 1.0 */ - len = 4; - value = 0; - break; - - case SQL_TABLE_TERM: /* ODBC 1.0 */ - p = "table"; - break; - - case SQL_TIMEDATE_ADD_INTERVALS: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_TIMEDATE_DIFF_INTERVALS: /* ODBC 2.0 */ - len = 4; - value = 0; - break; - - case SQL_TIMEDATE_FUNCTIONS: /* ODBC 1.0 */ - len = 4; - value = (SQL_FN_TD_NOW); - break; - - case SQL_TXN_CAPABLE: /* ODBC 1.0 */ - - /* - * Postgres can deal with create or drop table statements in a - * transaction - */ - len = 2; - value = SQL_TC_ALL; - break; - - case SQL_TXN_ISOLATION_OPTION: /* ODBC 1.0 */ - len = 4; - value = SQL_TXN_READ_COMMITTED; /* SQL_TXN_SERIALIZABLE; */ - break; - - case SQL_UNION: /* ODBC 2.0 */ - /* unions with all supported in postgres 6.3 */ - len = 4; - value = (SQL_U_UNION | SQL_U_UNION_ALL); - break; - - case SQL_USER_NAME: /* ODBC 1.0 */ - p = CC_get_username(conn); - break; - - default: - /* unrecognized key */ - conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo."; - conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - result = SQL_SUCCESS; - - mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "", len, value, cbInfoValueMax); - - /* - * NOTE, that if rgbInfoValue is NULL, then no warnings or errors - * should result and just pcbInfoValue is returned, which indicates - * what length would be required if a real buffer had been passed in. - */ - if (p) - { - /* char/binary data */ - len = strlen(p); - - if (rgbInfoValue) - { - strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax); - - if (len >= cbInfoValueMax) - { - result = SQL_SUCCESS_WITH_INFO; - conn->errornumber = STMT_TRUNCATED; - conn->errormsg = "The buffer was too small for tthe InfoValue."; - } - } - } - else - { - /* numeric data */ - if (rgbInfoValue) - { - if (len == 2) - *((WORD *) rgbInfoValue) = (WORD) value; - else if (len == 4) - *((DWORD *) rgbInfoValue) = (DWORD) value; - } - } - - if (pcbInfoValue) - *pcbInfoValue = len; - - return result; -} - - -RETCODE SQL_API -PGAPI_GetTypeInfo( - HSTMT hstmt, - SWORD fSqlType) -{ - static char *func = "PGAPI_GetTypeInfo"; - StatementClass *stmt = (StatementClass *) hstmt; - TupleNode *row; - int i; - - /* Int4 type; */ - Int4 pgType; - Int2 sqlType; - - mylog("%s: entering...fSqlType = %d\n", func, fSqlType); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - stmt->manual_result = TRUE; - stmt->result = QR_Constructor(); - if (!stmt->result) - { - SC_log_error(func, "Error creating result.", stmt); - return SQL_ERROR; - } - - extend_bindings(stmt, 15); - - QR_set_num_fields(stmt->result, 15); - QR_set_field_info(stmt->result, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "DATA_TYPE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 2, "PRECISION", PG_TYPE_INT4, 4); - QR_set_field_info(stmt->result, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 6, "NULLABLE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 8, "SEARCHABLE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 10, "MONEY", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2); - - for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i]) - { - pgType = sqltype_to_pgtype(stmt, sqlType); - - if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + (15 - 1) *sizeof(TupleField)); - - /* These values can't be NULL */ - set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType)); - set_tuplefield_int2(&row->tuple[1], (Int2) sqlType); - set_tuplefield_int2(&row->tuple[6], pgtype_nullable(stmt, pgType)); - set_tuplefield_int2(&row->tuple[7], pgtype_case_sensitive(stmt, pgType)); - set_tuplefield_int2(&row->tuple[8], pgtype_searchable(stmt, pgType)); - set_tuplefield_int2(&row->tuple[10], pgtype_money(stmt, pgType)); - - /* - * Localized data-source dependent data type name (always - * NULL) - */ - set_tuplefield_null(&row->tuple[12]); - - /* These values can be NULL */ - set_nullfield_int4(&row->tuple[2], pgtype_precision(stmt, pgType, PG_STATIC, PG_STATIC)); - set_nullfield_string(&row->tuple[3], pgtype_literal_prefix(stmt, pgType)); - set_nullfield_string(&row->tuple[4], pgtype_literal_suffix(stmt, pgType)); - set_nullfield_string(&row->tuple[5], pgtype_create_params(stmt, pgType)); - set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType)); - set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType)); - set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC)); - set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC)); - - QR_add_tuple(stmt->result, row); - } - } - - stmt->status = STMT_FINISHED; - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_GetFunctions( - HDBC hdbc, - UWORD fFunction, - UWORD FAR * pfExists) -{ - static char *func = "PGAPI_GetFunctions"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - ConnInfo *ci = &(conn->connInfo); - - mylog("%s: entering...%u\n", func, fFunction); - - if (fFunction == SQL_API_ALL_FUNCTIONS) - { -#if (ODBCVER < 0x0300) - if (ci->drivers.lie) - { - int i; - - memset(pfExists, 0, sizeof(UWORD) * 100); - - pfExists[SQL_API_SQLALLOCENV] = TRUE; - pfExists[SQL_API_SQLFREEENV] = TRUE; - for (i = SQL_API_SQLALLOCCONNECT; i <= SQL_NUM_FUNCTIONS; i++) - pfExists[i] = TRUE; - for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++) - pfExists[i] = TRUE; - } - else -#endif - { - memset(pfExists, 0, sizeof(UWORD) * 100); - - /* ODBC core functions */ - pfExists[SQL_API_SQLALLOCCONNECT] = TRUE; - pfExists[SQL_API_SQLALLOCENV] = TRUE; - pfExists[SQL_API_SQLALLOCSTMT] = TRUE; - pfExists[SQL_API_SQLBINDCOL] = TRUE; - pfExists[SQL_API_SQLCANCEL] = TRUE; - pfExists[SQL_API_SQLCOLATTRIBUTES] = TRUE; - pfExists[SQL_API_SQLCONNECT] = TRUE; - pfExists[SQL_API_SQLDESCRIBECOL] = TRUE; /* partial */ - pfExists[SQL_API_SQLDISCONNECT] = TRUE; - pfExists[SQL_API_SQLERROR] = TRUE; - pfExists[SQL_API_SQLEXECDIRECT] = TRUE; - pfExists[SQL_API_SQLEXECUTE] = TRUE; - pfExists[SQL_API_SQLFETCH] = TRUE; - pfExists[SQL_API_SQLFREECONNECT] = TRUE; - pfExists[SQL_API_SQLFREEENV] = TRUE; - pfExists[SQL_API_SQLFREESTMT] = TRUE; - pfExists[SQL_API_SQLGETCURSORNAME] = TRUE; - pfExists[SQL_API_SQLNUMRESULTCOLS] = TRUE; - pfExists[SQL_API_SQLPREPARE] = TRUE; /* complete? */ - pfExists[SQL_API_SQLROWCOUNT] = TRUE; - pfExists[SQL_API_SQLSETCURSORNAME] = TRUE; - pfExists[SQL_API_SQLSETPARAM] = FALSE; /* odbc 1.0 */ - pfExists[SQL_API_SQLTRANSACT] = TRUE; - - /* ODBC level 1 functions */ - pfExists[SQL_API_SQLBINDPARAMETER] = TRUE; - pfExists[SQL_API_SQLCOLUMNS] = TRUE; - pfExists[SQL_API_SQLDRIVERCONNECT] = TRUE; - pfExists[SQL_API_SQLGETCONNECTOPTION] = TRUE; /* partial */ - pfExists[SQL_API_SQLGETDATA] = TRUE; - pfExists[SQL_API_SQLGETFUNCTIONS] = TRUE; - pfExists[SQL_API_SQLGETINFO] = TRUE; - pfExists[SQL_API_SQLGETSTMTOPTION] = TRUE; /* partial */ - pfExists[SQL_API_SQLGETTYPEINFO] = TRUE; - pfExists[SQL_API_SQLPARAMDATA] = TRUE; - pfExists[SQL_API_SQLPUTDATA] = TRUE; - pfExists[SQL_API_SQLSETCONNECTOPTION] = TRUE; /* partial */ - pfExists[SQL_API_SQLSETSTMTOPTION] = TRUE; - pfExists[SQL_API_SQLSPECIALCOLUMNS] = TRUE; - pfExists[SQL_API_SQLSTATISTICS] = TRUE; - pfExists[SQL_API_SQLTABLES] = TRUE; - - /* ODBC level 2 functions */ - pfExists[SQL_API_SQLBROWSECONNECT] = FALSE; - pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE; - pfExists[SQL_API_SQLDATASOURCES] = FALSE; /* only implemented by - * DM */ - pfExists[SQL_API_SQLDESCRIBEPARAM] = FALSE; /* not properly - * implemented */ - pfExists[SQL_API_SQLDRIVERS] = FALSE; /* only implemented by - * DM */ - pfExists[SQL_API_SQLEXTENDEDFETCH] = TRUE; - pfExists[SQL_API_SQLFOREIGNKEYS] = TRUE; - pfExists[SQL_API_SQLMORERESULTS] = TRUE; - pfExists[SQL_API_SQLNATIVESQL] = TRUE; - pfExists[SQL_API_SQLNUMPARAMS] = TRUE; - pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE; - pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE; - pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE; - if (PG_VERSION_LT(conn, 6.5)) - pfExists[SQL_API_SQLPROCEDURES] = FALSE; - else - pfExists[SQL_API_SQLPROCEDURES] = TRUE; - pfExists[SQL_API_SQLSETPOS] = TRUE; - pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */ - pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE; - } - } - else - { - if (ci->drivers.lie) - *pfExists = TRUE; - else - { - switch (fFunction) - { - case SQL_API_SQLALLOCCONNECT: - *pfExists = TRUE; - break; - case SQL_API_SQLALLOCENV: - *pfExists = TRUE; - break; - case SQL_API_SQLALLOCSTMT: - *pfExists = TRUE; - break; - case SQL_API_SQLBINDCOL: - *pfExists = TRUE; - break; - case SQL_API_SQLCANCEL: - *pfExists = TRUE; - break; - case SQL_API_SQLCOLATTRIBUTES: - *pfExists = TRUE; - break; - case SQL_API_SQLCONNECT: - *pfExists = TRUE; - break; - case SQL_API_SQLDESCRIBECOL: - *pfExists = TRUE; - break; /* partial */ - case SQL_API_SQLDISCONNECT: - *pfExists = TRUE; - break; - case SQL_API_SQLERROR: - *pfExists = TRUE; - break; - case SQL_API_SQLEXECDIRECT: - *pfExists = TRUE; - break; - case SQL_API_SQLEXECUTE: - *pfExists = TRUE; - break; - case SQL_API_SQLFETCH: - *pfExists = TRUE; - break; - case SQL_API_SQLFREECONNECT: - *pfExists = TRUE; - break; - case SQL_API_SQLFREEENV: - *pfExists = TRUE; - break; - case SQL_API_SQLFREESTMT: - *pfExists = TRUE; - break; - case SQL_API_SQLGETCURSORNAME: - *pfExists = TRUE; - break; - case SQL_API_SQLNUMRESULTCOLS: - *pfExists = TRUE; - break; - case SQL_API_SQLPREPARE: - *pfExists = TRUE; - break; - case SQL_API_SQLROWCOUNT: - *pfExists = TRUE; - break; - case SQL_API_SQLSETCURSORNAME: - *pfExists = TRUE; - break; - case SQL_API_SQLSETPARAM: - *pfExists = FALSE; - break; /* odbc 1.0 */ - case SQL_API_SQLTRANSACT: - *pfExists = TRUE; - break; - - /* ODBC level 1 functions */ - case SQL_API_SQLBINDPARAMETER: - *pfExists = TRUE; - break; - case SQL_API_SQLCOLUMNS: - *pfExists = TRUE; - break; - case SQL_API_SQLDRIVERCONNECT: - *pfExists = TRUE; - break; - case SQL_API_SQLGETCONNECTOPTION: - *pfExists = TRUE; - break; /* partial */ - case SQL_API_SQLGETDATA: - *pfExists = TRUE; - break; - case SQL_API_SQLGETFUNCTIONS: - *pfExists = TRUE; - break; - case SQL_API_SQLGETINFO: - *pfExists = TRUE; - break; - case SQL_API_SQLGETSTMTOPTION: - *pfExists = TRUE; - break; /* partial */ - case SQL_API_SQLGETTYPEINFO: - *pfExists = TRUE; - break; - case SQL_API_SQLPARAMDATA: - *pfExists = TRUE; - break; - case SQL_API_SQLPUTDATA: - *pfExists = TRUE; - break; - case SQL_API_SQLSETCONNECTOPTION: - *pfExists = TRUE; - break; /* partial */ - case SQL_API_SQLSETSTMTOPTION: - *pfExists = TRUE; - break; - case SQL_API_SQLSPECIALCOLUMNS: - *pfExists = TRUE; - break; - case SQL_API_SQLSTATISTICS: - *pfExists = TRUE; - break; - case SQL_API_SQLTABLES: - *pfExists = TRUE; - break; - - /* ODBC level 2 functions */ - case SQL_API_SQLBROWSECONNECT: - *pfExists = FALSE; - break; - case SQL_API_SQLCOLUMNPRIVILEGES: - *pfExists = FALSE; - break; - case SQL_API_SQLDATASOURCES: - *pfExists = FALSE; - break; /* only implemented by DM */ - case SQL_API_SQLDESCRIBEPARAM: - *pfExists = FALSE; - break; /* not properly implemented */ - case SQL_API_SQLDRIVERS: - *pfExists = FALSE; - break; /* only implemented by DM */ - case SQL_API_SQLEXTENDEDFETCH: - *pfExists = TRUE; - break; - case SQL_API_SQLFOREIGNKEYS: - *pfExists = TRUE; - break; - case SQL_API_SQLMORERESULTS: - *pfExists = TRUE; - break; - case SQL_API_SQLNATIVESQL: - *pfExists = TRUE; - break; - case SQL_API_SQLNUMPARAMS: - *pfExists = TRUE; - break; - case SQL_API_SQLPARAMOPTIONS: - *pfExists = FALSE; - break; - case SQL_API_SQLPRIMARYKEYS: - *pfExists = TRUE; - break; - case SQL_API_SQLPROCEDURECOLUMNS: - *pfExists = FALSE; - break; - case SQL_API_SQLPROCEDURES: - if (PG_VERSION_LT(conn, 6.5)) - *pfExists = FALSE; - else - *pfExists = TRUE; - break; - case SQL_API_SQLSETPOS: - *pfExists = TRUE; - break; - case SQL_API_SQLSETSCROLLOPTIONS: - *pfExists = TRUE; - break; /* odbc 1.0 */ - case SQL_API_SQLTABLEPRIVILEGES: - *pfExists = FALSE; - break; - } - } - } - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_Tables( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UCHAR FAR * szTableType, - SWORD cbTableType) -{ - static char *func = "PGAPI_Tables"; - StatementClass *stmt = (StatementClass *) hstmt; - StatementClass *tbl_stmt; - TupleNode *row; - HSTMT htbl_stmt; - RETCODE result; - char *tableType; - char tables_query[INFO_INQUIRY_LEN]; - char table_name[MAX_INFO_STRING], - table_owner[MAX_INFO_STRING], - relkind_or_hasrules[MAX_INFO_STRING]; - ConnectionClass *conn; - ConnInfo *ci; - char *prefix[32], - prefixes[MEDIUM_REGISTRY_LEN]; - char *table_type[32], - table_types[MAX_INFO_STRING]; - char show_system_tables, - show_regular_tables, - show_views; - char regular_table, - view, - systable; - int i; - - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - stmt->manual_result = TRUE; - stmt->errormsg_created = TRUE; - - conn = SC_get_conn(stmt); - ci = &(conn->connInfo); - - result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for PGAPI_Tables result."; - SC_log_error(func, "", stmt); - 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')"); - } - else - { - strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user"); - strcat(tables_query, " where relkind = 'r'"); - } - - 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, ci->drivers.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; - show_regular_tables = FALSE; - show_views = FALSE; - - /* make_string mallocs memory */ - tableType = make_string(szTableType, cbTableType, NULL); - if (tableType) - { - strcpy(table_types, tableType); - free(tableType); - i = 0; - table_type[i] = strtok(table_types, ","); - while (table_type[i] && i < 32) - table_type[++i] = strtok(NULL, ","); - - /* Check for desired table types to return */ - i = 0; - while (table_type[i]) - { - if (strstr(table_type[i], "SYSTEM TABLE")) - show_system_tables = TRUE; - else if (strstr(table_type[i], "TABLE")) - show_regular_tables = TRUE; - else if (strstr(table_type[i], "VIEW")) - show_views = TRUE; - i++; - } - } - else - { - show_regular_tables = TRUE; - show_views = TRUE; - } - - /* - * If not interested in SYSTEM TABLES then filter them out to save - * some time on the query. If treating system tables as regular - * tables, then dont filter either. - */ - if (!atoi(ci->show_system_tables) && !show_system_tables) - { - strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX); - - /* Also filter out user-defined system table types */ - i = 0; - while (prefix[i]) - { - strcat(tables_query, "|^"); - 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 = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query)); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_CHAR, - table_name, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_CHAR, - table_owner, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - result = PGAPI_BindCol(htbl_stmt, 3, SQL_C_CHAR, - relkind_or_hasrules, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - stmt->result = QR_Constructor(); - if (!stmt->result) - { - stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - /* the binding structure for a statement is not set up until */ - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - extend_bindings(stmt, 5); - - /* set the field names */ - QR_set_num_fields(stmt->result, 5); - QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "REMARKS", PG_TYPE_TEXT, 254); - - /* add the tuples */ - result = PGAPI_Fetch(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. - */ - 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]) - { - mylog("table_name='%s', prefix[%d]='%s'\n", table_name, i, prefix[i]); - if (strncmp(table_name, prefix[i], strlen(prefix[i])) == 0) - { - systable = TRUE; - break; - } - i++; - } - } - } - - /* 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'); - - /* It must be a regular table */ - regular_table = (!systable && !view); - - - /* Include the row in the result set if meets all criteria */ - - /* - * NOTE: Unsupported table types (i.e., LOCAL TEMPORARY, ALIAS, - * etc) will return nothing - */ - if ((systable && show_system_tables) || - (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("%s: table_name = '%s'\n", func, table_name); - - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], table_name); - set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE")); - set_tuplefield_string(&row->tuple[4], ""); - - QR_add_tuple(stmt->result, row); - } - result = PGAPI_Fetch(htbl_stmt); - } - if (result != SQL_NO_DATA_FOUND) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - 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 */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - mylog("%s: EXIT, stmt=%u\n", func, stmt); - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_Columns( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UCHAR FAR * szColumnName, - SWORD cbColumnName) -{ - static char *func = "PGAPI_Columns"; - StatementClass *stmt = (StatementClass *) hstmt; - TupleNode *row; - HSTMT hcol_stmt; - StatementClass *col_stmt; - char columns_query[INFO_INQUIRY_LEN]; - RETCODE result; - char table_owner[MAX_INFO_STRING], - table_name[MAX_INFO_STRING], - field_name[MAX_INFO_STRING], - field_type_name[MAX_INFO_STRING]; - Int2 field_number, - result_cols, - scale; - Int4 field_type, - the_type, - field_length, - mod_length, - precision; - char useStaticPrecision; - char not_null[MAX_INFO_STRING], - relhasrules[MAX_INFO_STRING]; - ConnInfo *ci; - ConnectionClass *conn; - - - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - stmt->manual_result = TRUE; - stmt->errormsg_created = TRUE; - - conn = SC_get_conn(stmt); - ci = &(conn->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" - " where u.usesysid = c.relowner" - " and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)", - PG_VERSION_LE(conn, 6.2) ? "a.attlen" : "a.atttypmod"); - - my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName); - 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 = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for PGAPI_Columns result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - col_stmt = (StatementClass *) hcol_stmt; - - mylog("%s: hcol_stmt = %u, col_stmt = %u\n", func, hcol_stmt, col_stmt); - - result = PGAPI_ExecDirect(hcol_stmt, columns_query, - strlen(columns_query)); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(hcol_stmt); - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 1, SQL_C_CHAR, - table_owner, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 2, SQL_C_CHAR, - table_name, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 3, SQL_C_CHAR, - field_name, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 4, SQL_C_LONG, - &field_type, 4, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 5, SQL_C_CHAR, - field_type_name, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 6, SQL_C_SHORT, - &field_number, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 7, SQL_C_LONG, - &field_length, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 8, SQL_C_LONG, - &mod_length, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 9, SQL_C_CHAR, - not_null, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 10, SQL_C_CHAR, - relhasrules, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - stmt->result = QR_Constructor(); - if (!stmt->result) - { - stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - /* the binding structure for a statement is not set up until */ - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - result_cols = 14; - extend_bindings(stmt, result_cols); - - /* set the field names */ - QR_set_num_fields(stmt->result, result_cols); - QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4); - QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4); - QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254); - - /* User defined fields */ - 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 = PGAPI_Fetch(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 - * table - */ - - 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) + - (result_cols - 1) *sizeof(TupleField)); - - set_tuplefield_string(&row->tuple[0], ""); - /* see note in SQLTables() */ - /* set_tuplefield_string(&row->tuple[1], table_owner); */ - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], table_name); - set_tuplefield_string(&row->tuple[3], "oid"); - set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type)); - set_tuplefield_string(&row->tuple[5], "OID"); - - set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC)); - - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type, PG_STATIC)); - set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type)); - set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS); - set_tuplefield_string(&row->tuple[11], ""); - - set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[13], the_type); - - QR_add_tuple(stmt->result, row); - } - } - - while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + - (result_cols - 1) *sizeof(TupleField)); - - - set_tuplefield_string(&row->tuple[0], ""); - /* see note in SQLTables() */ - /* set_tuplefield_string(&row->tuple[1], table_owner); */ - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], table_name); - set_tuplefield_string(&row->tuple[3], field_name); - set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, field_type)); - set_tuplefield_string(&row->tuple[5], field_type_name); - - - /*---------- - * Some Notes about Postgres Data Types: - * - * VARCHAR - the length is stored in the pg_attribute.atttypmod field - * BPCHAR - the length is also stored as varchar is - * - * NUMERIC - the scale is stored in atttypmod as follows: - * - * precision =((atttypmod - VARHDRSZ) >> 16) & 0xffff - * scale = (atttypmod - VARHDRSZ) & 0xffff - * - *---------- - */ - qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n", - table_name, field_name, field_type, pgtype_to_sqltype, field_type_name); - - useStaticPrecision = TRUE; - - if (field_type == PG_TYPE_NUMERIC) - { - if (mod_length >= 4) - mod_length -= 4; /* the length is in atttypmod - 4 */ - - if (mod_length >= 0) - { - useStaticPrecision = FALSE; - - precision = (mod_length >> 16) & 0xffff; - scale = mod_length & 0xffff; - - mylog("%s: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", func, field_type, mod_length, precision, scale); - - set_tuplefield_int4(&row->tuple[7], precision + 2); /* sign+dec.point */ - set_tuplefield_int4(&row->tuple[6], precision); - set_tuplefield_int4(&row->tuple[12], precision + 2); /* sign+dec.point */ - set_nullfield_int2(&row->tuple[8], scale); - } - } - - if ((field_type == PG_TYPE_VARCHAR) || - (field_type == PG_TYPE_BPCHAR)) - { - useStaticPrecision = FALSE; - - if (mod_length >= 4) - mod_length -= 4; /* the length is in atttypmod - 4 */ - - if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0) - mod_length = ci->drivers.max_varchar_size; - - mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length); - - set_tuplefield_int4(&row->tuple[7], mod_length); - set_tuplefield_int4(&row->tuple[6], mod_length); - set_tuplefield_int4(&row->tuple[12], mod_length); - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC)); - } - - if (useStaticPrecision) - { - mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC)); - - set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, field_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC)); - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC)); - } - - set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type)); - set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type))); - set_tuplefield_string(&row->tuple[11], ""); - set_tuplefield_int4(&row->tuple[13], field_type); - - QR_add_tuple(stmt->result, row); - - - result = PGAPI_Fetch(hcol_stmt); - - } - if (result != SQL_NO_DATA_FOUND) - { - stmt->errormsg = SC_create_errormsg(hcol_stmt); - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - 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 */ - the_type = PG_TYPE_INT4; - - row = (TupleNode *) malloc(sizeof(TupleNode) + - (result_cols - 1) *sizeof(TupleField)); - - set_tuplefield_string(&row->tuple[0], ""); - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], table_name); - set_tuplefield_string(&row->tuple[3], "xmin"); - set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type)); - set_tuplefield_string(&row->tuple[5], pgtype_to_name(stmt, the_type)); - set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type, PG_STATIC)); - set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type)); - set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS); - set_tuplefield_string(&row->tuple[11], ""); - set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[13], the_type); - - 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 */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - mylog("%s: EXIT, stmt=%u\n", func, stmt); - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_SpecialColumns( - HSTMT hstmt, - UWORD fColType, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UWORD fScope, - UWORD fNullable) -{ - static char *func = "PGAPI_SpecialColumns"; - TupleNode *row; - StatementClass *stmt = (StatementClass *) hstmt; - ConnInfo *ci; - HSTMT hcol_stmt; - StatementClass *col_stmt; - char columns_query[INFO_INQUIRY_LEN]; - RETCODE result; - char relhasrules[MAX_INFO_STRING]; - - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->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"); - - my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName); - my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner); - - - result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for SQLSpecialColumns result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - col_stmt = (StatementClass *) hcol_stmt; - - mylog("%s: hcol_stmt = %u, col_stmt = %u\n", func, hcol_stmt, col_stmt); - - result = PGAPI_ExecDirect(hcol_stmt, columns_query, - strlen(columns_query)); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(hcol_stmt); - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(hcol_stmt, 1, SQL_C_CHAR, - relhasrules, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_Fetch(hcol_stmt); - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - - stmt->result = QR_Constructor(); - extend_bindings(stmt, 8); - - QR_set_num_fields(stmt->result, 8); - QR_set_field_info(stmt->result, 0, "SCOPE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "DATA_TYPE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "PRECISION", PG_TYPE_INT4, 4); - QR_set_field_info(stmt->result, 5, "LENGTH", PG_TYPE_INT4, 4); - QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2); - - if (relhasrules[0] != '1') - { - /* use the oid value for the rowid */ - if (fColType == SQL_BEST_ROWID) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField)); - - set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION); - set_tuplefield_string(&row->tuple[1], "oid"); - set_tuplefield_int2(&row->tuple[2], pgtype_to_sqltype(stmt, PG_TYPE_OID)); - set_tuplefield_string(&row->tuple[3], "OID"); - set_tuplefield_int4(&row->tuple[4], pgtype_precision(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[5], pgtype_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC)); - set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC)); - set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO); - - QR_add_tuple(stmt->result, row); - - } - else if (fColType == SQL_ROWVER) - { - Int2 the_type = PG_TYPE_INT4; - - if (atoi(ci->row_versioning)) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField)); - - set_tuplefield_null(&row->tuple[0]); - set_tuplefield_string(&row->tuple[1], "xmin"); - set_tuplefield_int2(&row->tuple[2], pgtype_to_sqltype(stmt, the_type)); - set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type)); - set_tuplefield_int4(&row->tuple[4], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int4(&row->tuple[5], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC)); - set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO); - - QR_add_tuple(stmt->result, row); - } - } - } - - stmt->status = STMT_FINISHED; - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - mylog("%s: EXIT, stmt=%u\n", func, stmt); - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_Statistics( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UWORD fUnique, - UWORD fAccuracy) -{ - static char *func = "PGAPI_Statistics"; - StatementClass *stmt = (StatementClass *) hstmt; - char index_query[INFO_INQUIRY_LEN]; - HSTMT hindx_stmt; - RETCODE result; - char *table_name; - char index_name[MAX_INFO_STRING]; - short fields_vector[16]; - char isunique[10], - isclustered[10], - ishash[MAX_INFO_STRING]; - SDWORD index_name_len, - fields_vector_len; - TupleNode *row; - int i; - HSTMT hcol_stmt; - StatementClass *col_stmt, - *indx_stmt; - char column_name[MAX_INFO_STRING], - relhasrules[MAX_INFO_STRING]; - char **column_names = 0; - SQLINTEGER column_name_len; - int total_columns = 0; - char error = TRUE; - ConnInfo *ci; - char buf[256]; - - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - stmt->manual_result = TRUE; - stmt->errormsg_created = TRUE; - - ci = &(SC_get_conn(stmt)->connInfo); - - stmt->result = QR_Constructor(); - if (!stmt->result) - { - stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* the binding structure for a statement is not set up until */ - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - extend_bindings(stmt, 13); - - /* set the field names */ - QR_set_num_fields(stmt->result, 13); - QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 3, "NON_UNIQUE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 6, "TYPE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 9, "COLLATION", PG_TYPE_CHAR, 1); - QR_set_field_info(stmt->result, 10, "CARDINALITY", PG_TYPE_INT4, 4); - 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) - { - stmt->errormsg = "No table name passed to PGAPI_Statistics."; - stmt->errornumber = STMT_INTERNAL_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* - * we need to get a list of the field names first, so we can return - * them later. - */ - result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = "PGAPI_AllocStmt failed in PGAPI_Statistics for columns."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - goto SEEYA; - } - - col_stmt = (StatementClass *) hcol_stmt; - - /* - * "internal" prevents SQLColumns from returning the oid if it is - * being shown. This would throw everything off. - */ - col_stmt->internal = TRUE; - result = PGAPI_Columns(hcol_stmt, "", 0, "", 0, - table_name, (SWORD) strlen(table_name), "", 0); - col_stmt->internal = FALSE; - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; /* "SQLColumns failed in - * SQLStatistics."; */ - stmt->errornumber = col_stmt->errornumber; /* STMT_EXEC_ERROR; */ - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - goto SEEYA; - } - result = PGAPI_BindCol(hcol_stmt, 4, SQL_C_CHAR, - column_name, MAX_INFO_STRING, &column_name_len); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = col_stmt->errormsg; - stmt->errornumber = col_stmt->errornumber; - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - goto SEEYA; - - } - - result = PGAPI_Fetch(hcol_stmt); - while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) - { - total_columns++; - - column_names = - (char **) realloc(column_names, - total_columns * sizeof(char *)); - column_names[total_columns - 1] = - (char *) malloc(strlen(column_name) + 1); - strcpy(column_names[total_columns - 1], column_name); - - mylog("%s: column_name = '%s'\n", func, column_name); - - result = PGAPI_Fetch(hcol_stmt); - } - - if (result != SQL_NO_DATA_FOUND || total_columns == 0) - { - stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column - * names in - * SQLStatistics."; */ - stmt->errornumber = col_stmt->errornumber; - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - goto SEEYA; - - } - - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - - /* get a list of indexes on this table */ - result = PGAPI_AllocStmt(stmt->hdbc, &hindx_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = "PGAPI_AllocStmt failed in SQLStatistics for indices."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - goto SEEYA; - - } - indx_stmt = (StatementClass *) hindx_stmt; - - sprintf(index_query, "select c.relname, i.indkey, i.indisunique" - ", i.indisclustered, a.amname, c.relhasrules" - " from pg_index i, pg_class c, pg_class d, pg_am a" - " where d.relname = '%s'" - " and d.oid = i.indrelid" - " and i.indexrelid = c.oid" - " and c.relam = a.oid" - ,table_name); - if (PG_VERSION_GT(SC_get_conn(stmt), 6.4)) - strcat(index_query, " order by i.indisprimary desc"); - - result = PGAPI_ExecDirect(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; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - } - - /* bind the index name column */ - result = PGAPI_BindCol(hindx_stmt, 1, SQL_C_CHAR, - index_name, MAX_INFO_STRING, &index_name_len); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column - * in SQLStatistics."; */ - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - - } - /* bind the vector column */ - result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT, - fields_vector, 32, &fields_vector_len); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column - * in SQLStatistics."; */ - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - - } - /* bind the "is unique" column */ - result = PGAPI_BindCol(hindx_stmt, 3, SQL_C_CHAR, - isunique, sizeof(isunique), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column - * in SQLStatistics."; */ - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - } - - /* bind the "is clustered" column */ - result = PGAPI_BindCol(hindx_stmt, 4, SQL_C_CHAR, - isclustered, sizeof(isclustered), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column - * in SQLStatistics."; */ - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - - } - - /* bind the "is hash" column */ - result = PGAPI_BindCol(hindx_stmt, 5, SQL_C_CHAR, - ishash, sizeof(ishash), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column - * in SQLStatistics."; */ - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - - } - - result = PGAPI_BindCol(hindx_stmt, 6, SQL_C_CHAR, - relhasrules, MAX_INFO_STRING, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = indx_stmt->errormsg; - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - } - - /* fake index of OID */ - if (relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index)) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + - (13 - 1) *sizeof(TupleField)); - - /* no table qualifier */ - set_tuplefield_string(&row->tuple[0], ""); - /* don't set the table owner, else Access tries to use it */ - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], table_name); - - /* non-unique index? */ - set_tuplefield_int2(&row->tuple[3], (Int2) (ci->drivers.unique_index ? FALSE : TRUE)); - - /* no index qualifier */ - set_tuplefield_string(&row->tuple[4], ""); - - sprintf(buf, "%s_idx_fake_oid", table_name); - set_tuplefield_string(&row->tuple[5], buf); - - /* - * Clustered/HASH index? - */ - set_tuplefield_int2(&row->tuple[6], (Int2) SQL_INDEX_OTHER); - set_tuplefield_int2(&row->tuple[7], (Int2) 1); - - set_tuplefield_string(&row->tuple[8], "oid"); - set_tuplefield_string(&row->tuple[9], "A"); - set_tuplefield_null(&row->tuple[10]); - set_tuplefield_null(&row->tuple[11]); - set_tuplefield_null(&row->tuple[12]); - - QR_add_tuple(stmt->result, row); - } - - result = PGAPI_Fetch(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))) - { - i = 0; - /* 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)); - - /* no table qualifier */ - set_tuplefield_string(&row->tuple[0], ""); - /* don't set the table owner, else Access tries to use it */ - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], table_name); - - /* non-unique index? */ - if (ci->drivers.unique_index) - set_tuplefield_int2(&row->tuple[3], (Int2) (atoi(isunique) ? FALSE : TRUE)); - else - set_tuplefield_int2(&row->tuple[3], TRUE); - - /* no index qualifier */ - set_tuplefield_string(&row->tuple[4], ""); - set_tuplefield_string(&row->tuple[5], index_name); - - /* - * Clustered/HASH index? - */ - set_tuplefield_int2(&row->tuple[6], (Int2) - (atoi(isclustered) ? SQL_INDEX_CLUSTERED : - (!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER)); - set_tuplefield_int2(&row->tuple[7], (Int2) (i + 1)); - - if (fields_vector[i] == OID_ATTNUM) - { - set_tuplefield_string(&row->tuple[8], "oid"); - mylog("%s: column name = oid\n", func); - } - else if (fields_vector[i] < 0 || fields_vector[i] > total_columns) - { - set_tuplefield_string(&row->tuple[8], "UNKNOWN"); - mylog("%s: column name = UNKNOWN\n", func); - } - else - { - set_tuplefield_string(&row->tuple[8], column_names[fields_vector[i] - 1]); - mylog("%s: column name = '%s'\n", func, column_names[fields_vector[i] - 1]); - } - - set_tuplefield_string(&row->tuple[9], "A"); - set_tuplefield_null(&row->tuple[10]); - set_tuplefield_null(&row->tuple[11]); - set_tuplefield_null(&row->tuple[12]); - - QR_add_tuple(stmt->result, row); - i++; - } - } - - result = PGAPI_Fetch(hindx_stmt); - } - if (result != SQL_NO_DATA_FOUND) - { - /* "SQLFetch failed in SQLStatistics."; */ - stmt->errormsg = SC_create_errormsg(hindx_stmt); - stmt->errornumber = indx_stmt->errornumber; - PGAPI_FreeStmt(hindx_stmt, SQL_DROP); - goto SEEYA; - } - - PGAPI_FreeStmt(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 */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - error = FALSE; - -SEEYA: - /* These things should be freed on any error ALSO! */ - free(table_name); - for (i = 0; i < total_columns; i++) - free(column_names[i]); - free(column_names); - - mylog("%s: EXIT, %s, stmt=%u\n", func, error ? "error" : "success", stmt); - - if (error) - { - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - else - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_ColumnPrivileges( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UCHAR FAR * szColumnName, - SWORD cbColumnName) -{ - static char *func = "PGAPI_ColumnPrivileges"; - - 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 -PGAPI_PrimaryKeys( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName) -{ - static char *func = "PGAPI_PrimaryKeys"; - StatementClass *stmt = (StatementClass *) hstmt; - ConnectionClass *conn; - TupleNode *row; - RETCODE result; - int seq = 0; - HSTMT htbl_stmt; - StatementClass *tbl_stmt; - char tables_query[INFO_INQUIRY_LEN]; - char attname[MAX_INFO_STRING]; - SDWORD attname_len; - char pktab[MAX_TABLE_LEN + 1]; - Int2 result_cols; - int qno, - qstart, - qend; - - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - stmt->manual_result = TRUE; - stmt->errormsg_created = TRUE; - - stmt->result = QR_Constructor(); - if (!stmt->result) - { - stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* the binding structure for a statement is not set up until */ - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - result_cols = 6; - extend_bindings(stmt, result_cols); - - /* set the field names */ - QR_set_num_fields(stmt->result, result_cols); - QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - - - result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for Primary Key result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - tbl_stmt = (StatementClass *) htbl_stmt; - - pktab[0] = '\0'; - make_string(szTableName, cbTableName, pktab); - if (pktab[0] == '\0') - { - stmt->errormsg = "No Table specified to PGAPI_PrimaryKeys."; - stmt->errornumber = STMT_INTERNAL_ERROR; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_CHAR, - attname, MAX_INFO_STRING, &attname_len); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - conn = SC_get_conn(stmt); - if (PG_VERSION_LE(conn, 6.4)) - qstart = 2; - else - qstart = 1; - qend = 2; - for (qno = qstart; qno <= qend; qno++) - { - switch (qno) - { - case 1: - - /* - * Simplified query to remove assumptions about number of - * possible index columns. Courtesy of Tom Lane - thomas - * 2000-03-21 - */ - sprintf(tables_query, "select ta.attname, ia.attnum" - " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i" - " where c.relname = '%s'" - " AND c.oid = i.indrelid" - " AND i.indisprimary = 't'" - " AND ia.attrelid = i.indexrelid" - " AND ta.attrelid = i.indrelid" - " AND ta.attnum = i.indkey[ia.attnum-1]" - " order by ia.attnum", pktab); - break; - case 2: - - /* - * Simplified query to search old fashoned primary key - */ - sprintf(tables_query, "select ta.attname, ia.attnum" - " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i" - " where c.relname = '%s_pkey'" - " AND c.oid = i.indexrelid" - " AND ia.attrelid = i.indexrelid" - " AND ta.attrelid = i.indrelid" - " AND ta.attnum = i.indkey[ia.attnum-1]" - " order by ia.attnum", pktab); - break; - } - mylog("%s: tables_query='%s'\n", func, tables_query); - - result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query)); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_Fetch(htbl_stmt); - if (result != SQL_NO_DATA_FOUND) - break; - } - - 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]); - - /* - * 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], ""); - set_tuplefield_string(&row->tuple[2], pktab); - set_tuplefield_string(&row->tuple[3], attname); - set_tuplefield_int2(&row->tuple[4], (Int2) (++seq)); - set_tuplefield_null(&row->tuple[5]); - - QR_add_tuple(stmt->result, row); - - mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq); - - result = PGAPI_Fetch(htbl_stmt); - } - - if (result != SQL_NO_DATA_FOUND) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - PGAPI_FreeStmt(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 */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - mylog("%s: EXIT, stmt=%u\n", func, stmt); - return SQL_SUCCESS; -} - - -#ifdef MULTIBYTE -/* - * Multibyte support stuff for SQLForeignKeys(). - * There may be much more effective way in the - * future version. The way is very forcible currently. - */ -static BOOL -isMultibyte(const unsigned char *str) -{ - for (; *str; str++) - { - if (*str >= 0x80) - return TRUE; - } - return FALSE; -} -static char * -getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloced) -{ - char query[1024], - saveoid[24], - *ret = serverTableName; - BOOL continueExec = TRUE, - bError = FALSE; - QResultClass *res; - - *nameAlloced = FALSE; - if (!conn->client_encoding || !isMultibyte(serverTableName)) - return ret; - if (!conn->server_encoding) - { - if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res) - { - if (QR_get_num_tuples(res) > 0) - conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0)); - QR_Destructor(res); - } - } - if (!conn->server_encoding) - return ret; - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding); - if (res = CC_send_query(conn, query, NULL), res) - { - bError = QR_get_aborted(res); - QR_Destructor(res); - } - else - bError = TRUE; - if (!bError && continueExec) - { - sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName); - if (res = CC_send_query(conn, query, NULL), res) - { - if (QR_get_num_tuples(res) > 0) - strcpy(saveoid, QR_get_value_backend_row(res, 0, 0)); - else - { - continueExec = FALSE; - bError = QR_get_aborted(res); - } - QR_Destructor(res); - } - else - bError = TRUE; - } - continueExec = (continueExec && !bError); - if (bError && CC_is_in_trans(conn)) - { - if (res = CC_send_query(conn, "abort", NULL), res) - QR_Destructor(res); - CC_set_no_trans(conn); - bError = FALSE; - } - /* restore the client encoding */ - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); - if (res = CC_send_query(conn, query, NULL), res) - { - bError = QR_get_aborted(res); - QR_Destructor(res); - } - else - bError = TRUE; - if (bError || !continueExec) - return ret; - sprintf(query, "select relname from pg_class where OID = %s", saveoid); - if (res = CC_send_query(conn, query, NULL), res) - { - if (QR_get_num_tuples(res) > 0) - { - ret = strdup(QR_get_value_backend_row(res, 0, 0)); - *nameAlloced = TRUE; - } - QR_Destructor(res); - } - return ret; -} -static char * -getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *serverColumnName, BOOL *nameAlloced) -{ - char query[1024], - saveattrelid[24], - saveattnum[16], - *ret = serverColumnName; - BOOL continueExec = TRUE, - bError = FALSE; - QResultClass *res; - - *nameAlloced = FALSE; - if (!conn->client_encoding || !isMultibyte(serverColumnName)) - return ret; - if (!conn->server_encoding) - { - if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res) - { - if (QR_get_num_tuples(res) > 0) - conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0)); - QR_Destructor(res); - } - } - if (!conn->server_encoding) - return ret; - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding); - if (res = CC_send_query(conn, query, NULL), res) - { - bError = QR_get_aborted(res); - QR_Destructor(res); - } - else - bError = TRUE; - if (!bError && continueExec) - { - sprintf(query, "select attrelid, attnum from pg_class, pg_attribute " - "where relname = '%s' and attrelid = pg_class.oid " - "and attname = '%s'", serverTableName, serverColumnName); - if (res = CC_send_query(conn, query, NULL), res) - { - if (QR_get_num_tuples(res) > 0) - { - strcpy(saveattrelid, QR_get_value_backend_row(res, 0, 0)); - strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1)); - } - else - { - continueExec = FALSE; - bError = QR_get_aborted(res); - } - QR_Destructor(res); - } - else - bError = TRUE; - } - continueExec = (continueExec && !bError); - if (bError && CC_is_in_trans(conn)) - { - if (res = CC_send_query(conn, "abort", NULL), res) - QR_Destructor(res); - CC_set_no_trans(conn); - bError = FALSE; - } - /* restore the cleint encoding */ - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); - if (res = CC_send_query(conn, query, NULL), res) - { - bError = QR_get_aborted(res); - QR_Destructor(res); - } - else - bError = TRUE; - if (bError || !continueExec) - return ret; - sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum); - if (res = CC_send_query(conn, query, NULL), res) - { - if (QR_get_num_tuples(res) > 0) - { - ret = strdup(QR_get_value_backend_row(res, 0, 0)); - *nameAlloced = TRUE; - } - QR_Destructor(res); - } - return ret; -} -#endif /* MULTIBYTE */ - -RETCODE SQL_API -PGAPI_ForeignKeys( - HSTMT hstmt, - UCHAR FAR * szPkTableQualifier, - SWORD cbPkTableQualifier, - UCHAR FAR * szPkTableOwner, - SWORD cbPkTableOwner, - UCHAR FAR * szPkTableName, - SWORD cbPkTableName, - UCHAR FAR * szFkTableQualifier, - SWORD cbFkTableQualifier, - UCHAR FAR * szFkTableOwner, - SWORD cbFkTableOwner, - UCHAR FAR * szFkTableName, - SWORD cbFkTableName) -{ - static char *func = "PGAPI_ForeignKeys"; - StatementClass *stmt = (StatementClass *) hstmt; - TupleNode *row; - HSTMT htbl_stmt, - hpkey_stmt; - StatementClass *tbl_stmt; - RETCODE result, - keyresult; - char tables_query[INFO_INQUIRY_LEN]; - char trig_deferrable[2]; - char trig_initdeferred[2]; - char trig_args[1024]; - char upd_rule[MAX_TABLE_LEN], - del_rule[MAX_TABLE_LEN]; - char pk_table_needed[MAX_TABLE_LEN + 1]; - char fk_table_needed[MAX_TABLE_LEN + 1]; - char *pkey_ptr, - *pkey_text, - *fkey_ptr, - *fkey_text, - *pk_table, - *pkt_text, - *fk_table, - *fkt_text; - -#ifdef MULTIBYTE - BOOL pkey_alloced, - fkey_alloced, - pkt_alloced, - fkt_alloced; - ConnectionClass *conn; -#endif /* MULTIBYTE */ - int i, - j, - k, - num_keys; - SWORD trig_nargs, - upd_rule_type = 0, - del_rule_type = 0; - -#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); - return SQL_INVALID_HANDLE; - } - - stmt->manual_result = TRUE; - stmt->errormsg_created = TRUE; - - stmt->result = QR_Constructor(); - if (!stmt->result) - { - stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* the binding structure for a statement is not set up until */ - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - result_cols = 14; - extend_bindings(stmt, result_cols); - - /* set the field names */ - QR_set_num_fields(stmt->result, result_cols); - QR_set_field_info(stmt->result, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 10, "DELETE_RULE", PG_TYPE_INT2, 2); - QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); -#if (ODBCVER >= 0x0300) - 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 */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - - result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for PGAPI_ForeignKeys result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - tbl_stmt = (StatementClass *) htbl_stmt; - - pk_table_needed[0] = '\0'; - fk_table_needed[0] = '\0'; - - make_string(szPkTableName, cbPkTableName, pk_table_needed); - make_string(szFkTableName, cbFkTableName, fk_table_needed); - -#ifdef MULTIBYTE - pkey_text = fkey_text = pkt_text = fkt_text = NULL; - pkey_alloced = fkey_alloced = pkt_alloced = fkt_alloced = FALSE; - conn = SC_get_conn(stmt); -#endif /* MULTIBYTE */ - - /* - * Case #2 -- Get the foreign keys in the specified table (fktab) that - * refer to the primary keys of other table(s). - */ - if (fk_table_needed[0] != '\0') - { - mylog("%s: entering Foreign Key Case #2", func); - sprintf(tables_query, "SELECT pt.tgargs, " - " pt.tgnargs, " - " pt.tgdeferrable, " - " pt.tginitdeferred, " - " pg_proc.proname, " - " pg_proc_1.proname " - "FROM pg_class pc, " - " pg_proc pg_proc, " - " pg_proc pg_proc_1, " - " pg_trigger pg_trigger, " - " pg_trigger pg_trigger_1, " - " pg_proc pp, " - " pg_trigger pt " - "WHERE pt.tgrelid = pc.oid " - "AND pp.oid = pt.tgfoid " - "AND pg_trigger.tgconstrrelid = pc.oid " - "AND pg_proc.oid = pg_trigger.tgfoid " - "AND pg_trigger_1.tgfoid = pg_proc_1.oid " - "AND pg_trigger_1.tgconstrrelid = pc.oid " - "AND ((pc.relname='%s') " - "AND (pp.proname LIKE '%%ins') " - "AND (pg_proc.proname LIKE '%%upd') " - "AND (pg_proc_1.proname LIKE '%%del') " - "AND (pg_trigger.tgrelid=pt.tgconstrrelid) " - "AND (pg_trigger.tgconstrname=pt.tgconstrname) " - "AND (pg_trigger_1.tgrelid=pt.tgconstrrelid) " - "AND (pg_trigger_1.tgconstrname=pt.tgconstrname))", - fk_table_needed); - - result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query)); - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY, - trig_args, sizeof(trig_args), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT, - &trig_nargs, 0, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 3, SQL_C_CHAR, - trig_deferrable, sizeof(trig_deferrable), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 4, SQL_C_CHAR, - trig_initdeferred, sizeof(trig_initdeferred), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 5, SQL_C_CHAR, - upd_rule, sizeof(upd_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 6, SQL_C_CHAR, - del_rule, sizeof(del_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_Fetch(htbl_stmt); - if (result == SQL_NO_DATA_FOUND) - return SQL_SUCCESS; - - if (result != SQL_SUCCESS) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - keyresult = PGAPI_AllocStmt(stmt->hdbc, &hpkey_stmt); - if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - keyresult = PGAPI_BindCol(hpkey_stmt, 4, SQL_C_CHAR, - pkey, sizeof(pkey), NULL); - if (keyresult != SQL_SUCCESS) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result."; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hpkey_stmt, SQL_DROP); - return SQL_ERROR; - } - - while (result == SQL_SUCCESS) - { - /* Compute the number of keyparts. */ - num_keys = (trig_nargs - 4) / 2; - - mylog("Foreign Key Case#2: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys); - - pk_table = trig_args; - - /* Get to the PK Table Name */ - for (k = 0; k < 2; k++) - pk_table += strlen(pk_table) + 1; - -#ifdef MULTIBYTE - fk_table = trig_args + strlen(trig_args) + 1; - pkt_text = getClientTableName(conn, pk_table, &pkt_alloced); -#else - pkt_text = pk_table; -#endif /* MULTIBYTE */ - /* 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(pkt_text, pk_table_needed)) - { - result = PGAPI_Fetch(htbl_stmt); - continue; - } - } - - keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pkt_text, SQL_NTS); - if (keyresult != SQL_SUCCESS) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't get primary keys for PGAPI_ForeignKeys result."; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hpkey_stmt, SQL_DROP); - return SQL_ERROR; - } - - - /* Get to first primary key */ - pkey_ptr = trig_args; - for (i = 0; i < 5; i++) - pkey_ptr += strlen(pkey_ptr) + 1; - - for (k = 0; k < num_keys; k++) - { - /* Check that the key listed is the primary key */ - keyresult = PGAPI_Fetch(hpkey_stmt); - if (keyresult != SQL_SUCCESS) - { - num_keys = 0; - break; - } -#ifdef MULTIBYTE - pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced); -#else - pkey_text = pkey_ptr; -#endif /* MULTIBYTE */ - mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey); - if (strcmp(pkey_text, pkey)) - { - num_keys = 0; - break; - } -#ifdef MULTIBYTE - if (pkey_alloced) - free(pkey_text); -#endif /* MULTIBYTE */ - /* Get to next primary key */ - for (k = 0; k < 2; k++) - pkey_ptr += strlen(pkey_ptr) + 1; - - } - - /* Set to first fk column */ - fkey_ptr = trig_args; - for (k = 0; k < 4; k++) - fkey_ptr += strlen(fkey_ptr) + 1; - - /* Set update and delete actions for foreign keys */ - if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) - upd_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) - upd_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) - upd_rule_type = SQL_SET_NULL; - - if (!strcmp(upd_rule, "RI_FKey_cascade_del")) - del_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) - del_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) - del_rule_type = SQL_SET_NULL; - -#if (ODBCVER >= 0x0300) - /* Set deferrability type */ - if (!strcmp(trig_initdeferred, "y")) - defer_type = SQL_INITIALLY_DEFERRED; - else if (!strcmp(trig_deferrable, "y")) - defer_type = SQL_INITIALLY_IMMEDIATE; - else - defer_type = SQL_NOT_DEFERRABLE; -#endif /* ODBCVER >= 0x0300 */ - - /* Get to first primary key */ - pkey_ptr = trig_args; - for (i = 0; i < 5; i++) - pkey_ptr += strlen(pkey_ptr) + 1; - - for (k = 0; k < num_keys; k++) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); - -#ifdef MULTIBYTE - pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced); - fkey_text = getClientColumnName(conn, fk_table, fkey_ptr, &fkey_alloced); -#else - pkey_text = pkey_ptr; - fkey_text = fkey_ptr; -#endif /* MULTIBYTE */ - mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pkt_text, pkey_text); - set_tuplefield_null(&row->tuple[0]); - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], pkt_text); - set_tuplefield_string(&row->tuple[3], pkey_text); - - mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text); - set_tuplefield_null(&row->tuple[4]); - set_tuplefield_string(&row->tuple[5], ""); - set_tuplefield_string(&row->tuple[6], fk_table_needed); - set_tuplefield_string(&row->tuple[7], fkey_text); - - mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args); - set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1)); - set_tuplefield_int2(&row->tuple[9], (Int2) upd_rule_type); - set_tuplefield_int2(&row->tuple[10], (Int2) del_rule_type); - set_tuplefield_null(&row->tuple[11]); - set_tuplefield_null(&row->tuple[12]); - set_tuplefield_string(&row->tuple[13], trig_args); -#if (ODBCVER >= 0x0300) - set_tuplefield_int2(&row->tuple[14], defer_type); -#endif /* ODBCVER >= 0x0300 */ - - QR_add_tuple(stmt->result, row); -#ifdef MULTIBYTE - if (fkey_alloced) - free(fkey_text); - fkey_alloced = FALSE; - if (pkey_alloced) - free(pkey_text); - pkey_alloced = FALSE; -#endif /* MULTIBYTE */ - /* next primary/foreign key */ - for (i = 0; i < 2; i++) - { - fkey_ptr += strlen(fkey_ptr) + 1; - pkey_ptr += strlen(pkey_ptr) + 1; - } - } -#ifdef MULTIBYTE - if (pkt_alloced) - free(pkt_text); - pkt_alloced = FALSE; -#endif /* MULTIBYTE */ - - result = PGAPI_Fetch(htbl_stmt); - } - PGAPI_FreeStmt(hpkey_stmt, SQL_DROP); - } - - /* - * Case #1 -- Get the foreign keys in other tables that refer to the - * primary key in the specified table (pktab). i.e., Who points to - * me? - */ - else if (pk_table_needed[0] != '\0') - { - sprintf(tables_query, "SELECT pg_trigger.tgargs, " - " pg_trigger.tgnargs, " - " pg_trigger.tgdeferrable, " - " pg_trigger.tginitdeferred, " - " pg_proc.proname, " - " pg_proc_1.proname " - "FROM pg_class pg_class, " - " pg_class pg_class_1, " - " pg_class pg_class_2, " - " pg_proc pg_proc, " - " pg_proc pg_proc_1, " - " pg_trigger pg_trigger, " - " pg_trigger pg_trigger_1, " - " pg_trigger pg_trigger_2 " - "WHERE pg_trigger.tgconstrrelid = pg_class.oid " - " AND pg_trigger.tgrelid = pg_class_1.oid " - " AND pg_trigger_1.tgfoid = pg_proc_1.oid " - " AND pg_trigger_1.tgconstrrelid = pg_class_1.oid " - " AND pg_trigger_2.tgconstrrelid = pg_class_2.oid " - " AND pg_trigger_2.tgfoid = pg_proc.oid " - " AND pg_class_2.oid = pg_trigger.tgrelid " - " AND (" - " (pg_class.relname='%s') " - " AND (pg_proc.proname Like '%%upd') " - " AND (pg_proc_1.proname Like '%%del')" - " AND (pg_trigger_1.tgrelid = pg_trigger.tgconstrrelid) " - " AND (pg_trigger_2.tgrelid = pg_trigger.tgconstrrelid) " - " )", - pk_table_needed); - - result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query)); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY, - trig_args, sizeof(trig_args), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT, - &trig_nargs, 0, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 3, SQL_C_CHAR, - trig_deferrable, sizeof(trig_deferrable), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 4, SQL_C_CHAR, - trig_initdeferred, sizeof(trig_initdeferred), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 5, SQL_C_CHAR, - upd_rule, sizeof(upd_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 6, SQL_C_CHAR, - del_rule, sizeof(del_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_Fetch(htbl_stmt); - if (result == SQL_NO_DATA_FOUND) - return SQL_SUCCESS; - - if (result != SQL_SUCCESS) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - while (result == SQL_SUCCESS) - { - /* Calculate the number of key parts */ - num_keys = (trig_nargs - 4) / 2;; - - /* Handle action (i.e., 'cascade', 'restrict', 'setnull') */ - if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) - upd_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) - upd_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) - upd_rule_type = SQL_SET_NULL; - - if (!strcmp(upd_rule, "RI_FKey_cascade_del")) - del_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) - del_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) - del_rule_type = SQL_SET_NULL; - -#if (ODBCVER >= 0x0300) - /* Set deferrability type */ - if (!strcmp(trig_initdeferred, "y")) - defer_type = SQL_INITIALLY_DEFERRED; - else if (!strcmp(trig_deferrable, "y")) - defer_type = SQL_INITIALLY_IMMEDIATE; - else - defer_type = SQL_NOT_DEFERRABLE; -#endif /* ODBCVER >= 0x0300 */ - - mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys); - - /* Get to first primary key */ - pkey_ptr = trig_args; - 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; -#ifdef MULTIBYTE - pk_table = fk_table + strlen(fk_table) + 1; - fkt_text = getClientTableName(conn, fk_table, &fkt_alloced); -#else - fkt_text = fk_table; -#endif /* MULTIBYTE */ - - /* Get to first foreign key */ - fkey_ptr = trig_args; - for (k = 0; k < 4; k++) - fkey_ptr += strlen(fkey_ptr) + 1; - - for (k = 0; k < num_keys; k++) - { -#ifdef MULTIBYTE - pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced); - fkey_text = getClientColumnName(conn, fk_table, fkey_ptr, &fkey_alloced); -#else - pkey_text = pkey_ptr; - fkey_text = fkey_ptr; -#endif /* MULTIBYTE */ - mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fkt_text, fkey_text); - - row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); - - mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text); - set_tuplefield_null(&row->tuple[0]); - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], pk_table_needed); - set_tuplefield_string(&row->tuple[3], pkey_text); - - mylog("fk_table = '%s', fkey_ptr = '%s'\n", fkt_text, fkey_text); - set_tuplefield_null(&row->tuple[4]); - set_tuplefield_string(&row->tuple[5], ""); - set_tuplefield_string(&row->tuple[6], fkt_text); - set_tuplefield_string(&row->tuple[7], fkey_text); - - set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1)); - - mylog("upd_rule = %d, del_rule= %d", upd_rule_type, del_rule_type); - set_nullfield_int2(&row->tuple[9], (Int2) upd_rule_type); - set_nullfield_int2(&row->tuple[10], (Int2) del_rule_type); - - set_tuplefield_null(&row->tuple[11]); - set_tuplefield_null(&row->tuple[12]); - - set_tuplefield_string(&row->tuple[13], trig_args); - -#if (ODBCVER >= 0x0300) - mylog("defer_type = '%s'", defer_type); - set_tuplefield_int2(&row->tuple[14], defer_type); -#endif /* ODBCVER >= 0x0300 */ - - QR_add_tuple(stmt->result, row); -#ifdef MULTIBYTE - if (pkey_alloced) - free(pkey_text); - pkey_alloced = FALSE; - if (fkey_alloced) - free(fkey_text); - fkey_alloced = FALSE; -#endif /* MULTIBYTE */ - - /* next primary/foreign key */ - for (j = 0; j < 2; j++) - { - pkey_ptr += strlen(pkey_ptr) + 1; - fkey_ptr += strlen(fkey_ptr) + 1; - } - } -#ifdef MULTIBYTE - if (fkt_alloced) - free(fkt_text); - fkt_alloced = FALSE; -#endif /* MULTIBYTE */ - result = PGAPI_Fetch(htbl_stmt); - } - } - else - { - stmt->errormsg = "No tables specified to PGAPI_ForeignKeys."; - stmt->errornumber = STMT_INTERNAL_ERROR; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } -#ifdef MULTIBYTE - if (pkt_alloced) - free(pkt_text); - if (pkey_alloced) - free(pkey_text); - if (fkt_alloced) - free(fkt_text); - if (fkey_alloced) - free(fkey_text); -#endif /* MULTIBYTE */ - - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - - mylog("PGAPI_ForeignKeys(): EXIT, stmt=%u\n", stmt); - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_ProcedureColumns( - HSTMT hstmt, - UCHAR FAR * szProcQualifier, - SWORD cbProcQualifier, - UCHAR FAR * szProcOwner, - SWORD cbProcOwner, - UCHAR FAR * szProcName, - SWORD cbProcName, - UCHAR FAR * szColumnName, - SWORD cbColumnName) -{ - static char *func = "PGAPI_ProcedureColumns"; - - mylog("%s: entering...\n", func); - - SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); - return SQL_ERROR; -} - - -RETCODE SQL_API -PGAPI_Procedures( - HSTMT hstmt, - UCHAR FAR * szProcQualifier, - SWORD cbProcQualifier, - UCHAR FAR * szProcOwner, - SWORD cbProcOwner, - UCHAR FAR * szProcName, - SWORD cbProcName) -{ - static char *func = "PGAPI_Procedures"; - StatementClass *stmt = (StatementClass *) hstmt; - ConnectionClass *conn = SC_get_conn(stmt); - char proc_query[INFO_INQUIRY_LEN]; - QResultClass *res; - - mylog("%s: entering...\n", func); - - if (PG_VERSION_LT(conn, 6.5)) - { - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Version is too old"; - SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); - return SQL_ERROR; - } - if (!SC_recycle_statement(stmt)) - return SQL_ERROR; - - /* - * The following seems the simplest implementation - */ - strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", '' as " "PROCEDURE_SCHEM" "," - " proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" "," - " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" "," - " '' as " "REMARKS" "," - " case when prorettype =0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc"); - my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName); - - res = CC_send_query(conn, proc_query, NULL); - if (!res || QR_aborted(res)) - { - if (res) - QR_Destructor(res); - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "PGAPI_Procedures query error"; - return SQL_ERROR; - } - stmt->result = res; - - /* - * also, things need to think that this statement is finished so the - * results can be retrieved. - */ - stmt->status = STMT_FINISHED; - extend_bindings(stmt, 8); - /* set up the current tuple pointer for SQLFetch */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_TablePrivileges( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName) -{ - StatementClass *stmt = (StatementClass *) hstmt; - static char *func = "PGAPI_TablePrivileges"; - Int2 result_cols; - - mylog("%s: entering...\n", func); - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - result_cols = 7; - extend_bindings(stmt, result_cols); - - /* set the field names */ - QR_set_num_fields(stmt->result, result_cols); - QR_set_field_info(stmt->result, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(stmt->result, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING); - - SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); - return SQL_ERROR; -} diff --git a/src/interfaces/odbc/windev/iodbc.h b/src/interfaces/odbc/windev/iodbc.h deleted file mode 100644 index f8e7d248b1..0000000000 --- a/src/interfaces/odbc/windev/iodbc.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _IODBC_H -#define _IODBC_H - -#if !defined(WIN32) && !defined(WIN32_SYSTEM) -#define _UNIX_ - -#include -#include - -#define MEM_ALLOC(size) (malloc((size_t)(size))) -#define MEM_FREE(ptr) \ -do { \ - if(ptr) \ - free(ptr); \ -} while (0) - -#define STRCPY(t, s) (strcpy((char*)(t), (char*)(s))) -#define STRNCPY(t,s,n) (strncpy((char*)(t), (char*)(s), (size_t)(n))) -#define STRCAT(t, s) (strcat((char*)(t), (char*)(s))) -#define STRNCAT(t,s,n) (strncat((char*)(t), (char*)(s), (size_t)(n))) -#define STREQ(a, b) (strcmp((char*)(a), (char*)(b)) == 0) -#define STRLEN(str) ((str)? strlen((char*)(str)):0) - -#define EXPORT -#define CALLBACK -#define FAR - -typedef signed short SSHOR; -typedef short WORD; -typedef long DWORD; - -typedef WORD WPARAM; -typedef DWORD LPARAM; -typedef void *HWND; -typedef int BOOL; -#endif /* _UNIX_ */ - -#if defined(WIN32) || defined(WIN32_SYSTEM) - -#include -#include - -#ifdef _MSVC_ -#define MEM_ALLOC(size) (fmalloc((size_t)(size))) -#define MEM_FREE(ptr) ((ptr)? ffree((PTR)(ptr)):0)) -#define STRCPY(t, s) (fstrcpy((char FAR*)(t), (char FAR*)(s))) -#define STRNCPY(t,s,n) (fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n))) -#define STRLEN(str) ((str)? fstrlen((char FAR*)(str)):0) -#define STREQ(a, b) (fstrcmp((char FAR*)(a), (char FAR*)(b) == 0) -#endif - -#ifdef _BORLAND_ -#define MEM_ALLOC(size) (farmalloc((unsigned long)(size)) -#define MEM_FREE(ptr) ((ptr)? farfree((void far*)(ptr)):0) -#define STRCPY(t, s) (_fstrcpy((char FAR*)(t), (char FAR*)(s))) -#define STRNCPY(t,s,n) (_fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n))) -#define STRLEN(str) ((str)? _fstrlen((char FAR*)(str)):0) -#define STREQ(a, b) (_fstrcmp((char FAR*)(a), (char FAR*)(b) == 0) -#endif -#endif /* WIN32 */ - -#define SYSERR (-1) - -#ifndef NULL -#define NULL ((void FAR*)0UL) -#endif - -#endif diff --git a/src/interfaces/odbc/windev/license.txt b/src/interfaces/odbc/windev/license.txt deleted file mode 100644 index bdf8ab0cb3..0000000000 --- a/src/interfaces/odbc/windev/license.txt +++ /dev/null @@ -1,962 +0,0 @@ - GNU LIBRARY GENERAL PUBLIC LICENSE - - Version 2, June 1991 - - - - Copyright (C) 1991 Free Software Foundation, Inc. - - 675 Mass Ave, Cambridge, MA 02139, USA - - Everyone is permitted to copy and distribute verbatim copies - - of this license document, but changing it is not allowed. - - - -[This is the first released version of the library GPL. It is - - numbered 2 because it goes with version 2 of the ordinary GPL.] - - - - Preamble - - - - The licenses for most software are designed to take away your - -freedom to share and change it. By contrast, the GNU General Public - -Licenses are intended to guarantee your freedom to share and change - -free software--to make sure the software is free for all its users. - - - - This license, the Library General Public License, applies to some - -specially designated Free Software Foundation software, and to any - -other libraries whose authors decide to use it. You can use it for - -your libraries, too. - - - - When we speak of free software, we are referring to freedom, not - -price. Our General Public Licenses are designed to make sure that you - -have the freedom to distribute copies of free software (and charge for - -this service if you wish), that you receive source code or can get it - -if you want it, that you can change the software or use pieces of it - -in new free programs; and that you know you can do these things. - - - - To protect your rights, we need to make restrictions that forbid - -anyone to deny you these rights or to ask you to surrender the rights. - -These restrictions translate to certain responsibilities for you if - -you distribute copies of the library, or if you modify it. - - - - For example, if you distribute copies of the library, whether gratis - -or for a fee, you must give the recipients all the rights that we gave - -you. You must make sure that they, too, receive or can get the source - -code. If you link a program with the library, you must provide - -complete object files to the recipients so that they can relink them - -with the library, after making changes to the library and recompiling - -it. And you must show them these terms so they know their rights. - - - - Our method of protecting your rights has two steps: (1) copyright - -the library, and (2) offer you this license which gives you legal - -permission to copy, distribute and/or modify the library. - - - - Also, for each distributor's protection, we want to make certain - -that everyone understands that there is no warranty for this free - -library. If the library is modified by someone else and passed on, we - -want its recipients to know that what they have is not the original - -version, so that any problems introduced by others will not reflect on - -the original authors' reputations. - - - - Finally, any free program is threatened constantly by software - -patents. We wish to avoid the danger that companies distributing free - -software will individually obtain patent licenses, thus in effect - -transforming the program into proprietary software. To prevent this, - -we have made it clear that any patent must be licensed for everyone's - -free use or not licensed at all. - - - - Most GNU software, including some libraries, is covered by the ordinary - -GNU General Public License, which was designed for utility programs. This - -license, the GNU Library General Public License, applies to certain - -designated libraries. This license is quite different from the ordinary - -one; be sure to read it in full, and don't assume that anything in it is - -the same as in the ordinary license. - - - - The reason we have a separate public license for some libraries is that - -they blur the distinction we usually make between modifying or adding to a - -program and simply using it. Linking a program with a library, without - -changing the library, is in some sense simply using the library, and is - -analogous to running a utility program or application program. However, in - -a textual and legal sense, the linked executable is a combined work, a - -derivative of the original library, and the ordinary General Public License - -treats it as such. - - - - Because of this blurred distinction, using the ordinary General - -Public License for libraries did not effectively promote software - -sharing, because most developers did not use the libraries. We - -concluded that weaker conditions might promote sharing better. - - - - However, unrestricted linking of non-free programs would deprive the - -users of those programs of all benefit from the free status of the - -libraries themselves. This Library General Public License is intended to - -permit developers of non-free programs to use free libraries, while - -preserving your freedom as a user of such programs to change the free - -libraries that are incorporated in them. (We have not seen how to achieve - -this as regards changes in header files, but we have achieved it as regards - -changes in the actual functions of the Library.) The hope is that this - -will lead to faster development of free libraries. - - - - The precise terms and conditions for copying, distribution and - -modification follow. Pay close attention to the difference between a - -"work based on the library" and a "work that uses the library". The - -former contains code derived from the library, while the latter only - -works together with the library. - - - - Note that it is possible for a library to be covered by the ordinary - -General Public License rather than by this special one. - - - - GNU LIBRARY GENERAL PUBLIC LICENSE - - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - - - 0. This License Agreement applies to any software library which - -contains a notice placed by the copyright holder or other authorized - -party saying it may be distributed under the terms of this Library - -General Public License (also called "this License"). Each licensee is - -addressed as "you". - - - - A "library" means a collection of software functions and/or data - -prepared so as to be conveniently linked with application programs - -(which use some of those functions and data) to form executables. - - - - The "Library", below, refers to any such software library or work - -which has been distributed under these terms. A "work based on the - -Library" means either the Library or any derivative work under - -copyright law: that is to say, a work containing the Library or a - -portion of it, either verbatim or with modifications and/or translated - -straightforwardly into another language. (Hereinafter, translation is - -included without limitation in the term "modification".) - - - - "Source code" for a work means the preferred form of the work for - -making modifications to it. For a library, complete source code means - -all the source code for all modules it contains, plus any associated - -interface definition files, plus the scripts used to control compilation - -and installation of the library. - - - - Activities other than copying, distribution and modification are not - -covered by this License; they are outside its scope. The act of - -running a program using the Library is not restricted, and output from - -such a program is covered only if its contents constitute a work based - -on the Library (independent of the use of the Library in a tool for - -writing it). Whether that is true depends on what the Library does - -and what the program that uses the Library does. - - - - 1. You may copy and distribute verbatim copies of the Library's - -complete source code as you receive it, in any medium, provided that - -you conspicuously and appropriately publish on each copy an - -appropriate copyright notice and disclaimer of warranty; keep intact - -all the notices that refer to this License and to the absence of any - -warranty; and distribute a copy of this License along with the - -Library. - - - - You may charge a fee for the physical act of transferring a copy, - -and you may at your option offer warranty protection in exchange for a - -fee. - - - - 2. You may modify your copy or copies of the Library or any portion - -of it, thus forming a work based on the Library, and copy and - -distribute such modifications or work under the terms of Section 1 - -above, provided that you also meet all of these conditions: - - - - a) The modified work must itself be a software library. - - - - b) You must cause the files modified to carry prominent notices - - stating that you changed the files and the date of any change. - - - - c) You must cause the whole of the work to be licensed at no - - charge to all third parties under the terms of this License. - - - - d) If a facility in the modified Library refers to a function or a - - table of data to be supplied by an application program that uses - - the facility, other than as an argument passed when the facility - - is invoked, then you must make a good faith effort to ensure that, - - in the event an application does not supply such function or - - table, the facility still operates, and performs whatever part of - - its purpose remains meaningful. - - - - (For example, a function in a library to compute square roots has - - a purpose that is entirely well-defined independent of the - - application. Therefore, Subsection 2d requires that any - - application-supplied function or table used by this function must - - be optional: if the application does not supply it, the square - - root function must still compute square roots.) - - - -These requirements apply to the modified work as a whole. If - -identifiable sections of that work are not derived from the Library, - -and can be reasonably considered independent and separate works in - -themselves, then this License, and its terms, do not apply to those - -sections when you distribute them as separate works. But when you - -distribute the same sections as part of a whole which is a work based - -on the Library, the distribution of the whole must be on the terms of - -this License, whose permissions for other licensees extend to the - -entire whole, and thus to each and every part regardless of who wrote - -it. - - - -Thus, it is not the intent of this section to claim rights or contest - -your rights to work written entirely by you; rather, the intent is to - -exercise the right to control the distribution of derivative or - -collective works based on the Library. - - - -In addition, mere aggregation of another work not based on the Library - -with the Library (or with a work based on the Library) on a volume of - -a storage or distribution medium does not bring the other work under - -the scope of this License. - - - - 3. You may opt to apply the terms of the ordinary GNU General Public - -License instead of this License to a given copy of the Library. To do - -this, you must alter all the notices that refer to this License, so - -that they refer to the ordinary GNU General Public License, version 2, - -instead of to this License. (If a newer version than version 2 of the - -ordinary GNU General Public License has appeared, then you can specify - -that version instead if you wish.) Do not make any other change in - -these notices. - - - - Once this change is made in a given copy, it is irreversible for - -that copy, so the ordinary GNU General Public License applies to all - -subsequent copies and derivative works made from that copy. - - - - This option is useful when you wish to copy part of the code of - -the Library into a program that is not a library. - - - - 4. You may copy and distribute the Library (or a portion or - -derivative of it, under Section 2) in object code or executable form - -under the terms of Sections 1 and 2 above provided that you accompany - -it with the complete corresponding machine-readable source code, which - -must be distributed under the terms of Sections 1 and 2 above on a - -medium customarily used for software interchange. - - - - If distribution of object code is made by offering access to copy - -from a designated place, then offering equivalent access to copy the - -source code from the same place satisfies the requirement to - -distribute the source code, even though third parties are not - -compelled to copy the source along with the object code. - - - - 5. A program that contains no derivative of any portion of the - -Library, but is designed to work with the Library by being compiled or - -linked with it, is called a "work that uses the Library". Such a - -work, in isolation, is not a derivative work of the Library, and - -therefore falls outside the scope of this License. - - - - However, linking a "work that uses the Library" with the Library - -creates an executable that is a derivative of the Library (because it - -contains portions of the Library), rather than a "work that uses the - -library". The executable is therefore covered by this License. - -Section 6 states terms for distribution of such executables. - - - - When a "work that uses the Library" uses material from a header file - -that is part of the Library, the object code for the work may be a - -derivative work of the Library even though the source code is not. - -Whether this is true is especially significant if the work can be - -linked without the Library, or if the work is itself a library. The - -threshold for this to be true is not precisely defined by law. - - - - If such an object file uses only numerical parameters, data - -structure layouts and accessors, and small macros and small inline - -functions (ten lines or less in length), then the use of the object - -file is unrestricted, regardless of whether it is legally a derivative - -work. (Executables containing this object code plus portions of the - -Library will still fall under Section 6.) - - - - Otherwise, if the work is a derivative of the Library, you may - -distribute the object code for the work under the terms of Section 6. - -Any executables containing that work also fall under Section 6, - -whether or not they are linked directly with the Library itself. - - - - 6. As an exception to the Sections above, you may also compile or - -link a "work that uses the Library" with the Library to produce a - -work containing portions of the Library, and distribute that work - -under terms of your choice, provided that the terms permit - -modification of the work for the customer's own use and reverse - -engineering for debugging such modifications. - - - - You must give prominent notice with each copy of the work that the - -Library is used in it and that the Library and its use are covered by - -this License. You must supply a copy of this License. If the work - -during execution displays copyright notices, you must include the - -copyright notice for the Library among them, as well as a reference - -directing the user to the copy of this License. Also, you must do one - -of these things: - - - - a) Accompany the work with the complete corresponding - - machine-readable source code for the Library including whatever - - changes were used in the work (which must be distributed under - - Sections 1 and 2 above); and, if the work is an executable linked - - with the Library, with the complete machine-readable "work that - - uses the Library", as object code and/or source code, so that the - - user can modify the Library and then relink to produce a modified - - executable containing the modified Library. (It is understood - - that the user who changes the contents of definitions files in the - - Library will not necessarily be able to recompile the application - - to use the modified definitions.) - - - - b) Accompany the work with a written offer, valid for at - - least three years, to give the same user the materials - - specified in Subsection 6a, above, for a charge no more - - than the cost of performing this distribution. - - - - c) If distribution of the work is made by offering access to copy - - from a designated place, offer equivalent access to copy the above - - specified materials from the same place. - - - - d) Verify that the user has already received a copy of these - - materials or that you have already sent this user a copy. - - - - For an executable, the required form of the "work that uses the - -Library" must include any data and utility programs needed for - -reproducing the executable from it. However, as a special exception, - -the source code distributed need not include anything that is normally - -distributed (in either source or binary form) with the major - -components (compiler, kernel, and so on) of the operating system on - -which the executable runs, unless that component itself accompanies - -the executable. - - - - It may happen that this requirement contradicts the license - -restrictions of other proprietary libraries that do not normally - -accompany the operating system. Such a contradiction means you cannot - -use both them and the Library together in an executable that you - -distribute. - - - - 7. You may place library facilities that are a work based on the - -Library side-by-side in a single library together with other library - -facilities not covered by this License, and distribute such a combined - -library, provided that the separate distribution of the work based on - -the Library and of the other library facilities is otherwise - -permitted, and provided that you do these two things: - - - - a) Accompany the combined library with a copy of the same work - - based on the Library, uncombined with any other library - - facilities. This must be distributed under the terms of the - - Sections above. - - - - b) Give prominent notice with the combined library of the fact - - that part of it is a work based on the Library, and explaining - - where to find the accompanying uncombined form of the same work. - - - - 8. You may not copy, modify, sublicense, link with, or distribute - -the Library except as expressly provided under this License. Any - -attempt otherwise to copy, modify, sublicense, link with, or - -distribute the Library is void, and will automatically terminate your - -rights under this License. However, parties who have received copies, - -or rights, from you under this License will not have their licenses - -terminated so long as such parties remain in full compliance. - - - - 9. You are not required to accept this License, since you have not - -signed it. However, nothing else grants you permission to modify or - -distribute the Library or its derivative works. These actions are - -prohibited by law if you do not accept this License. Therefore, by - -modifying or distributing the Library (or any work based on the - -Library), you indicate your acceptance of this License to do so, and - -all its terms and conditions for copying, distributing or modifying - -the Library or works based on it. - - - - 10. Each time you redistribute the Library (or any work based on the - -Library), the recipient automatically receives a license from the - -original licensor to copy, distribute, link with or modify the Library - -subject to these terms and conditions. You may not impose any further - -restrictions on the recipients' exercise of the rights granted herein. - -You are not responsible for enforcing compliance by third parties to - -this License. - - - - 11. If, as a consequence of a court judgment or allegation of patent - -infringement or for any other reason (not limited to patent issues), - -conditions are imposed on you (whether by court order, agreement or - -otherwise) that contradict the conditions of this License, they do not - -excuse you from the conditions of this License. If you cannot - -distribute so as to satisfy simultaneously your obligations under this - -License and any other pertinent obligations, then as a consequence you - -may not distribute the Library at all. For example, if a patent - -license would not permit royalty-free redistribution of the Library by - -all those who receive copies directly or indirectly through you, then - -the only way you could satisfy both it and this License would be to - -refrain entirely from distribution of the Library. - - - -If any portion of this section is held invalid or unenforceable under any - -particular circumstance, the balance of the section is intended to apply, - -and the section as a whole is intended to apply in other circumstances. - - - -It is not the purpose of this section to induce you to infringe any - -patents or other property right claims or to contest validity of any - -such claims; this section has the sole purpose of protecting the - -integrity of the free software distribution system which is - -implemented by public license practices. Many people have made - -generous contributions to the wide range of software distributed - -through that system in reliance on consistent application of that - -system; it is up to the author/donor to decide if he or she is willing - -to distribute software through any other system and a licensee cannot - -impose that choice. - - - -This section is intended to make thoroughly clear what is believed to - -be a consequence of the rest of this License. - - - - 12. If the distribution and/or use of the Library is restricted in - -certain countries either by patents or by copyrighted interfaces, the - -original copyright holder who places the Library under this License may add - -an explicit geographical distribution limitation excluding those countries, - -so that distribution is permitted only in or among countries not thus - -excluded. In such case, this License incorporates the limitation as if - -written in the body of this License. - - - - 13. The Free Software Foundation may publish revised and/or new - -versions of the Library General Public License from time to time. - -Such new versions will be similar in spirit to the present version, - -but may differ in detail to address new problems or concerns. - - - -Each version is given a distinguishing version number. If the Library - -specifies a version number of this License which applies to it and - -"any later version", you have the option of following the terms and - -conditions either of that version or of any later version published by - -the Free Software Foundation. If the Library does not specify a - -license version number, you may choose any version ever published by - -the Free Software Foundation. - - - - 14. If you wish to incorporate parts of the Library into other free - -programs whose distribution conditions are incompatible with these, - -write to the author to ask for permission. For software which is - -copyrighted by the Free Software Foundation, write to the Free - -Software Foundation; we sometimes make exceptions for this. Our - -decision will be guided by the two goals of preserving the free status - -of all derivatives of our free software and of promoting the sharing - -and reuse of software generally. - - - - NO WARRANTY - - - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO - -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. - -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR - -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY - -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE - -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME - -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN - -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY - -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU - -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR - -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE - -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING - -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A - -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF - -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - -DAMAGES. - - - - END OF TERMS AND CONDITIONS - - - - Appendix: How to Apply These Terms to Your New Libraries - - - - If you develop a new library, and you want it to be of the greatest - -possible use to the public, we recommend making it free software that - -everyone can redistribute and change. You can do so by permitting - -redistribution under these terms (or, alternatively, under the terms of the - -ordinary General Public License). - - - - To apply these terms, attach the following notices to the library. It is - -safest to attach them to the start of each source file to most effectively - -convey the exclusion of warranty; and each file should have at least the - -"copyright" line and a pointer to where the full notice is found. - - - - - - Copyright (C) - - - - This library is free software; you can redistribute it and/or - - modify it under the terms of the GNU Library General Public - - License as published by the Free Software Foundation; either - - version 2 of the License, or (at your option) any later version. - - - - This library is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - - Library General Public License for more details. - - - - You should have received a copy of the GNU Library General Public - - License along with this library; if not, write to the Free - - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - - -Also add information on how to contact you by electronic and paper mail. - - - -You should also get your employer (if you work as a programmer) or your - -school, if any, to sign a "copyright disclaimer" for the library, if - -necessary. Here is a sample; alter the names: - - - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - - - , 1 April 1990 - - Ty Coon, President of Vice - - - -That's all there is to it! - diff --git a/src/interfaces/odbc/windev/lobj.c b/src/interfaces/odbc/windev/lobj.c deleted file mode 100644 index 6b55b82d54..0000000000 --- a/src/interfaces/odbc/windev/lobj.c +++ /dev/null @@ -1,186 +0,0 @@ -/*-------- - * Module: lobj.c - * - * Description: This module contains routines related to manipulating - * large objects. - * - * Classes: none - * - * API functions: none - * - * Comments: See "notice.txt" for copyright and license information. - *-------- - */ - -#include "lobj.h" - -#include "connection.h" - - -Oid -lo_creat(ConnectionClass *conn, int mode) -{ - LO_ARG argv[1]; - int retval, - result_len; - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = mode; - - if (!CC_send_function(conn, LO_CREAT, &retval, &result_len, 1, argv, 1)) - return 0; /* invalid oid */ - else - return retval; -} - - -int -lo_open(ConnectionClass *conn, int lobjId, int mode) -{ - int fd; - int result_len; - LO_ARG argv[2]; - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = lobjId; - - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = mode; - - if (!CC_send_function(conn, LO_OPEN, &fd, &result_len, 1, argv, 2)) - return -1; - - if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0) - return -1; - - return fd; -} - - -int -lo_close(ConnectionClass *conn, int fd) -{ - LO_ARG argv[1]; - 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; - - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = len; - - if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2)) - return -1; - else - return result_len; -} - - -int -lo_write(ConnectionClass *conn, int fd, char *buf, int len) -{ - LO_ARG argv[2]; - int retval, - result_len; - - if (len <= 0) - return 0; - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; - - argv[1].isint = 0; - argv[1].len = len; - argv[1].u.ptr = (char *) buf; - - if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2)) - return -1; - else - return retval; -} - - -int -lo_lseek(ConnectionClass *conn, int fd, int offset, int whence) -{ - LO_ARG argv[3]; - int retval, - result_len; - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; - - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = offset; - - argv[2].isint = 1; - argv[2].len = 4; - argv[2].u.integer = whence; - - if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3)) - return -1; - else - return retval; -} - - -int -lo_tell(ConnectionClass *conn, int fd) -{ - LO_ARG argv[1]; - 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; -} - - -int -lo_unlink(ConnectionClass *conn, Oid lobjId) -{ - LO_ARG argv[1]; - 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; -} diff --git a/src/interfaces/odbc/windev/lobj.h b/src/interfaces/odbc/windev/lobj.h deleted file mode 100644 index 4d720488a0..0000000000 --- a/src/interfaces/odbc/windev/lobj.h +++ /dev/null @@ -1,47 +0,0 @@ -/* File: lobj.h - * - * Description: See "lobj.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __LOBJ_H__ -#define __LOBJ_H__ - - -#include "psqlodbc.h" - -struct lo_arg -{ - int isint; - int len; - union - { - int integer; - char *ptr; - } u; -}; - -#define LO_CREAT 957 -#define LO_OPEN 952 -#define LO_CLOSE 953 -#define LO_READ 954 -#define LO_WRITE 955 -#define LO_LSEEK 956 -#define LO_TELL 958 -#define LO_UNLINK 964 - -#define INV_WRITE 0x00020000 -#define INV_READ 0x00040000 - -Oid lo_creat(ConnectionClass *conn, int mode); -int lo_open(ConnectionClass *conn, int lobjId, int mode); -int lo_close(ConnectionClass *conn, int fd); -int lo_read(ConnectionClass *conn, int fd, char *buf, int len); -int lo_write(ConnectionClass *conn, int fd, char *buf, int len); -int lo_lseek(ConnectionClass *conn, int fd, int offset, int len); -int lo_tell(ConnectionClass *conn, int fd); -int lo_unlink(ConnectionClass *conn, Oid lobjId); - -#endif diff --git a/src/interfaces/odbc/windev/md5.c b/src/interfaces/odbc/windev/md5.c deleted file mode 100644 index da32380dde..0000000000 --- a/src/interfaces/odbc/windev/md5.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * md5.c - * - * Implements the MD5 Message-Digest Algorithm as specified in - * RFC 1321. This implementation is a simple one, in that it - * needs every input byte to be buffered before doing any - * calculations. I do not expect this file to be used for - * general purpose MD5'ing of large amounts of data, only for - * generating hashed passwords from limited input. - * - * Sverre H. Huseby - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/odbc/windev/Attic/md5.c,v 1.1 2002/01/11 02:50:01 inoue Exp $ - */ - - -/* - * NOTE: - * - * There are two copies of this file, one in backend/libpq and another - * in interfaces/odbc. They should be identical. This is done so ODBC - * can be compiled stand-alone. - */ - -#ifndef MD5_ODBC -#include "postgres.h" -#include "libpq/crypt.h" -#else -#include "md5.h" -#endif - -#ifdef FRONTEND -#undef palloc -#define palloc malloc -#undef pfree -#define pfree free -#endif - - -/* - * PRIVATE FUNCTIONS - */ - - -/* - * The returned array is allocated using malloc. the caller should free it - * when it is no longer needed. - */ -static uint8 * -createPaddedCopyWithLength(uint8 *b, uint32 *l) -{ - uint8 *ret; - uint32 q; - uint32 len, - newLen448; - uint32 len_high, - len_low; /* 64-bit value split into 32-bit sections */ - - len = ((b == NULL) ? 0 : *l); - newLen448 = len + 64 - (len % 64) - 8; - if (newLen448 <= len) - newLen448 += 64; - - *l = newLen448 + 8; - if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL) - return NULL; - - if (b != NULL) - memcpy(ret, b, sizeof(uint8) * len); - - /* pad */ - ret[len] = 0x80; - for (q = len + 1; q < newLen448; q++) - ret[q] = 0x00; - - /* append length as a 64 bit bitcount */ - len_low = len; - /* split into two 32-bit values */ - /* we only look at the bottom 32-bits */ - len_high = len >> 29; - len_low <<= 3; - q = newLen448; - ret[q++] = (len_low & 0xff); - len_low >>= 8; - ret[q++] = (len_low & 0xff); - len_low >>= 8; - ret[q++] = (len_low & 0xff); - len_low >>= 8; - ret[q++] = (len_low & 0xff); - ret[q++] = (len_high & 0xff); - len_high >>= 8; - ret[q++] = (len_high & 0xff); - len_high >>= 8; - ret[q++] = (len_high & 0xff); - len_high >>= 8; - ret[q] = (len_high & 0xff); - - return ret; -} - -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define ROT_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - -static void -doTheRounds(uint32 X[16], uint32 state[4]) -{ - uint32 a, - b, - c, - d; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - - /* round 1 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[0] + 0xd76aa478), 7); /* 1 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[1] + 0xe8c7b756), 12); /* 2 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[2] + 0x242070db), 17); /* 3 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[3] + 0xc1bdceee), 22); /* 4 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[4] + 0xf57c0faf), 7); /* 5 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[5] + 0x4787c62a), 12); /* 6 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[6] + 0xa8304613), 17); /* 7 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[7] + 0xfd469501), 22); /* 8 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[8] + 0x698098d8), 7); /* 9 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[9] + 0x8b44f7af), 12); /* 10 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[10] + 0xffff5bb1), 17); /* 11 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[11] + 0x895cd7be), 22); /* 12 */ - a = b + ROT_LEFT((a + F(b, c, d) + X[12] + 0x6b901122), 7); /* 13 */ - d = a + ROT_LEFT((d + F(a, b, c) + X[13] + 0xfd987193), 12); /* 14 */ - c = d + ROT_LEFT((c + F(d, a, b) + X[14] + 0xa679438e), 17); /* 15 */ - b = c + ROT_LEFT((b + F(c, d, a) + X[15] + 0x49b40821), 22); /* 16 */ - - /* round 2 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[1] + 0xf61e2562), 5); /* 17 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[6] + 0xc040b340), 9); /* 18 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[11] + 0x265e5a51), 14); /* 19 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[0] + 0xe9b6c7aa), 20); /* 20 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[5] + 0xd62f105d), 5); /* 21 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[10] + 0x02441453), 9); /* 22 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[15] + 0xd8a1e681), 14); /* 23 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[4] + 0xe7d3fbc8), 20); /* 24 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[9] + 0x21e1cde6), 5); /* 25 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[14] + 0xc33707d6), 9); /* 26 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[3] + 0xf4d50d87), 14); /* 27 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[8] + 0x455a14ed), 20); /* 28 */ - a = b + ROT_LEFT((a + G(b, c, d) + X[13] + 0xa9e3e905), 5); /* 29 */ - d = a + ROT_LEFT((d + G(a, b, c) + X[2] + 0xfcefa3f8), 9); /* 30 */ - c = d + ROT_LEFT((c + G(d, a, b) + X[7] + 0x676f02d9), 14); /* 31 */ - b = c + ROT_LEFT((b + G(c, d, a) + X[12] + 0x8d2a4c8a), 20); /* 32 */ - - /* round 3 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[5] + 0xfffa3942), 4); /* 33 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[8] + 0x8771f681), 11); /* 34 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[11] + 0x6d9d6122), 16); /* 35 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[14] + 0xfde5380c), 23); /* 36 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[1] + 0xa4beea44), 4); /* 37 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[4] + 0x4bdecfa9), 11); /* 38 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[7] + 0xf6bb4b60), 16); /* 39 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[10] + 0xbebfbc70), 23); /* 40 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[13] + 0x289b7ec6), 4); /* 41 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[0] + 0xeaa127fa), 11); /* 42 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[3] + 0xd4ef3085), 16); /* 43 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[6] + 0x04881d05), 23); /* 44 */ - a = b + ROT_LEFT((a + H(b, c, d) + X[9] + 0xd9d4d039), 4); /* 45 */ - d = a + ROT_LEFT((d + H(a, b, c) + X[12] + 0xe6db99e5), 11); /* 46 */ - c = d + ROT_LEFT((c + H(d, a, b) + X[15] + 0x1fa27cf8), 16); /* 47 */ - b = c + ROT_LEFT((b + H(c, d, a) + X[2] + 0xc4ac5665), 23); /* 48 */ - - /* round 4 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[0] + 0xf4292244), 6); /* 49 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[7] + 0x432aff97), 10); /* 50 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[14] + 0xab9423a7), 15); /* 51 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[5] + 0xfc93a039), 21); /* 52 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[12] + 0x655b59c3), 6); /* 53 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[3] + 0x8f0ccc92), 10); /* 54 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[10] + 0xffeff47d), 15); /* 55 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[1] + 0x85845dd1), 21); /* 56 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[8] + 0x6fa87e4f), 6); /* 57 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[15] + 0xfe2ce6e0), 10); /* 58 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[6] + 0xa3014314), 15); /* 59 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[13] + 0x4e0811a1), 21); /* 60 */ - a = b + ROT_LEFT((a + I(b, c, d) + X[4] + 0xf7537e82), 6); /* 61 */ - d = a + ROT_LEFT((d + I(a, b, c) + X[11] + 0xbd3af235), 10); /* 62 */ - c = d + ROT_LEFT((c + I(d, a, b) + X[2] + 0x2ad7d2bb), 15); /* 63 */ - b = c + ROT_LEFT((b + I(c, d, a) + X[9] + 0xeb86d391), 21); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; -} - -static int -calculateDigestFromBuffer(uint8 *b, uint32 len, uint8 sum[16]) -{ - register uint32 i, - j, - k, - newI; - uint32 l; - uint8 *input; - register uint32 *wbp; - uint32 workBuff[16], - state[4]; - - l = len; - - state[0] = 0x67452301; - state[1] = 0xEFCDAB89; - state[2] = 0x98BADCFE; - state[3] = 0x10325476; - - if ((input = createPaddedCopyWithLength(b, &l)) == NULL) - return 0; - - for (i = 0;;) - { - if ((newI = i + 16 * 4) > l) - break; - k = i + 3; - for (j = 0; j < 16; j++) - { - wbp = (workBuff + j); - *wbp = input[k--]; - *wbp <<= 8; - *wbp |= input[k--]; - *wbp <<= 8; - *wbp |= input[k--]; - *wbp <<= 8; - *wbp |= input[k]; - k += 7; - } - doTheRounds(workBuff, state); - i = newI; - } - free(input); - - j = 0; - for (i = 0; i < 4; i++) - { - k = state[i]; - sum[j++] = (k & 0xff); - k >>= 8; - sum[j++] = (k & 0xff); - k >>= 8; - sum[j++] = (k & 0xff); - k >>= 8; - sum[j++] = (k & 0xff); - } - return 1; -} - -static void -bytesToHex(uint8 b[16], char *s) -{ - static char *hex = "0123456789abcdef"; - int q, - w; - - for (q = 0, w = 0; q < 16; q++) - { - s[w++] = hex[(b[q] >> 4) & 0x0F]; - s[w++] = hex[b[q] & 0x0F]; - } - s[w] = '\0'; -} - -/* - * PUBLIC FUNCTIONS - */ - -/* - * md5_hash - * - * Calculates the MD5 sum of the bytes in a buffer. - * - * SYNOPSIS #include "crypt.h" - * int md5_hash(const void *buff, size_t len, char *hexsum) - * - * INPUT buff the buffer containing the bytes that you want - * the MD5 sum of. - * len number of bytes in the buffer. - * - * OUTPUT hexsum the MD5 sum as a '\0'-terminated string of - * hexadecimal digits. an MD5 sum is 16 bytes long. - * each byte is represented by two heaxadecimal - * characters. you thus need to provide an array - * of 33 characters, including the trailing '\0'. - * - * RETURNS 0 on failure (out of memory for internal buffers) or - * non-zero on success. - * - * STANDARDS MD5 is described in RFC 1321. - * - * AUTHOR Sverre H. Huseby - * - */ -bool -md5_hash(const void *buff, size_t len, char *hexsum) -{ - uint8 sum[16]; - - if (!calculateDigestFromBuffer((uint8 *) buff, len, sum)) - return false; - - bytesToHex(sum, hexsum); - return true; -} - - - -/* - * Computes MD5 checksum of "passwd" (a null-terminated string) followed - * by "salt" (which need not be null-terminated). - * - * Output format is "md5" followed by a 32-hex-digit MD5 checksum. - * Hence, the output buffer "buf" must be at least 36 bytes long. - * - * Returns TRUE if okay, FALSE on error (out of memory). - */ -bool -EncryptMD5(const char *passwd, const char *salt, size_t salt_len, - char *buf) -{ - size_t passwd_len = strlen(passwd); - char *crypt_buf = palloc(passwd_len + salt_len); - bool ret; - - /* - * Place salt at the end because it may be known by users trying to - * crack the MD5 output. - */ - strcpy(crypt_buf, passwd); - memcpy(crypt_buf + passwd_len, salt, salt_len); - - strcpy(buf, "md5"); - ret = md5_hash(crypt_buf, passwd_len + salt_len, buf + 3); - - pfree(crypt_buf); - - return ret; -} diff --git a/src/interfaces/odbc/windev/md5.h b/src/interfaces/odbc/windev/md5.h deleted file mode 100644 index 2e2429d33d..0000000000 --- a/src/interfaces/odbc/windev/md5.h +++ /dev/null @@ -1,49 +0,0 @@ -/* File: md5.h - * - * Description: See "md5.h" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __MD5_H__ -#define __MD5_H__ - -#include "psqlodbc.h" - -#include -#include - -#define MD5_PASSWD_LEN 35 - -/* From c.h */ -#ifndef __BEOS__ - -#ifndef __cplusplus - -#ifndef bool -typedef char bool; -#endif - -#ifndef true -#define true ((bool) 1) -#endif - -#ifndef false -#define false ((bool) 0) -#endif -#endif /* not C++ */ -#endif /* __BEOS__ */ - -/* Also defined in include/c.h */ -#ifndef HAVE_UINT8 -typedef unsigned char uint8; /* == 8 bits */ -typedef unsigned short uint16; /* == 16 bits */ -typedef unsigned int uint32; /* == 32 bits */ -#endif /* not HAVE_UINT8 */ - -extern bool md5_hash(const void *buff, size_t len, char *hexsum); -extern bool EncryptMD5(const char *passwd, const char *salt, - size_t salt_len, char *buf); - -#endif diff --git a/src/interfaces/odbc/windev/misc.c b/src/interfaces/odbc/windev/misc.c deleted file mode 100644 index 443d1f47b3..0000000000 --- a/src/interfaces/odbc/windev/misc.c +++ /dev/null @@ -1,306 +0,0 @@ -/*------- - * Module: misc.c - * - * Description: This module contains miscellaneous routines - * such as for debugging/logging and string functions. - * - * Classes: n/a - * - * API functions: none - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "psqlodbc.h" - -#include -#include -#include - -#ifndef WIN32 -#if HAVE_PWD_H -#include -#endif -#include -#include -#else -#include /* Byron: is this where Windows keeps def. - * of getpid ? */ -#endif - -extern GLOBAL_VALUES globals; -void generate_filename(const char *, const char *, char *); - - -void -generate_filename(const char *dirname, const char *prefix, char *filename) -{ - int pid = 0; - -#ifndef WIN32 - struct passwd *ptr = 0; - - ptr = getpwuid(getuid()); -#endif - pid = getpid(); - if (dirname == 0 || filename == 0) - return; - - strcpy(filename, dirname); - strcat(filename, DIRSEPARATOR); - if (prefix != 0) - strcat(filename, prefix); -#ifndef WIN32 - strcat(filename, ptr->pw_name); -#endif - sprintf(filename, "%s%u%s", filename, pid, ".log"); - return; -} - -static int mylog_on = 0, - qlog_on = 0; -void -logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff) -{ - static int mylog_on_count = 0, - mylog_off_count = 0, - qlog_on_count = 0, - qlog_off_count = 0; - - if (mylog_onoff) - mylog_on_count += cnopen; - else - mylog_off_count += cnopen; - if (mylog_on_count > 0) - mylog_on = 1; - else if (mylog_off_count > 0) - mylog_on = 0; - else - mylog_on = globals.debug; - if (qlog_onoff) - qlog_on_count += cnopen; - else - qlog_off_count += cnopen; - if (qlog_on_count > 0) - qlog_on = 1; - else if (qlog_off_count > 0) - qlog_on = 0; - else - qlog_on = globals.commlog; -} - -#ifdef MY_LOG -void -mylog(char *fmt,...) -{ - va_list args; - char filebuf[80]; - static FILE *LOGFP = NULL; - - if (mylog_on) - { - va_start(args, fmt); - - if (!LOGFP) - { - generate_filename(MYLOGDIR, MYLOGFILE, filebuf); - LOGFP = fopen(filebuf, PG_BINARY_W); - setbuf(LOGFP, NULL); - } - - if (LOGFP) - vfprintf(LOGFP, fmt, args); - - va_end(args); - } -} -#endif - - -#ifdef Q_LOG -void -qlog(char *fmt,...) -{ - va_list args; - char filebuf[80]; - static FILE *LOGFP = NULL; - - if (qlog_on) - { - va_start(args, fmt); - - if (!LOGFP) - { - generate_filename(QLOGDIR, QLOGFILE, filebuf); - LOGFP = fopen(filebuf, PG_BINARY_W); - setbuf(LOGFP, NULL); - } - - if (LOGFP) - vfprintf(LOGFP, fmt, args); - - va_end(args); - } -} -#endif - - -/* - * returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied - * (not including null term) - */ -int -my_strcpy(char *dst, int dst_len, const char *src, int src_len) -{ - if (dst_len <= 0) - return STRCPY_FAIL; - - if (src_len == SQL_NULL_DATA) - { - dst[0] = '\0'; - return STRCPY_NULL; - } - else if (src_len == SQL_NTS) - src_len = strlen(src); - - if (src_len <= 0) - return STRCPY_FAIL; - else - { - if (src_len < dst_len) - { - memcpy(dst, src, src_len); - dst[src_len] = '\0'; - } - else - { - memcpy(dst, src, dst_len - 1); - dst[dst_len - 1] = '\0'; /* truncated */ - return STRCPY_TRUNCATED; - } - } - - 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) -{ - int i; - - - if (NULL != dst) - { - /* Just in case, check for special lengths */ - if (len == SQL_NULL_DATA) - { - dst[0] = '\0'; - return NULL; - } - else if (len == SQL_NTS) - len = strlen(src) + 1; - - for (i = 0; src[i] && i < len - 1; i++) - dst[i] = src[i]; - - if (len > 0) - dst[i] = '\0'; - } - 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(const char *s, int len, char *buf) -{ - int length; - char *str; - - if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) - { - length = (len > 0) ? len : strlen(s); - - if (buf) - { - strncpy_null(buf, s, length + 1); - return buf; - } - - str = malloc(length + 1); - if (!str) - return NULL; - - strncpy_null(str, s, length + 1); - return str; - } - - 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, const char *fmt, const char *s, int len) -{ - if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) - { - int length = (len > 0) ? len : strlen(s); - - int pos = strlen(buf); - - sprintf(&buf[pos], fmt, length, s); - return buf; - } - return NULL; -} - - -void -remove_newlines(char *string) -{ - unsigned int i; - - for (i = 0; i < strlen(string); i++) - { - if ((string[i] == '\n') || - (string[i] == '\r')) - string[i] = ' '; - } -} - - -char * -trim(char *s) -{ - int i; - - for (i = strlen(s) - 1; i >= 0; i--) - { - if (s[i] == ' ') - s[i] = '\0'; - else - break; - } - - return s; -} diff --git a/src/interfaces/odbc/windev/misc.h b/src/interfaces/odbc/windev/misc.h deleted file mode 100644 index 5cedd4c147..0000000000 --- a/src/interfaces/odbc/windev/misc.h +++ /dev/null @@ -1,98 +0,0 @@ -/* File: misc.h - * - * Description: See "misc.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __MISC_H__ -#define __MISC_H__ - -#include "psqlodbc.h" - -#include - -/* Uncomment MY_LOG define to compile in the mylog() statements. - Then, debug logging will occur if 'Debug' is set to 1 in the ODBCINST.INI - portion of the registry. You may have to manually add this key. - This logfile is intended for development use, not for an end user! -*/ -#define MY_LOG - - -/* Uncomment Q_LOG to compile in the qlog() statements (Communications log, i.e. CommLog). - This logfile contains serious log statements that are intended for an - end user to be able to read and understand. It is controlled by the - 'CommLog' flag in the ODBCINST.INI portion of the registry (see above), - which is manipulated on the setup/connection dialog boxes. -*/ -#define Q_LOG - - -#ifdef MY_LOG -#define MYLOGFILE "mylog_" -#ifndef WIN32 -#define MYLOGDIR "/tmp" -#else -#define MYLOGDIR "c:" -#endif -extern void mylog(char *fmt,...); - -#else -#ifndef WIN32 -#define mylog(args...) /* GNU convention for variable arguments */ -#else -#define mylog /* mylog */ -#endif -#endif - -#ifdef Q_LOG -#define QLOGFILE "psqlodbc_" -#ifndef WIN32 -#define QLOGDIR "/tmp" -#else -#define QLOGDIR "c:" -#endif -extern void qlog(char *fmt,...); - -#else -#ifndef WIN32 -#define qlog(args...) /* GNU convention for variable arguments */ -#else -#define qlog /* qlog */ -#endif -#endif - -#ifndef WIN32 -#define DIRSEPARATOR "/" -#else -#define DIRSEPARATOR "\\" -#endif - -#ifdef WIN32 -#define PG_BINARY O_BINARY -#define PG_BINARY_R "rb" -#define PG_BINARY_W "wb" -#else -#define PG_BINARY 0 -#define PG_BINARY_R "r" -#define PG_BINARY_W "w" -#endif - - -void remove_newlines(char *string); -char *strncpy_null(char *dst, const char *src, int len); -char *trim(char *string); -char *make_string(const char *s, int len, char *buf); -char *my_strcat(char *buf, const char *fmt, const char *s, int len); - -/* defines for return value of my_strcpy */ -#define STRCPY_SUCCESS 1 -#define STRCPY_FAIL 0 -#define STRCPY_TRUNCATED (-1) -#define STRCPY_NULL (-2) - -int my_strcpy(char *dst, int dst_len, const char *src, int src_len); - -#endif diff --git a/src/interfaces/odbc/windev/multibyte.c b/src/interfaces/odbc/windev/multibyte.c deleted file mode 100644 index b19af2764c..0000000000 --- a/src/interfaces/odbc/windev/multibyte.c +++ /dev/null @@ -1,138 +0,0 @@ -/*-------- - * Module : multibyte.c - * - * Description: Mlutibyte related additional function. - * - * Create 2001-03-03 Eiji Tokuya - *-------- - */ - -#include "multibyte.h" -#include - -int multibyte_client_encoding; /* Multibyte Client Encoding. */ -int multibyte_status; /* Multibyte Odds and ends character. */ - - -unsigned char * -multibyte_strchr(unsigned char *s, unsigned char c) -{ - int mb_st = 0, - i = 0; - - while (!(mb_st == 0 && (s[i] == c || s[i] == 0))) - { - if (s[i] == 0) - return (0); - switch (multibyte_client_encoding) - { - case SJIS: - { - if (mb_st < 2 && s[i] > 0x80 && !(s[i] > 0x9f && s[i] < 0xe0)) - mb_st = 2; - else if (mb_st == 2) - mb_st = 1; - else - mb_st = 0; - } - break; - -/* Chinese Big5 Support. */ - case BIG5: - { - if (mb_st < 2 && s[i] > 0xA0) - mb_st = 2; - else if (mb_st == 2) - mb_st = 1; - else - mb_st = 0; - } - break; - default: - mb_st = 0; - } - i++; - } -#ifdef _DEBUG - qlog("i = %d\n", i); -#endif - return (s + i); -} - - -void -multibyte_init(void) -{ - multibyte_status = 0; -} - - -unsigned char * -check_client_encoding(unsigned char *str) -{ - if (strstr(str, "%27SJIS%27") || - strstr(str, "%27Shift_JIS%27") || - strstr(str, "'SJIS'") || - strstr(str, "'sjis'") || - strstr(str, "'Shift_JIS'")) - { - multibyte_client_encoding = SJIS; - return ("SJIS"); - } - if (strstr(str, "%27BIG5%27") || - strstr(str, "%27Big5%27") || - strstr(str, "'BIG5'") || - strstr(str, "'big5'") || - strstr(str, "'Big5'")) - { - multibyte_client_encoding = BIG5; - return ("BIG5"); - } - return ("OTHER"); -} - - -/*-------- - * 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)) - multibyte_status = 2; - else if (multibyte_status == 2) - multibyte_status = 1; - else - 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); -#endif - return (multibyte_status); -} diff --git a/src/interfaces/odbc/windev/multibyte.h b/src/interfaces/odbc/windev/multibyte.h deleted file mode 100644 index 43870458e0..0000000000 --- a/src/interfaces/odbc/windev/multibyte.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Multibyte library header ( psqlODBC Only ) - * - */ -#include "psqlodbc.h" - -/* PostgreSQL client encoding */ -#define SQL_ASCII 0 /* SQL/ASCII */ -#define EUC_JP 1 /* EUC for Japanese */ -#define EUC_CN 2 /* EUC for Chinese */ -#define EUC_KR 3 /* EUC for Korean */ -#define EUC_TW 4 /* EUC for Taiwan */ -#define UNICODE 5 /* Unicode UTF-8 */ -#define MULE_INTERNAL 6 /* Mule internal code */ -#define LATIN1 7 /* ISO-8859 Latin 1 */ -#define LATIN2 8 /* ISO-8859 Latin 2 */ -#define LATIN3 9 /* ISO-8859 Latin 3 */ -#define LATIN4 10 /* ISO-8859 Latin 4 */ -#define LATIN5 11 /* ISO-8859 Latin 5 */ -#define LATIN6 12 /* ISO-8859 Latin 6 */ -#define LATIN7 13 /* ISO-8859 Latin 7 */ -#define LATIN8 14 /* ISO-8859 Latin 8 */ -#define LATIN9 15 /* ISO-8859 Latin 9 */ -#define KOI8 16 /* KOI8-R/U */ -#define WIN 17 /* windows-1251 */ -#define ALT 18 /* Alternativny Variant (MS-DOS CP866) */ -#define SJIS 32 /* Shift JIS */ -#define BIG5 33 /* Big5 */ -#define WIN1250 34 /* windows-1250 */ - - -extern int multibyte_client_encoding; /* Multibyte client encoding. */ -extern int multibyte_status; /* Multibyte charcter status. */ - -void multibyte_init(void); -unsigned char *check_client_encoding(unsigned char *str); -int multibyte_char_check(unsigned char s); -unsigned char *multibyte_strchr(unsigned char *s, unsigned char c); diff --git a/src/interfaces/odbc/windev/notice.txt b/src/interfaces/odbc/windev/notice.txt deleted file mode 100644 index 70df4401cd..0000000000 --- a/src/interfaces/odbc/windev/notice.txt +++ /dev/null @@ -1,35 +0,0 @@ - -/******************************************************************** - - PSQLODBC.DLL - A library to talk to the PostgreSQL DBMS using ODBC. - - - Copyright (C) 1998; Insight Distribution Systems - - The code contained in this library is based on code written by - Christian Czezatke and Dan McGuirk, (C) 1996. - - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library (see "license.txt"); if not, write to - the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA - 02139, USA. - - - How to contact the author: - - email: byronn@insightdist.com (Byron Nikolaidis) - - -***********************************************************************/ - diff --git a/src/interfaces/odbc/windev/odbcapi.c b/src/interfaces/odbc/windev/odbcapi.c deleted file mode 100644 index a87c35850c..0000000000 --- a/src/interfaces/odbc/windev/odbcapi.c +++ /dev/null @@ -1,661 +0,0 @@ -/*------- - * Module: odbcapi.c - * - * Description: This module contains routines related to - * preparing and executing an SQL statement. - * - * Classes: n/a - * - * API functions: SQLAllocConnect, SQLAllocEnv, SQLAllocStmt, - SQLBindCol, SQLCancel, SQLColumns, SQLConnect, - SQLDataSources, SQLDescribeCol, SQLDisconnect, - SQLError, SQLExecDirect, SQLExecute, SQLFetch, - SQLFreeConnect, SQLFreeEnv, SQLFreeStmt, - SQLGetConnectOption, SQLGetCursorName, SQLGetData, - SQLGetFunctions, SQLGetInfo, SQLGetStmtOption, - SQLGetTypeInfo, SQLNumResultCols, SQLParamData, - SQLPrepare, SQLPutData, SQLRowCount, - SQLSetConnectOption, SQLSetCursorName, SQLSetParam, - SQLSetStmtOption, SQLSpecialColumns, SQLStatistics, - SQLTables, SQLTransact, SQLColAttributes, - SQLColumnPrivileges, SQLDescribeParam, SQLExtendedFetch, - SQLForeignKeys, SQLMoreResults, SQLNativeSql, - SQLNumParams, SQLParamOptions, SQLPrimaryKeys, - SQLProcedureColumns, SQLProcedures, SQLSetPos, - SQLTablePrivileges, SQLBindParameter - *------- - */ - -#include "psqlodbc.h" -#include -#include - -#include "pgapifunc.h" -#include "connection.h" -#include "statement.h" - -RETCODE SQL_API -SQLAllocConnect(HENV EnvironmentHandle, - HDBC FAR * ConnectionHandle) -{ - mylog("[SQLAllocConnect]"); - return PGAPI_AllocConnect(EnvironmentHandle, ConnectionHandle); -} - -RETCODE SQL_API -SQLAllocEnv(HENV FAR * EnvironmentHandle) -{ - mylog("[SQLAllocEnv]"); - return PGAPI_AllocEnv(EnvironmentHandle); -} - -RETCODE SQL_API -SQLAllocStmt(HDBC ConnectionHandle, - HSTMT *StatementHandle) -{ - mylog("[SQLAllocStmt]"); - return PGAPI_AllocStmt(ConnectionHandle, StatementHandle); -} - -RETCODE SQL_API -SQLBindCol(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, - PTR TargetValue, SQLINTEGER BufferLength, - SQLINTEGER *StrLen_or_Ind) -{ - mylog("[SQLBindCol]"); - return PGAPI_BindCol(StatementHandle, ColumnNumber, - TargetType, TargetValue, BufferLength, StrLen_or_Ind); -} - -RETCODE SQL_API -SQLCancel(HSTMT StatementHandle) -{ - mylog("[SQLCancel]"); - return PGAPI_Cancel(StatementHandle); -} - -RETCODE SQL_API -SQLColumns(HSTMT StatementHandle, - SQLCHAR *CatalogName, SQLSMALLINT NameLength1, - SQLCHAR *SchemaName, SQLSMALLINT NameLength2, - SQLCHAR *TableName, SQLSMALLINT NameLength3, - SQLCHAR *ColumnName, SQLSMALLINT NameLength4) -{ - mylog("[SQLColumns]"); - return PGAPI_Columns(StatementHandle, CatalogName, NameLength1, - SchemaName, NameLength2, TableName, NameLength3, - ColumnName, NameLength4); -} - - -RETCODE SQL_API -SQLConnect(HDBC ConnectionHandle, - SQLCHAR *ServerName, SQLSMALLINT NameLength1, - SQLCHAR *UserName, SQLSMALLINT NameLength2, - SQLCHAR *Authentication, SQLSMALLINT NameLength3) -{ - mylog("[SQLConnect]"); - return PGAPI_Connect(ConnectionHandle, ServerName, NameLength1, - UserName, NameLength2, Authentication, NameLength3); -} - -RETCODE SQL_API -SQLDriverConnect(HDBC hdbc, - HWND hwnd, - UCHAR FAR * szConnStrIn, - SWORD cbConnStrIn, - UCHAR FAR * szConnStrOut, - SWORD cbConnStrOutMax, - SWORD FAR * pcbConnStrOut, - UWORD fDriverCompletion) -{ - mylog("[SQLDriverConnect]"); - return PGAPI_DriverConnect(hdbc, hwnd, szConnStrIn, cbConnStrIn, - szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion); -} -RETCODE SQL_API -SQLBrowseConnect( - HDBC hdbc, - SQLCHAR *szConnStrIn, - SQLSMALLINT cbConnStrIn, - SQLCHAR *szConnStrOut, - SQLSMALLINT cbConnStrOutMax, - SQLSMALLINT *pcbConnStrOut) -{ - mylog("[SQLBrowseConnect]"); - return PGAPI_BrowseConnect(hdbc, szConnStrIn, cbConnStrIn, - szConnStrOut, cbConnStrOutMax, pcbConnStrOut); -} - -RETCODE SQL_API -SQLDataSources(HENV EnvironmentHandle, - SQLUSMALLINT Direction, SQLCHAR *ServerName, - SQLSMALLINT BufferLength1, SQLSMALLINT *NameLength1, - SQLCHAR *Description, SQLSMALLINT BufferLength2, - SQLSMALLINT *NameLength2) -{ - mylog("[SQLDataSources]"); - - /* - * return PGAPI_DataSources(EnvironmentHandle, Direction, ServerName, - * BufferLength1, NameLength1, Description, BufferLength2, - * NameLength2); - */ - return SQL_ERROR; -} - -RETCODE SQL_API -SQLDescribeCol(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, - SQLSMALLINT BufferLength, SQLSMALLINT *NameLength, - SQLSMALLINT *DataType, SQLUINTEGER *ColumnSize, - SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) -{ - mylog("[SQLDescribeCol]"); - return PGAPI_DescribeCol(StatementHandle, ColumnNumber, - ColumnName, BufferLength, NameLength, - DataType, ColumnSize, DecimalDigits, Nullable); -} - -RETCODE SQL_API -SQLDisconnect(HDBC ConnectionHandle) -{ - mylog("[SQLDisconnect]"); - return PGAPI_Disconnect(ConnectionHandle); -} - -RETCODE SQL_API -SQLError(HENV EnvironmentHandle, - HDBC ConnectionHandle, HSTMT StatementHandle, - SQLCHAR *Sqlstate, SQLINTEGER *NativeError, - SQLCHAR *MessageText, SQLSMALLINT BufferLength, - SQLSMALLINT *TextLength) -{ - mylog("[SQLError]"); - return PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle, - Sqlstate, NativeError, MessageText, BufferLength, TextLength); -} - -RETCODE SQL_API -SQLExecDirect(HSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength) -{ - mylog("[SQLExecDirect]"); - return PGAPI_ExecDirect(StatementHandle, StatementText, TextLength); -} - -RETCODE SQL_API -SQLExecute(HSTMT StatementHandle) -{ - mylog("[SQLExecute]"); - return PGAPI_Execute(StatementHandle); -} - -RETCODE SQL_API -SQLFetch(HSTMT StatementHandle) -{ - static char *func = "SQLFetch"; - -#if (ODBCVER >= 0x0300) - StatementClass *stmt = (StatementClass *) StatementHandle; - ConnectionClass *conn = SC_get_conn(stmt); - - if (conn->driver_version >= 0x0300) - { - SQLUSMALLINT *rowStatusArray = stmt->options.rowStatusArray; - SQLINTEGER *pcRow = stmt->options.rowsFetched; - - mylog("[[%s]]", func); - return PGAPI_ExtendedFetch(StatementHandle, SQL_FETCH_NEXT, 0, - pcRow, rowStatusArray); - } -#endif - mylog("[%s]", func); - return PGAPI_Fetch(StatementHandle); -} - -RETCODE SQL_API -SQLFreeConnect(HDBC ConnectionHandle) -{ - mylog("[SQLFreeStmt]"); - return PGAPI_FreeConnect(ConnectionHandle); -} - -RETCODE SQL_API -SQLFreeEnv(HENV EnvironmentHandle) -{ - mylog("[SQLFreeEnv]"); - return PGAPI_FreeEnv(EnvironmentHandle); -} - -RETCODE SQL_API -SQLFreeStmt(HSTMT StatementHandle, - SQLUSMALLINT Option) -{ - mylog("[SQLFreeStmt]"); - return PGAPI_FreeStmt(StatementHandle, Option); -} - -RETCODE SQL_API -SQLGetConnectOption(HDBC ConnectionHandle, - SQLUSMALLINT Option, PTR Value) -{ - mylog("[SQLGetConnectOption]"); - return PGAPI_GetConnectOption(ConnectionHandle, Option, Value); -} -RETCODE SQL_API -SQLGetCursorName(HSTMT StatementHandle, - SQLCHAR *CursorName, SQLSMALLINT BufferLength, - SQLSMALLINT *NameLength) -{ - mylog("[SQLGetCursorName]"); - return PGAPI_GetCursorName(StatementHandle, CursorName, BufferLength, - NameLength); -} - -RETCODE SQL_API -SQLGetData(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, - PTR TargetValue, SQLINTEGER BufferLength, - SQLINTEGER *StrLen_or_Ind) -{ - mylog("[SQLGetData]"); - return PGAPI_GetData(StatementHandle, ColumnNumber, TargetType, - TargetValue, BufferLength, StrLen_or_Ind); -} - -RETCODE SQL_API -SQLGetFunctions(HDBC ConnectionHandle, - SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported) -{ - mylog("[SQLGetFunctions]"); -#if (ODBCVER >= 0x0300) - if (FunctionId == SQL_API_ODBC3_ALL_FUNCTIONS) - return PGAPI_GetFunctions30(ConnectionHandle, FunctionId, Supported); -#endif - return PGAPI_GetFunctions(ConnectionHandle, FunctionId, Supported); -} -RETCODE SQL_API -SQLGetInfo(HDBC ConnectionHandle, - SQLUSMALLINT InfoType, PTR InfoValue, - SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) -{ -#if (ODBCVER >= 0x0300) - RETCODE ret; - - mylog("[SQLGetInfo(30)]"); - if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, - BufferLength, StringLength)) == SQL_ERROR) - { - if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300) - return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue, - BufferLength, StringLength); - } - return ret; -#else - mylog("[SQLGetInfo]"); - return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, - BufferLength, StringLength); -#endif -} - -RETCODE SQL_API -SQLGetStmtOption(HSTMT StatementHandle, - SQLUSMALLINT Option, PTR Value) -{ - mylog("[SQLGetStmtOption]"); - return PGAPI_GetStmtOption(StatementHandle, Option, Value); -} - -RETCODE SQL_API -SQLGetTypeInfo(HSTMT StatementHandle, - SQLSMALLINT DataType) -{ - mylog("[SQLGetTypeInfo]"); - return PGAPI_GetTypeInfo(StatementHandle, DataType); -} - -RETCODE SQL_API -SQLNumResultCols(HSTMT StatementHandle, - SQLSMALLINT *ColumnCount) -{ - mylog("[SQLNumResultCols]"); - return PGAPI_NumResultCols(StatementHandle, ColumnCount); -} - -RETCODE SQL_API -SQLParamData(HSTMT StatementHandle, - PTR *Value) -{ - mylog("[SQLParamData]"); - return PGAPI_ParamData(StatementHandle, Value); -} - -RETCODE SQL_API -SQLPrepare(HSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength) -{ - mylog("[SQLPrepare]"); - return PGAPI_Prepare(StatementHandle, StatementText, TextLength); -} - -RETCODE SQL_API -SQLPutData(HSTMT StatementHandle, - PTR Data, SQLINTEGER StrLen_or_Ind) -{ - mylog("[SQLPutData]"); - return PGAPI_PutData(StatementHandle, Data, StrLen_or_Ind); -} - -RETCODE SQL_API -SQLRowCount(HSTMT StatementHandle, - SQLINTEGER *RowCount) -{ - mylog("[SQLRowCount]"); - return PGAPI_RowCount(StatementHandle, RowCount); -} - -RETCODE SQL_API -SQLSetConnectOption(HDBC ConnectionHandle, - SQLUSMALLINT Option, SQLUINTEGER Value) -{ - mylog("[SQLSetConnectionOption]"); - return PGAPI_SetConnectOption(ConnectionHandle, Option, Value); -} - -RETCODE SQL_API -SQLSetCursorName(HSTMT StatementHandle, - SQLCHAR *CursorName, SQLSMALLINT NameLength) -{ - mylog("[SQLSetCursorName]"); - return PGAPI_SetCursorName(StatementHandle, CursorName, NameLength); -} - -RETCODE SQL_API -SQLSetParam(HSTMT StatementHandle, - SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, - SQLSMALLINT ParameterType, SQLUINTEGER LengthPrecision, - SQLSMALLINT ParameterScale, PTR ParameterValue, - SQLINTEGER *StrLen_or_Ind) -{ - mylog("[SQLSetParam]"); - - /* - * return PGAPI_SetParam(StatementHandle, ParameterNumber, ValueType, - * ParameterType, LengthPrecision, ParameterScale, ParameterValue, - * StrLen_or_Ind); - */ - return SQL_ERROR; -} - -RETCODE SQL_API -SQLSetStmtOption(HSTMT StatementHandle, - SQLUSMALLINT Option, SQLUINTEGER Value) -{ - mylog("[SQLSetStmtOption]"); - return PGAPI_SetStmtOption(StatementHandle, Option, Value); -} - -RETCODE SQL_API -SQLSpecialColumns(HSTMT StatementHandle, - SQLUSMALLINT IdentifierType, SQLCHAR *CatalogName, - SQLSMALLINT NameLength1, SQLCHAR *SchemaName, - SQLSMALLINT NameLength2, SQLCHAR *TableName, - SQLSMALLINT NameLength3, SQLUSMALLINT Scope, - SQLUSMALLINT Nullable) -{ - mylog("[SQLSpecialColumns]"); - return PGAPI_SpecialColumns(StatementHandle, IdentifierType, CatalogName, - NameLength1, SchemaName, NameLength2, TableName, NameLength3, - Scope, Nullable); -} - -RETCODE SQL_API -SQLStatistics(HSTMT StatementHandle, - SQLCHAR *CatalogName, SQLSMALLINT NameLength1, - SQLCHAR *SchemaName, SQLSMALLINT NameLength2, - SQLCHAR *TableName, SQLSMALLINT NameLength3, - SQLUSMALLINT Unique, SQLUSMALLINT Reserved) -{ - mylog("[SQLStatistics]"); - return PGAPI_Statistics(StatementHandle, CatalogName, NameLength1, - SchemaName, NameLength2, TableName, NameLength3, Unique, - Reserved); -} - -RETCODE SQL_API -SQLTables(HSTMT StatementHandle, - SQLCHAR *CatalogName, SQLSMALLINT NameLength1, - SQLCHAR *SchemaName, SQLSMALLINT NameLength2, - SQLCHAR *TableName, SQLSMALLINT NameLength3, - SQLCHAR *TableType, SQLSMALLINT NameLength4) -{ - mylog("[SQLTables]"); - return PGAPI_Tables(StatementHandle, CatalogName, NameLength1, - SchemaName, NameLength2, TableName, NameLength3, - TableType, NameLength4); -} - -RETCODE SQL_API -SQLTransact(HENV EnvironmentHandle, - HDBC ConnectionHandle, SQLUSMALLINT CompletionType) -{ - mylog("[SQLTransact]"); - return PGAPI_Transact(EnvironmentHandle, ConnectionHandle, CompletionType); -} - -RETCODE SQL_API -SQLColAttributes( - HSTMT hstmt, - SQLUSMALLINT icol, - SQLUSMALLINT fDescType, - PTR rgbDesc, - SQLSMALLINT cbDescMax, - SQLSMALLINT *pcbDesc, - SQLINTEGER *pfDesc) -{ - mylog("[SQLColAttributes]"); - return PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc, - cbDescMax, pcbDesc, pfDesc); -} - -RETCODE SQL_API -SQLColumnPrivileges( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szTableName, - SQLSMALLINT cbTableName, - SQLCHAR *szColumnName, - SQLSMALLINT cbColumnName) -{ - mylog("[SQLColumnPrivileges]"); - return PGAPI_ColumnPrivileges(hstmt, szCatalogName, cbCatalogName, - szSchemaName, cbSchemaName, szTableName, cbTableName, - szColumnName, cbColumnName); -} - -RETCODE SQL_API -SQLDescribeParam( - HSTMT hstmt, - SQLUSMALLINT ipar, - SQLSMALLINT *pfSqlType, - SQLUINTEGER *pcbParamDef, - SQLSMALLINT *pibScale, - SQLSMALLINT *pfNullable) -{ - mylog("[SQLDescribeParam]"); - return PGAPI_DescribeParam(hstmt, ipar, pfSqlType, pcbParamDef, - pibScale, pfNullable); -} - -RETCODE SQL_API -SQLExtendedFetch( - HSTMT hstmt, - SQLUSMALLINT fFetchType, - SQLINTEGER irow, - SQLUINTEGER *pcrow, - SQLUSMALLINT *rgfRowStatus) -{ - mylog("[SQLExtendedFetch]"); - return PGAPI_ExtendedFetch(hstmt, fFetchType, irow, pcrow, rgfRowStatus); -} - -RETCODE SQL_API -SQLForeignKeys( - HSTMT hstmt, - SQLCHAR *szPkCatalogName, - SQLSMALLINT cbPkCatalogName, - SQLCHAR *szPkSchemaName, - SQLSMALLINT cbPkSchemaName, - SQLCHAR *szPkTableName, - SQLSMALLINT cbPkTableName, - SQLCHAR *szFkCatalogName, - SQLSMALLINT cbFkCatalogName, - SQLCHAR *szFkSchemaName, - SQLSMALLINT cbFkSchemaName, - SQLCHAR *szFkTableName, - SQLSMALLINT cbFkTableName) -{ - mylog("[SQLForeignKeys]"); - return PGAPI_ForeignKeys(hstmt, szPkCatalogName, cbPkCatalogName, - szPkSchemaName, cbPkSchemaName, szPkTableName, - cbPkTableName, szFkCatalogName, cbFkCatalogName, - szFkSchemaName, cbFkSchemaName, szFkTableName, cbFkTableName); -} - -RETCODE SQL_API -SQLMoreResults(HSTMT hstmt) -{ - mylog("[SQLMoreResults]"); - return PGAPI_MoreResults(hstmt); -} - -RETCODE SQL_API -SQLNativeSql( - HDBC hdbc, - SQLCHAR *szSqlStrIn, - SQLINTEGER cbSqlStrIn, - SQLCHAR *szSqlStr, - SQLINTEGER cbSqlStrMax, - SQLINTEGER *pcbSqlStr) -{ - mylog("[SQLNativeSql]"); - return PGAPI_NativeSql(hdbc, szSqlStrIn, cbSqlStrIn, szSqlStr, - cbSqlStrMax, pcbSqlStr); -} - -RETCODE SQL_API -SQLNumParams( - HSTMT hstmt, - SQLSMALLINT *pcpar) -{ - mylog("[SQLNumParams]"); - return PGAPI_NumParams(hstmt, pcpar); -} - -RETCODE SQL_API -SQLParamOptions( - HSTMT hstmt, - SQLUINTEGER crow, - SQLUINTEGER *pirow) -{ - mylog("[SQLParamOptions]"); - return PGAPI_ParamOptions(hstmt, crow, pirow); -} - -RETCODE SQL_API -SQLPrimaryKeys( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szTableName, - SQLSMALLINT cbTableName) -{ - mylog("[SQLPrimaryKeys]"); - return PGAPI_PrimaryKeys(hstmt, szCatalogName, cbCatalogName, - szSchemaName, cbSchemaName, szTableName, cbTableName); -} - -RETCODE SQL_API -SQLProcedureColumns( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szProcName, - SQLSMALLINT cbProcName, - SQLCHAR *szColumnName, - SQLSMALLINT cbColumnName) -{ - mylog("[SQLProcedureColumns]"); - return PGAPI_ProcedureColumns(hstmt, szCatalogName, cbCatalogName, - szSchemaName, cbSchemaName, szProcName, cbProcName, - szColumnName, cbColumnName); -} - -RETCODE SQL_API -SQLProcedures( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szProcName, - SQLSMALLINT cbProcName) -{ - mylog("[SQLProcedures]"); - return PGAPI_Procedures(hstmt, szCatalogName, cbCatalogName, - szSchemaName, cbSchemaName, szProcName, cbProcName); -} - -RETCODE SQL_API -SQLSetPos( - HSTMT hstmt, - SQLUSMALLINT irow, - SQLUSMALLINT fOption, - SQLUSMALLINT fLock) -{ - mylog("[SQLSetPos]"); - return PGAPI_SetPos(hstmt, irow, fOption, fLock); -} - -RETCODE SQL_API -SQLTablePrivileges( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szTableName, - SQLSMALLINT cbTableName) -{ - mylog("[SQLTablePrivileges]"); - return PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName, - szSchemaName, cbSchemaName, szTableName, cbTableName); -} - -RETCODE SQL_API -SQLBindParameter( - HSTMT hstmt, - SQLUSMALLINT ipar, - SQLSMALLINT fParamType, - SQLSMALLINT fCType, - SQLSMALLINT fSqlType, - SQLUINTEGER cbColDef, - SQLSMALLINT ibScale, - PTR rgbValue, - SQLINTEGER cbValueMax, - SQLINTEGER *pcbValue) -{ - mylog("[SQLBindParameter]"); - return PGAPI_BindParameter(hstmt, ipar, fParamType, fCType, - fSqlType, cbColDef, ibScale, rgbValue, cbValueMax, - pcbValue); -} diff --git a/src/interfaces/odbc/windev/odbcapi30.c b/src/interfaces/odbc/windev/odbcapi30.c deleted file mode 100644 index 8ad1dba7e6..0000000000 --- a/src/interfaces/odbc/windev/odbcapi30.c +++ /dev/null @@ -1,752 +0,0 @@ -/*------- - * Module: odbcapi30.c - * - * Description: This module contains routines related to ODBC 3.0 - * most of their implementations are temporary - * and must be rewritten properly. - * 2001/07/23 inoue - * - * Classes: n/a - * - * API functions: SQLAllocHandle, SQLBindParam, SQLCloseCursor, - SQLColAttribute, SQLCopyDesc, SQLEndTran, - SQLFetchScroll, SQLFreeHandle, SQLGetDescField, - SQLGetDescRec, SQLGetDiagField, SQLGetDiagRec, - SQLGetEnvAttr, SQLGetConnectAttr, SQLGetStmtAttr, - SQLSetConnectAttr, SQLSetDescField, SQLSetDescRec, - SQLSetEnvAttr, SQLSetStmtAttr, SQLBulkOperations - *------- - */ - -#ifndef ODBCVER -#define ODBCVER 0x0300 -#endif -#include "psqlodbc.h" -#include -#include - -#include "environ.h" -#include "connection.h" -#include "statement.h" -#include "pgapifunc.h" - -/* SQLAllocConnect/SQLAllocEnv/SQLAllocStmt -> SQLAllocHandle */ -RETCODE SQL_API -SQLAllocHandle(SQLSMALLINT HandleType, - SQLHANDLE InputHandle, SQLHANDLE * OutputHandle) -{ - mylog("[[SQLAllocHandle]]"); - switch (HandleType) - { - case SQL_HANDLE_ENV: - return PGAPI_AllocEnv(OutputHandle); - case SQL_HANDLE_DBC: - return PGAPI_AllocConnect(InputHandle, OutputHandle); - case SQL_HANDLE_STMT: - return PGAPI_AllocStmt(InputHandle, OutputHandle); - default: - break; - } - return SQL_ERROR; -} - -/* SQLBindParameter/SQLSetParam -> SQLBindParam */ -RETCODE SQL_API -SQLBindParam(HSTMT StatementHandle, - SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, - SQLSMALLINT ParameterType, SQLUINTEGER LengthPrecision, - SQLSMALLINT ParameterScale, PTR ParameterValue, - SQLINTEGER *StrLen_or_Ind) -{ - int BufferLength = 512; /* Is it OK ? */ - - mylog("[[SQLBindParam]]"); - return PGAPI_BindParameter(StatementHandle, ParameterNumber, SQL_PARAM_INPUT, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, BufferLength, StrLen_or_Ind); -} - -/* New function */ -RETCODE SQL_API -SQLCloseCursor(HSTMT StatementHandle) -{ - mylog("[[SQLCloseCursor]]"); - return PGAPI_FreeStmt(StatementHandle, SQL_CLOSE); -} - -/* SQLColAttributes -> SQLColAttribute */ -RETCODE SQL_API -SQLColAttribute(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, - PTR CharacterAttribute, SQLSMALLINT BufferLength, - SQLSMALLINT *StringLength, PTR NumericAttribute) -{ - mylog("[[SQLColAttribute]]"); - return PGAPI_ColAttributes(StatementHandle, ColumnNumber, - FieldIdentifier, CharacterAttribute, BufferLength, - StringLength, NumericAttribute); -} - -/* new function */ -RETCODE SQL_API -SQLCopyDesc(SQLHDESC SourceDescHandle, - SQLHDESC TargetDescHandle) -{ - mylog("[[SQLCopyDesc]]\n"); - return SQL_ERROR; -} - -/* SQLTransact -> SQLEndTran */ -RETCODE SQL_API -SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT CompletionType) -{ - mylog("[[SQLEndTran]]"); - switch (HandleType) - { - case SQL_HANDLE_ENV: - return PGAPI_Transact(Handle, SQL_NULL_HDBC, CompletionType); - case SQL_HANDLE_DBC: - return PGAPI_Transact(SQL_NULL_HENV, Handle, CompletionType); - default: - break; - } - return SQL_ERROR; /* SQLSTATE HY092 ("Invalid - * attribute/option identifier") */ - -} - -/* SQLExtendedFetch -> SQLFetchScroll */ -RETCODE SQL_API -SQLFetchScroll(HSTMT StatementHandle, - SQLSMALLINT FetchOrientation, SQLINTEGER FetchOffset) -{ - static char *func = "SQLFetchScroll"; - StatementClass *stmt = (StatementClass *) StatementHandle; - RETCODE ret; - SQLUSMALLINT *rowStatusArray = stmt->options.rowStatusArray; - SQLINTEGER *pcRow = stmt->options.rowsFetched; - - mylog("[[%s]] %d,%d\n", func, FetchOrientation, FetchOffset); - if (FetchOrientation == SQL_FETCH_BOOKMARK) - { - if (stmt->options.bookmark_ptr) - FetchOffset += *((Int4 *) stmt->options.bookmark_ptr); - else - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "Bookmark isn't specifed yet"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - ret = PGAPI_ExtendedFetch(StatementHandle, FetchOrientation, FetchOffset, - pcRow, rowStatusArray); - if (ret != SQL_SUCCESS) - mylog("%s return = %d\n", func, ret); - return ret; -} - -/* SQLFree(Connect/Env/Stmt) -> SQLFreeHandle */ -RETCODE SQL_API -SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) -{ - mylog("[[SQLFreeHandle]]"); - switch (HandleType) - { - case SQL_HANDLE_ENV: - return PGAPI_FreeEnv(Handle); - case SQL_HANDLE_DBC: - return PGAPI_FreeConnect(Handle); - case SQL_HANDLE_STMT: - return PGAPI_FreeStmt(Handle, SQL_DROP); - default: - break; - } - return SQL_ERROR; -} - -/* new function */ -RETCODE SQL_API -SQLGetDescField(SQLHDESC DescriptorHandle, - SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, - PTR Value, SQLINTEGER BufferLength, - SQLINTEGER *StringLength) -{ - mylog("[[SQLGetDescField]]\n"); - return SQL_ERROR; -} - -/* new function */ -RETCODE SQL_API -SQLGetDescRec(SQLHDESC DescriptorHandle, - SQLSMALLINT RecNumber, SQLCHAR *Name, - SQLSMALLINT BufferLength, SQLSMALLINT *StringLength, - SQLSMALLINT *Type, SQLSMALLINT *SubType, - SQLINTEGER *Length, SQLSMALLINT *Precision, - SQLSMALLINT *Scale, SQLSMALLINT *Nullable) -{ - mylog("[[SQLGetDescRec]]\n"); - return SQL_ERROR; -} - -/* new function */ -RETCODE SQL_API -SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, - PTR DiagInfo, SQLSMALLINT BufferLength, - SQLSMALLINT *StringLength) -{ - mylog("[[SQLGetDiagField]]\n"); - return SQL_ERROR; -} - -/* SQLError -> SQLDiagRec */ -RETCODE SQL_API -SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, - SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, - SQLINTEGER *NativeError, SQLCHAR *MessageText, - SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) -{ - RETCODE ret; - - mylog("[[SQLGetDiagRec]]\n"); - switch (HandleType) - { - case SQL_HANDLE_ENV: - ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError, - MessageText, BufferLength, TextLength); - break; - case SQL_HANDLE_DBC: - ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError, - MessageText, BufferLength, TextLength); - break; - case SQL_HANDLE_STMT: - ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError, - MessageText, BufferLength, TextLength); - break; - default: - ret = SQL_ERROR; - } - if (ret == SQL_SUCCESS_WITH_INFO && - BufferLength == 0 && - *TextLength) - { - SQLSMALLINT BufferLength = *TextLength + 4; - SQLCHAR *MessageText = malloc(BufferLength); - - ret = SQLGetDiagRec(HandleType, Handle, RecNumber, Sqlstate, - NativeError, MessageText, BufferLength, - TextLength); - free(MessageText); - } - return ret; -} - -/* new function */ -RETCODE SQL_API -SQLGetEnvAttr(HENV EnvironmentHandle, - SQLINTEGER Attribute, PTR Value, - SQLINTEGER BufferLength, SQLINTEGER *StringLength) -{ - EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle; - - mylog("[[SQLGetEnvAttr]] %d\n", Attribute); - switch (Attribute) - { - case SQL_ATTR_CONNECTION_POOLING: - *((unsigned int *) Value) = SQL_CP_OFF; - break; - case SQL_ATTR_CP_MATCH: - *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; - break; - case SQL_ATTR_ODBC_VERSION: - *((unsigned int *) Value) = SQL_OV_ODBC3; - break; - case SQL_ATTR_OUTPUT_NTS: - *((unsigned int *) Value) = SQL_TRUE; - break; - default: - env->errornumber = CONN_INVALID_ARGUMENT_NO; - return SQL_ERROR; - } - return SQL_SUCCESS; -} - -/* SQLGetConnectOption -> SQLGetconnectAttr */ -RETCODE SQL_API -SQLGetConnectAttr(HDBC ConnectionHandle, - SQLINTEGER Attribute, PTR Value, - SQLINTEGER BufferLength, SQLINTEGER *StringLength) -{ - ConnectionClass *conn = (ConnectionClass *) ConnectionHandle; - - mylog("[[SQLGetConnectAttr]] %d\n", Attribute); - switch (Attribute) - { - case SQL_ATTR_ASYNC_ENABLE: - case SQL_ATTR_AUTO_IPD: - case SQL_ATTR_CONNECTION_DEAD: - case SQL_ATTR_CONNECTION_TIMEOUT: - case SQL_ATTR_METADATA_ID: - conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER; - conn->errormsg = "Unsupported connection option (Set)"; - return SQL_ERROR; - } - return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value); -} - -/* SQLGetStmtOption -> SQLGetStmtAttr */ -RETCODE SQL_API -SQLGetStmtAttr(HSTMT StatementHandle, - SQLINTEGER Attribute, PTR Value, - SQLINTEGER BufferLength, SQLINTEGER *StringLength) -{ - static char *func = "SQLGetStmtAttr"; - StatementClass *stmt = (StatementClass *) StatementHandle; - RETCODE ret = SQL_SUCCESS; - int len = 0; - - mylog("[[%s]] %d\n", func, Attribute); - switch (Attribute) - { - case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */ - Value = stmt->options.bookmark_ptr; - - len = 4; - break; - case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ - Value = stmt->options.rowStatusArray; - - len = 4; - break; - case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ - Value = stmt->options.rowsFetched; - - len = 4; - break; - case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ - *((SQLUINTEGER *) Value) = stmt->options.rowset_size; - len = 4; - break; - case SQL_ATTR_APP_ROW_DESC: /* 10010 */ - *((HSTMT *) Value) = StatementHandle; /* this is useless */ - len = 4; - break; - case SQL_ATTR_APP_PARAM_DESC: /* 10011 */ - *((HSTMT *) Value) = StatementHandle; /* this is useless */ - len = 4; - break; - case SQL_ATTR_IMP_ROW_DESC: /* 10012 */ - *((HSTMT *) Value) = StatementHandle; /* this is useless */ - len = 4; - break; - case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */ - *((HSTMT *) Value) = StatementHandle; /* this is useless */ - len = 4; - break; - case SQL_ATTR_AUTO_IPD: /* 10001 */ - /* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */ - case SQL_ATTR_PARAMSET_SIZE: /* 22 */ - case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */ - case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ - - case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */ - case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */ - - case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */ - case SQL_ATTR_METADATA_ID: /* 10014 */ - - /* - * case SQL_ATTR_PREDICATE_PTR: case - * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR: - */ - case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */ - case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ - case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */ - case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */ - case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */ - stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; - stmt->errormsg = "Unsupported statement option (Get)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - default: - len = 4; - ret = PGAPI_GetStmtOption(StatementHandle, (UWORD) Attribute, Value); - } - if (ret == SQL_SUCCESS && StringLength) - *StringLength = len; - return ret; -} - -/* SQLSetConnectOption -> SQLSetConnectAttr */ -RETCODE SQL_API -SQLSetConnectAttr(HDBC ConnectionHandle, - SQLINTEGER Attribute, PTR Value, - SQLINTEGER StringLength) -{ - ConnectionClass *conn = (ConnectionClass *) ConnectionHandle; - - mylog("[[SQLSetConnectAttr]] %d\n", Attribute); - switch (Attribute) - { - case SQL_ATTR_ASYNC_ENABLE: - case SQL_ATTR_AUTO_IPD: - case SQL_ATTR_CONNECTION_DEAD: - case SQL_ATTR_CONNECTION_TIMEOUT: - case SQL_ATTR_METADATA_ID: - conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER; - conn->errormsg = "Unsupported connection option (Set)"; - return SQL_ERROR; - } - return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value); -} - -/* new function */ -RETCODE SQL_API -SQLSetDescField(SQLHDESC DescriptorHandle, - SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, - PTR Value, SQLINTEGER BufferLength) -{ - mylog("[[SQLSetDescField]]\n"); - return SQL_ERROR; -} - -/* new fucntion */ -RETCODE SQL_API -SQLSetDescRec(SQLHDESC DescriptorHandle, - SQLSMALLINT RecNumber, SQLSMALLINT Type, - SQLSMALLINT SubType, SQLINTEGER Length, - SQLSMALLINT Precision, SQLSMALLINT Scale, - PTR Data, SQLINTEGER *StringLength, - SQLINTEGER *Indicator) -{ - mylog("[[SQLsetDescRec]]\n"); - return SQL_ERROR; -} - -/* new function */ -RETCODE SQL_API -SQLSetEnvAttr(HENV EnvironmentHandle, - SQLINTEGER Attribute, PTR Value, - SQLINTEGER StringLength) -{ - EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle; - - mylog("[[SQLSetEnvAttr]] att=%d,%u\n", Attribute, Value); - switch (Attribute) - { - case SQL_ATTR_CONNECTION_POOLING: - if ((SQLUINTEGER) Value == SQL_CP_OFF) - return SQL_SUCCESS; - break; - case SQL_ATTR_CP_MATCH: - /* *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; */ - return SQL_SUCCESS; - case SQL_ATTR_ODBC_VERSION: - if ((SQLUINTEGER) Value == SQL_OV_ODBC2) - return SQL_SUCCESS; - break; - case SQL_ATTR_OUTPUT_NTS: - if ((SQLUINTEGER) Value == SQL_TRUE) - return SQL_SUCCESS; - break; - default: - env->errornumber = CONN_INVALID_ARGUMENT_NO; - return SQL_ERROR; - } - env->errornumber = CONN_OPTION_VALUE_CHANGED; - env->errormsg = "SetEnv changed to "; - return SQL_SUCCESS_WITH_INFO; -} - -/* SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */ -RETCODE SQL_API -SQLSetStmtAttr(HSTMT StatementHandle, - SQLINTEGER Attribute, PTR Value, - SQLINTEGER StringLength) -{ - static char *func = "SQLSetStmtAttr"; - StatementClass *stmt = (StatementClass *) StatementHandle; - UDWORD rowcount; - - mylog("[[%s]] %d,%u\n", func, Attribute, Value); - switch (Attribute) - { - case SQL_ATTR_PARAMSET_SIZE: /* 22 */ - return PGAPI_ParamOptions(StatementHandle, (UWORD) Value, &rowcount); - case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */ - case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ - - case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */ - case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */ - - case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */ - - case SQL_ATTR_APP_ROW_DESC: /* 10010 */ - case SQL_ATTR_APP_PARAM_DESC: /* 10011 */ - case SQL_ATTR_AUTO_IPD: /* 10001 */ - /* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */ - case SQL_ATTR_IMP_ROW_DESC: /* 10012 */ - case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */ - case SQL_ATTR_METADATA_ID: /* 10014 */ - - /* - * case SQL_ATTR_PREDICATE_PTR: case - * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR: - */ - case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */ - case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ - case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */ - case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */ - case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */ - stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; - stmt->errormsg = "Unsupported statement option (Set)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - - case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */ - stmt->options.bookmark_ptr = Value; - - break; - case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ - stmt->options.rowStatusArray = (SQLUSMALLINT *) Value; - - break; - case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ - stmt->options.rowsFetched = (SQLUINTEGER *) Value; - - break; - case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ - stmt->options.rowset_size = (SQLUINTEGER) Value; - - break; - default: - return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value); - } - return SQL_SUCCESS; -} - -#define SQL_FUNC_ESET(pfExists, uwAPI) \ - (*(((UWORD*) (pfExists)) + ((uwAPI) >> 4)) \ - |= (1 << ((uwAPI) & 0x000F)) \ - ) -RETCODE SQL_API -PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists) -{ - if (fFunction != SQL_API_ODBC3_ALL_FUNCTIONS) - return SQL_ERROR; - memset(pfExists, 0, sizeof(UWORD) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE); - - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCCONNECT); 1 deprecated */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCENV); 2 deprecated */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCSTMT); 3 deprecated */ - - /* - * for (i = SQL_API_SQLBINDCOL; i <= 23; i++) SQL_FUNC_ESET(pfExists, - * i); - */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDCOL); /* 4 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCANCEL); /* 5 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLATTRIBUTE); /* 6 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCONNECT); /* 7 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBECOL); /* 8 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLDISCONNECT); /* 9 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLERROR); 10 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLEXECDIRECT); /* 11 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLEXECUTE); /* 12 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCH); /* 13 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLFREECONNECT); 14 deprecated */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLFREEENV); 15 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLFREESTMT); /* 16 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCURSORNAME); /* 17 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLNUMRESULTCOLS); /* 18 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLPREPARE); /* 19 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLROWCOUNT); /* 20 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCURSORNAME); /* 21 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPARAM); 22 deprecated */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLTRANSACT); 23 deprecated */ - - /* - * for (i = 40; i < SQL_API_SQLEXTENDEDFETCH; i++) - * SQL_FUNC_ESET(pfExists, i); - */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNS); /* 40 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERCONNECT); /* 41 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCONNECTOPTION); 42 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDATA); /* 43 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETFUNCTIONS); /* 44 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETINFO); /* 45 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLGETSTMTOPTION); 46 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETTYPEINFO); /* 47 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMDATA); /* 48 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLPUTDATA); /* 49 */ - - /* - * SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTIONOPTION); 50 - * deprecated - */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTOPTION); 51 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS); /* 52 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSTATISTICS); /* 53 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLES); /* 54 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT); /* 55 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES); /* 57 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); 59 deprecated */ - - /* - * for (++i; i < SQL_API_SQLBINDPARAMETER; i++) - * SQL_FUNC_ESET(pfExists, i); - */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLFOREIGNKEYS); /* 60 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLMORERESULTS); /* 61 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLNATIVESQL); /* 62 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLNUMPARAMS); /* 63 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS); /* 65 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS); /* 66 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES); /* 67 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS); /* 68 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); /* 69 deprecated */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES); /* 70 */ - /* SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERS); */ /* 71 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAMETER); /* 72 */ - - SQL_FUNC_ESET(pfExists, SQL_API_SQLALLOCHANDLE); /* 1001 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAM); /* 1002 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCLOSECURSOR); /* 1003 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLCOPYDESC); /* 1004 not implemented - * yet */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLENDTRAN); /* 1005 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLFREEHANDLE); /* 1006 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCONNECTATTR); /* 1007 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCFIELD); /* 1008 not implemented - * yet */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented - * yet */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGFIELD); /* 1010 not implemented - * yet */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGREC); /* 1011 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETENVATTR); /* 1012 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLGETSTMTATTR); /* 1014 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR); /* 1016 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD); /* 1017 not implemeted - * yet */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented - * yet */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR); /* 1019 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR); /* 1020 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL); /* 1021 */ - SQL_FUNC_ESET(pfExists, SQL_API_SQLBULKOPERATIONS); /* 24 not implemented - * yet */ - - return SQL_SUCCESS; -} -RETCODE SQL_API -PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, - SWORD cbInfoValueMax, SWORD FAR * pcbInfoValue) -{ - static char *func = "PGAPI_GetInfo30"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - char *p = NULL; - int len = 0, - value = 0; - RETCODE result; - - switch (fInfoType) - { - case SQL_DYNAMIC_CURSOR_ATTRIBUTES1: - len = 4; - value = 0; - break; - case SQL_DYNAMIC_CURSOR_ATTRIBUTES2: - len = 4; - value = 0; - break; - - case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1: - len = 4; - value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | - SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK; - break; - case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2: - len = 4; - value = 0; - break; - case SQL_KEYSET_CURSOR_ATTRIBUTES1: - len = 4; - value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE - | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK - | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION - | SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE - | SQL_CA1_POS_REFRESH - | SQL_CA1_BULK_ADD - | SQL_CA1_BULK_UPDATE_BY_BOOKMARK - | SQL_CA1_BULK_DELETE_BY_BOOKMARK - | SQL_CA1_BULK_FETCH_BY_BOOKMARK - ; - break; - case SQL_KEYSET_CURSOR_ATTRIBUTES2: - len = 4; - value = SQL_CA2_OPT_ROWVER_CONCURRENCY | - SQL_CA2_SENSITIVITY_ADDITIONS | - SQL_CA2_SENSITIVITY_DELETIONS | - SQL_CA2_SENSITIVITY_UPDATES; - break; - - case SQL_STATIC_CURSOR_ATTRIBUTES1: - len = 4; - value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | - SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | - SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION | - SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE | - SQL_CA1_POS_REFRESH; - break; - case SQL_STATIC_CURSOR_ATTRIBUTES2: - len = 4; - value = SQL_CA2_OPT_ROWVER_CONCURRENCY | - SQL_CA2_SENSITIVITY_ADDITIONS | - SQL_CA2_SENSITIVITY_DELETIONS | - SQL_CA2_SENSITIVITY_UPDATES; - break; - default: - /* unrecognized key */ - conn->errormsg = "Unrecognized key passed to SQLGetInfo."; - conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - result = SQL_SUCCESS; - if (p) - { - /* char/binary data */ - len = strlen(p); - - if (rgbInfoValue) - { - strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax); - - if (len >= cbInfoValueMax) - { - result = SQL_SUCCESS_WITH_INFO; - conn->errornumber = STMT_TRUNCATED; - conn->errormsg = "The buffer was too small for tthe InfoValue."; - } - } - } - else - { - /* numeric data */ - if (rgbInfoValue) - { - if (len == 2) - *((WORD *) rgbInfoValue) = (WORD) value; - else if (len == 4) - *((DWORD *) rgbInfoValue) = (DWORD) value; - } - } - - if (pcbInfoValue) - *pcbInfoValue = len; - return result; -} diff --git a/src/interfaces/odbc/windev/options.c b/src/interfaces/odbc/windev/options.c deleted file mode 100644 index bf2707f4da..0000000000 --- a/src/interfaces/odbc/windev/options.c +++ /dev/null @@ -1,668 +0,0 @@ -/*-------- - * Module: options.c - * - * Description: This module contains routines for getting/setting - * connection and statement options. - * - * Classes: n/a - * - * API functions: SQLSetConnectOption, SQLSetStmtOption, SQLGetConnectOption, - * SQLGetStmtOption - * - * Comments: See "notice.txt" for copyright and license information. - *-------- - */ - -#include "psqlodbc.h" -#include - -#include "environ.h" -#include "connection.h" -#include "statement.h" -#include "qresult.h" -#include "pgapifunc.h" - - - -RETCODE set_statement_option(ConnectionClass *conn, - StatementClass *stmt, - UWORD fOption, - UDWORD vParam); - - -RETCODE -set_statement_option(ConnectionClass *conn, - StatementClass *stmt, - UWORD fOption, - UDWORD vParam) -{ - static char *func = "set_statement_option"; - char changed = FALSE; - ConnInfo *ci = NULL; - - if (conn) - ci = &(conn->connInfo); - else if (stmt) - ci = &(SC_get_conn(stmt)->connInfo); - switch (fOption) - { - case SQL_ASYNC_ENABLE: /* ignored */ - break; - - case SQL_BIND_TYPE: - /* now support multi-column and multi-row binding */ - if (conn) - conn->stmtOptions.bind_size = vParam; - if (stmt) - stmt->options.bind_size = vParam; - break; - - case SQL_CONCURRENCY: - - /* - * positioned update isn't supported so cursor concurrency is - * read-only - */ - mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam); - if (ci->drivers.lie || vParam == SQL_CONCUR_READ_ONLY || vParam == SQL_CONCUR_ROWVER) - { - if (conn) - conn->stmtOptions.scroll_concurrency = vParam; - if (stmt) - stmt->options.scroll_concurrency = vParam; - } - else - { - if (conn) - conn->stmtOptions.scroll_concurrency = SQL_CONCUR_ROWVER; - if (stmt) - stmt->options.scroll_concurrency = SQL_CONCUR_ROWVER; - changed = TRUE; - } - break; - - case SQL_CURSOR_TYPE: - - /* - * if declare/fetch, then type can only be forward. otherwise, - * it can only be forward or static. - */ - mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam); - - if (ci->drivers.lie) - { - if (conn) - conn->stmtOptions.cursor_type = vParam; - if (stmt) - stmt->options.cursor_type = vParam; - } - else - { - if (ci->drivers.use_declarefetch) - { - if (conn) - conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY; - if (stmt) - stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY; - - if (vParam != SQL_CURSOR_FORWARD_ONLY) - changed = TRUE; - } - else - { - if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC) - { - if (conn) - conn->stmtOptions.cursor_type = vParam; /* valid type */ - if (stmt) - stmt->options.cursor_type = vParam; /* valid type */ - } - else - { - if (conn) - conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC; - if (stmt) - stmt->options.cursor_type = SQL_CURSOR_STATIC; - - changed = TRUE; - } - } - } - break; - - case SQL_KEYSET_SIZE: /* ignored, but saved and returned */ - mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %d\n", vParam); - - if (conn) - conn->stmtOptions.keyset_size = vParam; - if (stmt) - stmt->options.keyset_size = vParam; - - break; - - /*------- - * if (ci->drivers.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; - if (stmt) - 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; - if (stmt) - 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: - mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam); - if (conn) - conn->stmtOptions.retrieve_data = vParam; - if (stmt) - stmt->options.retrieve_data = vParam; - break; - - 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 - * rows. - */ - - if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0) - stmt->save_rowset_size = stmt->options.rowset_size; - - if (vParam < 1) - { - vParam = 1; - changed = TRUE; - } - - if (conn) - conn->stmtOptions.rowset_size = vParam; - if (stmt) - stmt->options.rowset_size = vParam; - break; - - case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */ - if (stmt) - { - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library."; - SC_log_error(func, "", stmt); - } - if (conn) - { - conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - conn->errormsg = "Simulated positioned update/delete not supported. Use the cursor library."; - CC_log_error(func, "", conn); - } - return SQL_ERROR; - - case SQL_USE_BOOKMARKS: - if (stmt) - stmt->options.use_bookmarks = vParam; - if (conn) - conn->stmtOptions.use_bookmarks = vParam; - break; - - default: - { - char option[64]; - - if (stmt) - { - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Unknown statement option (Set)"; - sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); - SC_log_error(func, option, stmt); - } - if (conn) - { - conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - conn->errormsg = "Unknown statement option (Set)"; - sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); - CC_log_error(func, option, conn); - } - - return SQL_ERROR; - } - } - - if (changed) - { - if (stmt) - { - stmt->errormsg = "Requested value changed."; - stmt->errornumber = STMT_OPTION_VALUE_CHANGED; - } - if (conn) - { - conn->errormsg = "Requested value changed."; - conn->errornumber = STMT_OPTION_VALUE_CHANGED; - } - return SQL_SUCCESS_WITH_INFO; - } - else - return SQL_SUCCESS; -} - - -/* Implements only SQL_AUTOCOMMIT */ -RETCODE SQL_API -PGAPI_SetConnectOption( - HDBC hdbc, - UWORD fOption, - UDWORD vParam) -{ - static char *func = "PGAPI_SetConnectOption"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - char changed = FALSE; - RETCODE retval; - int i; - - mylog("%s: entering fOption = %d vParam = %d\n", func, fOption, vParam); - if (!conn) - { - CC_log_error(func, "", NULL); - 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: - case SQL_CURSOR_TYPE: - case SQL_KEYSET_SIZE: - case SQL_MAX_LENGTH: - case SQL_MAX_ROWS: - case SQL_NOSCAN: - case SQL_QUERY_TIMEOUT: - case SQL_RETRIEVE_DATA: - case SQL_ROWSET_SIZE: - case SQL_SIMULATE_CURSOR: - case SQL_USE_BOOKMARKS: - - /* Affect all current Statements */ - for (i = 0; i < conn->num_stmts; i++) - { - if (conn->stmts[i]) - set_statement_option(NULL, conn->stmts[i], fOption, vParam); - } - - /* - * Become the default for all future statements on this - * connection - */ - retval = set_statement_option(conn, NULL, fOption, vParam); - - if (retval == SQL_SUCCESS_WITH_INFO) - changed = TRUE; - else if (retval == SQL_ERROR) - return SQL_ERROR; - - 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"; - conn->errornumber = CONN_TRANSACT_IN_PROGRES; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - mylog("PGAPI_SetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam); - - switch (vParam) - { - case SQL_AUTOCOMMIT_OFF: - CC_set_autocommit_off(conn); - break; - - case SQL_AUTOCOMMIT_ON: - CC_set_autocommit_on(conn); - break; - - default: - conn->errormsg = "Illegal parameter value for SQL_AUTOCOMMIT"; - conn->errornumber = CONN_INVALID_ARGUMENT_NO; - 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 */ - break; - - 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: - case SQL_TRANSLATE_DLL: - case SQL_TRANSLATE_OPTION: - CC_log_error(func, "This connect option (Set) is only used by the Driver Manager", conn); - break; - - default: - { - char option[64]; - - conn->errormsg = "Unknown connect option (Set)"; - conn->errornumber = CONN_UNSUPPORTED_OPTION; - sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); - if (fOption == 30002 && vParam) - { - if (strcmp((char *) vParam, "Microsoft Jet") == 0) - { - conn->errornumber = 0; - conn->ms_jet = 1; - return SQL_SUCCESS; - } - } - CC_log_error(func, option, conn); - return SQL_ERROR; - } - } - - if (changed) - { - conn->errornumber = CONN_OPTION_VALUE_CHANGED; - conn->errormsg = "Requested value changed."; - return SQL_SUCCESS_WITH_INFO; - } - else - return SQL_SUCCESS; -} - - -/* This function just can tell you whether you are in Autcommit mode or not */ -RETCODE SQL_API -PGAPI_GetConnectOption( - HDBC hdbc, - UWORD fOption, - PTR pvParam) -{ - static char *func = "PGAPI_GetConnectOption"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - ConnInfo *ci = &(conn->connInfo); - - mylog("%s: entering...\n", func); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - switch (fOption) - { - case SQL_ACCESS_MODE: /* NOT SUPPORTED */ - *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE; - break; - - case SQL_AUTOCOMMIT: - *((UDWORD *) pvParam) = (UDWORD) (CC_is_in_autocommit(conn) ? - SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF); - break; - - case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */ - if (pvParam) - strcpy(pvParam, ""); - - break; - - case SQL_LOGIN_TIMEOUT: /* NOT SUPPORTED */ - *((UDWORD *) pvParam) = 0; - break; - - case SQL_PACKET_SIZE: /* NOT SUPPORTED */ - *((UDWORD *) pvParam) = ci->drivers.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: - case SQL_TRANSLATE_DLL: - case SQL_TRANSLATE_OPTION: - CC_log_error(func, "This connect option (Get) is only used by the Driver Manager", conn); - break; - - default: - { - char option[64]; - - conn->errormsg = "Unknown connect option (Get)"; - conn->errornumber = CONN_UNSUPPORTED_OPTION; - sprintf(option, "fOption=%d", fOption); - CC_log_error(func, option, conn); - return SQL_ERROR; - break; - } - } - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_SetStmtOption( - HSTMT hstmt, - UWORD fOption, - UDWORD vParam) -{ - static char *func = "PGAPI_SetStmtOption"; - 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); - return SQL_INVALID_HANDLE; - } - - return set_statement_option(NULL, stmt, fOption, vParam); -} - - -RETCODE SQL_API -PGAPI_GetStmtOption( - HSTMT hstmt, - UWORD fOption, - PTR pvParam) -{ - static char *func = "PGAPI_GetStmtOption"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); - - 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); - return SQL_INVALID_HANDLE; - } - - switch (fOption) - { - case SQL_GET_BOOKMARK: - case SQL_ROW_NUMBER: - - res = stmt->result; - - if (stmt->manual_result || !ci->drivers.use_declarefetch) - { - /* make sure we're positioned on a valid row */ - if ((stmt->currTuple < 0) || - (stmt->currTuple >= QR_get_num_tuples(res))) - { - stmt->errormsg = "Not positioned on a valid row."; - stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - else - { - if (stmt->currTuple == -1 || !res || !res->tupleField) - { - stmt->errormsg = "Not positioned on a valid row."; - stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - - if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF) - { - stmt->errormsg = "Operation invalid because use bookmarks not enabled."; - stmt->errornumber = STMT_OPERATION_INVALID; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - *((UDWORD *) pvParam) = SC_get_bookmark(stmt); - - break; - - case SQL_ASYNC_ENABLE: /* NOT SUPPORTED */ - *((SDWORD *) pvParam) = SQL_ASYNC_ENABLE_OFF; - break; - - case SQL_BIND_TYPE: - *((SDWORD *) pvParam) = stmt->options.bind_size; - break; - - case SQL_CONCURRENCY: /* NOT REALLY SUPPORTED */ - mylog("GetStmtOption(): SQL_CONCURRENCY\n"); - *((SDWORD *) pvParam) = stmt->options.scroll_concurrency; - break; - - case SQL_CURSOR_TYPE: /* PARTIAL SUPPORT */ - mylog("GetStmtOption(): SQL_CURSOR_TYPE\n"); - *((SDWORD *) pvParam) = stmt->options.cursor_type; - break; - - case SQL_KEYSET_SIZE: /* NOT SUPPORTED, but saved */ - mylog("GetStmtOption(): SQL_KEYSET_SIZE\n"); - *((SDWORD *) pvParam) = stmt->options.keyset_size; - break; - - case SQL_MAX_LENGTH: /* NOT SUPPORTED, but saved */ - *((SDWORD *) pvParam) = stmt->options.maxLength; - break; - - case SQL_MAX_ROWS: /* NOT SUPPORTED, but saved */ - *((SDWORD *) pvParam) = stmt->options.maxRows; - mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->options.maxRows); - break; - - case SQL_NOSCAN: /* NOT SUPPORTED */ - *((SDWORD *) pvParam) = SQL_NOSCAN_ON; - break; - - case SQL_QUERY_TIMEOUT: /* NOT SUPPORTED */ - *((SDWORD *) pvParam) = 0; - break; - - case SQL_RETRIEVE_DATA: - *((SDWORD *) pvParam) = stmt->options.retrieve_data; - break; - - case SQL_ROWSET_SIZE: - *((SDWORD *) pvParam) = stmt->options.rowset_size; - break; - - case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */ - *((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE; - break; - - case SQL_USE_BOOKMARKS: - *((SDWORD *) pvParam) = stmt->options.use_bookmarks; - break; - - default: - { - char option[64]; - - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Unknown statement option (Get)"; - sprintf(option, "fOption=%d", fOption); - SC_log_error(func, option, stmt); - return SQL_ERROR; - } - } - - return SQL_SUCCESS; -} diff --git a/src/interfaces/odbc/windev/parse.c b/src/interfaces/odbc/windev/parse.c deleted file mode 100644 index e73cb82a32..0000000000 --- a/src/interfaces/odbc/windev/parse.c +++ /dev/null @@ -1,954 +0,0 @@ -/*-------- - * 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 */ - -#include "psqlodbc.h" - -#include -#include -#include - -#include "statement.h" -#include "connection.h" -#include "qresult.h" -#include "pgtypes.h" -#include "pgapifunc.h" - -#ifdef MULTIBYTE -#include "multibyte.h" -#endif - -#define FLD_INCR 32 -#define TAB_INCR 8 -#define COL_INCR 16 - -char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric); -void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k); -char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi); - - -char * -getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric) -{ - int i = 0; - int out = 0; - char qc, - in_escape = FALSE; - - if (smax <= 1) - return NULL; - - smax--; - - /* skip leading delimiters */ - while (isspace((unsigned char) s[i]) || s[i] == ',') - { - /* mylog("skipping '%c'\n", s[i]); */ - i++; - } - - if (s[i] == '\0') - { - token[0] = '\0'; - return NULL; - } - - if (quote) - *quote = FALSE; - if (dquote) - *dquote = FALSE; - if (numeric) - *numeric = FALSE; - - /* get the next token */ - while (!isspace((unsigned char) s[i]) && s[i] != ',' && - s[i] != '\0' && out != smax) - { -#ifdef MULTIBYTE - if (multibyte_char_check(s[i]) != 0) - { - token[out++] = s[i++]; - continue; - } -#endif - /* Handle quoted stuff */ - if (out == 0 && (s[i] == '\"' || s[i] == '\'')) - { - qc = s[i]; - if (qc == '\"') - { - if (dquote) - *dquote = TRUE; - } - if (qc == '\'') - { - if (quote) - *quote = TRUE; - } - - i++; /* dont return the quote */ - while (s[i] != '\0' && out != smax) - { -#ifdef MULTIBYTE - if (multibyte_char_check(s[i]) != 0) - { - token[out++] = s[i++]; - continue; - } -#endif - if (s[i] == qc && !in_escape) - break; - if (s[i] == '\\' && !in_escape) - in_escape = TRUE; - else - { - in_escape = FALSE; - token[out++] = s[i]; - } - i++; - } - if (s[i] == qc) - i++; - break; - } - - /* Check for numeric literals */ - if (out == 0 && isdigit((unsigned char) s[i])) - { - if (numeric) - *numeric = TRUE; - token[out++] = s[i++]; - while (isalnum((unsigned char) s[i]) || s[i] == '.') - token[out++] = s[i++]; - - break; - } - - if (ispunct((unsigned char) s[i]) && s[i] != '_') - { - mylog("got ispunct: s[%d] = '%c'\n", i, s[i]); - - if (out == 0) - { - token[out++] = s[i++]; - break; - } - else - break; - } - - if (out != smax) - token[out++] = s[i]; - - i++; - } - - /* mylog("done -- s[%d] = '%c'\n", i, s[i]); */ - - token[out] = '\0'; - - /* find the delimiter */ - while (isspace((unsigned char) s[i])) - i++; - - /* return the most priority delimiter */ - if (s[i] == ',') - { - if (delim) - *delim = s[i]; - } - else if (s[i] == '\0') - { - if (delim) - *delim = '\0'; - } - else - { - if (delim) - *delim = ' '; - } - - /* skip trailing blanks */ - while (isspace((unsigned char) s[i])) - i++; - - return &s[i]; -} - - -#if 0 -QR_set_num_fields(stmt->result, 14); -QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); -QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); -QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); -QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); -QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2); -QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); -QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4); -QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4); -QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2); -QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2); -QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2); -QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254); -/* User defined fields */ -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); -#endif - -void -getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k) -{ - char *str; - - if (fi->name[0] == '\0') - strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3)); - - fi->type = atoi(QR_get_value_manual(col_info->result, k, 13)); - fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6)); - fi->length = atoi(QR_get_value_manual(col_info->result, k, 7)); - if (str = QR_get_value_manual(col_info->result, k, 8), str) - fi->scale = atoi(str); - else - fi->scale = -1; - fi->nullable = atoi(QR_get_value_manual(col_info->result, k, 10)); - fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12)); -} - - -char -searchColInfo(COL_INFO *col_info, FIELD_INFO *fi) -{ - int k, - cmp; - char *col; - - for (k = 0; k < QR_get_num_tuples(col_info->result); k++) - { - col = QR_get_value_manual(col_info->result, k, 3); - if (fi->dquote) - cmp = strcmp(col, fi->name); - else - cmp = stricmp(col, fi->name); - if (!cmp) - { - if (!fi->dquote) - strcpy(fi->name, col); - getColInfo(col_info, fi, k); - - mylog("PARSE: searchColInfo: \n"); - return TRUE; - } - } - - return FALSE; -} - - -char -parse_statement(StatementClass *stmt) -{ - static char *func = "parse_statement"; - char token[256]; - char delim, - quote, - dquote, - numeric, - unquoted; - char *ptr, - *pptr = NULL; - char in_select = FALSE, - in_distinct = FALSE, - in_on = FALSE, - in_from = FALSE, - from_found = FALSE, - in_where = FALSE, - in_table = FALSE; - char in_field = FALSE, - in_expr = FALSE, - in_func = FALSE, - in_dot = FALSE, - in_as = FALSE; - int j, - i, - k = 0, - n, - first_where = 0, - blevel = 0; - FIELD_INFO **fi; - TABLE_INFO **ti; - char parse; - ConnectionClass *conn = stmt->hdbc; - HSTMT hcol_stmt; - StatementClass *col_stmt; - RETCODE result; - - mylog("%s: entering...\n", func); - - ptr = stmt->statement; - fi = stmt->fi; - ti = stmt->ti; - - stmt->nfld = 0; - stmt->ntab = 0; - -#ifdef MULTIBYTE - multibyte_init(); -#endif - while (pptr = ptr, (ptr = getNextToken(pptr, 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); - - if (in_select && unquoted && blevel == 0) - { - if (!stricmp(token, "distinct")) - { - in_distinct = TRUE; - - mylog("DISTINCT\n"); - continue; - } - if (!stricmp(token, "into")) - { - in_select = FALSE; - mylog("INTO\n"); - stmt->statement_type = STMT_TYPE_CREATE; - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - if (!stricmp(token, "from")) - { - in_select = FALSE; - in_from = TRUE; - if (!from_found && - (!strnicmp(pptr, "from", 4))) - { - mylog("First "); - from_found = TRUE; - } - - mylog("FROM\n"); - continue; - } - } - if (unquoted && blevel == 0) - { - if ((!stricmp(token, "where") || - !stricmp(token, "union") || - !stricmp(token, "intersect") || - !stricmp(token, "except") || - !stricmp(token, "order") || - !stricmp(token, "group") || - !stricmp(token, "having"))) - { - in_select = FALSE; - in_from = FALSE; - in_where = TRUE; - - if (!first_where && - (!stricmp(token, "where"))) - first_where = ptr - stmt->statement; - - mylog("WHERE...\n"); - break; - } - } - if (in_select && (in_expr || in_func)) - { - /* just eat the expression */ - mylog("in_expr=%d or func=%d\n", in_expr, in_func); - - if (unquoted) - { - if (token[0] == '(') - { - blevel++; - mylog("blevel++ = %d\n", blevel); - } - else if (token[0] == ')') - { - blevel--; - mylog("blevel-- = %d\n", blevel); - } - } - if (blevel == 0) - { - if (delim == ',') - { - mylog("**** Got comma in_expr/func\n"); - in_func = FALSE; - in_expr = FALSE; - in_field = FALSE; - } - else if (unquoted && !stricmp(token, "as")) - { - mylog("got AS in_expr\n"); - in_func = FALSE; - in_expr = FALSE; - in_as = TRUE; - in_field = TRUE; - } - } - continue; - } - - if (unquoted && !stricmp(token, "select")) - { - in_select = TRUE; - - mylog("SELECT\n"); - continue; - } - if (in_select) - { - if (in_distinct) - { - mylog("in distinct\n"); - - if (unquoted && !stricmp(token, "on")) - { - in_on = TRUE; - mylog("got on\n"); - continue; - } - if (in_on) - { - in_distinct = FALSE; - in_on = FALSE; - continue; /* just skip the unique on field */ - } - mylog("done distinct\n"); - in_distinct = FALSE; - } - - if (!in_field) - { - if (!token[0]) - continue; - - if (!(stmt->nfld % FLD_INCR)) - { - mylog("reallocing at nfld=%d\n", stmt->nfld); - fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *)); - if (!fi) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - stmt->fi = fi; - } - - fi[stmt->nfld] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO)); - if (fi[stmt->nfld] == NULL) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - - /* Initialize the field info */ - memset(fi[stmt->nfld], 0, sizeof(FIELD_INFO)); - - /* double quotes are for qualifiers */ - if (dquote) - fi[stmt->nfld]->dquote = TRUE; - - if (quote) - { - fi[stmt->nfld]->quote = TRUE; - fi[stmt->nfld]->precision = strlen(token); - } - else if (numeric) - { - mylog("**** got numeric: nfld = %d\n", stmt->nfld); - fi[stmt->nfld]->numeric = TRUE; - } - else if (token[0] == '(') - { /* expression */ - mylog("got EXPRESSION\n"); - fi[stmt->nfld++]->expr = TRUE; - in_expr = TRUE; - blevel = 1; - continue; - } - else - { - strcpy(fi[stmt->nfld]->name, token); - fi[stmt->nfld]->dot[0] = '\0'; - } - mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot); - - if (delim == ',') - mylog("comma (1)\n"); - else - in_field = TRUE; - stmt->nfld++; - continue; - } - - /* - * We are in a field now - */ - if (in_dot) - { - stmt->nfld--; - strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name); - strcpy(fi[stmt->nfld]->name, token); - stmt->nfld++; - in_dot = FALSE; - - if (delim == ',') - { - mylog("in_dot: got comma\n"); - in_field = FALSE; - } - continue; - } - - if (in_as) - { - stmt->nfld--; - strcpy(fi[stmt->nfld]->alias, token); - mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias); - in_as = FALSE; - in_field = FALSE; - - stmt->nfld++; - - if (delim == ',') - mylog("comma(2)\n"); - continue; - } - - /* Function */ - if (token[0] == '(') - { - in_func = TRUE; - blevel = 1; - fi[stmt->nfld - 1]->func = TRUE; - - /* - * name will have the function name -- maybe useful some - * day - */ - mylog("**** got function = '%s'\n", fi[stmt->nfld - 1]->name); - continue; - } - - if (token[0] == '.') - { - in_dot = TRUE; - mylog("got dot\n"); - continue; - } - - if (!stricmp(token, "as")) - { - in_as = TRUE; - mylog("got AS\n"); - continue; - } - - /* otherwise, it's probably an expression */ - in_expr = TRUE; - fi[stmt->nfld - 1]->expr = TRUE; - fi[stmt->nfld - 1]->name[0] = '\0'; - fi[stmt->nfld - 1]->precision = 0; - mylog("*** setting expression\n"); - } - - if (in_from) - { - if (!in_table) - { - if (!token[0]) - continue; - - if (!(stmt->ntab % TAB_INCR)) - { - ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *)); - if (!ti) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - stmt->ti = ti; - } - ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO)); - if (ti[stmt->ntab] == NULL) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - - ti[stmt->ntab]->alias[0] = '\0'; - - strcpy(ti[stmt->ntab]->name, token); - if (!dquote) - { - char *ptr; - - /* lower case table name */ - for (ptr = ti[stmt->ntab]->name; *ptr; ptr++) - { -#ifdef MULTIBYTE - if ((unsigned char) *ptr >= 0x80) - ptr++; - else -#endif /* MULTIBYTE */ - *ptr = tolower((unsigned char) *ptr); - } - } - mylog("got table = '%s'\n", ti[stmt->ntab]->name); - - if (delim == ',') - mylog("more than 1 tables\n"); - else - in_table = TRUE; - stmt->ntab++; - continue; - } - - strcpy(ti[stmt->ntab - 1]->alias, token); - mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias); - in_table = FALSE; - if (delim == ',') - 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; - fi[i]->type = -1; - parse = FALSE; - continue; - } - else if (fi[i]->quote) - { /* handle as text */ - fi[i]->ti = NULL; - - /* - * fi[i]->type = PG_TYPE_TEXT; fi[i]->precision = 0; the - * following may be better - */ - fi[i]->type = PG_TYPE_UNKNOWN; - if (fi[i]->precision == 0) - { - fi[i]->type = PG_TYPE_VARCHAR; - fi[i]->precision = 254; - } - fi[i]->length = fi[i]->precision; - continue; - } - /* it's a dot, resolve to table or alias */ - else if (fi[i]->dot[0]) - { - for (k = 0; k < stmt->ntab; k++) - { - if (!stricmp(ti[k]->name, fi[i]->dot)) - { - fi[i]->ti = ti[k]; - break; - } - else if (!stricmp(ti[k]->alias, fi[i]->dot)) - { - fi[i]->ti = ti[k]; - break; - } - } - } - else if (stmt->ntab == 1) - fi[i]->ti = ti[0]; - } - - mylog("--------------------------------------------\n"); - mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab); - - for (i = 0; i < stmt->nfld; i++) - { - mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot); - if (fi[i]->ti) - mylog(" ----> table_name='%s', table_alias='%s'\n", fi[i]->ti->name, fi[i]->ti->alias); - } - - 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; - - for (k = 0; k < conn->ntables; k++) - { - if (!stricmp(conn->col_info[k]->name, ti[i]->name)) - { - mylog("FOUND col_info table='%s'\n", ti[i]->name); - found = TRUE; - break; - } - } - - if (!found) - { - mylog("PARSE: Getting PG_Columns for table[%d]='%s'\n", i, ti[i]->name); - - result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = "PGAPI_AllocStmt failed in parse_statement for columns."; - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - - col_stmt = (StatementClass *) hcol_stmt; - col_stmt->internal = TRUE; - - result = PGAPI_Columns(hcol_stmt, "", 0, "", 0, - ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0); - - mylog(" Past PG_Columns\n"); - if (result == SQL_SUCCESS) - { - 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 *)); - if (!conn->col_info) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - } - - mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables); - conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO)); - if (!conn->col_info[conn->ntables]) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - - /* - * Store the table name and the SQLColumns result - * structure - */ - strcpy(conn->col_info[conn->ntables]->name, ti[i]->name); - conn->col_info[conn->ntables]->result = col_stmt->result; - - /* - * The connection will now free the result structures, so - * make sure that the statement doesn't free it - */ - col_stmt->result = NULL; - - conn->ntables++; - - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - mylog("Created col_info table='%s', ntables=%d\n", ti[i]->name, conn->ntables); - } - else - { - PGAPI_FreeStmt(hcol_stmt, SQL_DROP); - break; - } - } - - /* Associate a table from the statement with a SQLColumn info */ - ti[i]->col_info = conn->col_info[k]; - mylog("associate col_info: i=%d, k=%d\n", i, k); - } - - mylog("Done PG_Columns\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) - { - i++; - continue; - } - - /* Stars get expanded to all fields in the table */ - else if (fi[i]->name[0] == '*') - { - char do_all_tables; - int total_cols, - old_alloc, - new_size, - cols; - int increased_cols; - - mylog("expanding field %d\n", i); - - total_cols = 0; - - if (fi[i]->ti) /* The star represents only the qualified - * table */ - total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result); - - else - { /* The star represents all tables */ - - /* Calculate the total number of columns after expansion */ - for (k = 0; k < stmt->ntab; k++) - total_cols += QR_get_num_tuples(ti[k]->col_info->result); - } - 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; - - mylog("k=%d, increased_cols=%d, old_alloc=%d, new_size=%d\n", k, increased_cols, old_alloc, new_size); - - if (new_size > old_alloc) - { - int new_alloc = ((new_size / FLD_INCR) + 1) * FLD_INCR; - - mylog("need more cols: new_alloc = %d\n", new_alloc); - fi = (FIELD_INFO **) realloc(fi, new_alloc * sizeof(FIELD_INFO *)); - if (!fi) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - stmt->fi = fi; - } - - /* - * copy any other fields (if there are any) up past the - * expansion - */ - for (j = stmt->nfld - 1; j > i; j--) - { - mylog("copying field %d to %d\n", j, increased_cols + j); - fi[increased_cols + j] = fi[j]; - } - 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); - - for (n = 0; n < cols; n++) - { - mylog("creating field info: n=%d\n", n); - /* skip malloc (already did it for the Star) */ - if (k > 0 || n > 0) - { - mylog("allocating field info at %d\n", n + i); - fi[n + i] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO)); - if (fi[n + i] == NULL) - { - stmt->parse_status = STMT_PARSE_FATAL; - return FALSE; - } - } - /* Initialize the new space (or the * field) */ - memset(fi[n + i], 0, sizeof(FIELD_INFO)); - fi[n + i]->ti = the_ti; - - mylog("about to copy at %d\n", n + i); - - getColInfo(the_ti->col_info, fi[n + i], n); - - mylog("done copying\n"); - } - - i += cols; - mylog("i now at %d\n", i); - } - } - - /* - * We either know which table the field was in because it was - * qualified with a table name or alias -OR- there was only 1 - * table. - */ - else if (fi[i]->ti) - { - if (!searchColInfo(fi[i]->ti->col_info, fi[i])) - parse = FALSE; - - i++; - } - - /* Don't know the table -- search all tables in "from" list */ - else - { - parse = FALSE; - for (k = 0; k < stmt->ntab; k++) - { - if (searchColInfo(ti[k]->col_info, fi[i])) - { - fi[i]->ti = ti[k]; /* now know the table */ - parse = TRUE; - break; - } - } - i++; - } - } - - 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; -} diff --git a/src/interfaces/odbc/windev/pgapifunc.h b/src/interfaces/odbc/windev/pgapifunc.h deleted file mode 100644 index 2ebf20371a..0000000000 --- a/src/interfaces/odbc/windev/pgapifunc.h +++ /dev/null @@ -1,244 +0,0 @@ -/*------- - * Module: pgapifunc.h - * - *------- - */ -#ifndef _PG_API_FUNC_H__ -#define _PG_API_FUNC_H__ - -#include "psqlodbc.h" -#include -#include - - -RETCODE SQL_API PGAPI_AllocConnect(HENV EnvironmentHandle, - HDBC FAR * ConnectionHandle); -RETCODE SQL_API PGAPI_AllocEnv(HENV FAR * EnvironmentHandle); -RETCODE SQL_API PGAPI_AllocStmt(HDBC ConnectionHandle, - HSTMT *StatementHandle); -RETCODE SQL_API PGAPI_BindCol(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, - PTR TargetValue, SQLINTEGER BufferLength, - SQLINTEGER *StrLen_or_Ind); -RETCODE SQL_API PGAPI_Cancel(HSTMT StatementHandle); -RETCODE SQL_API PGAPI_Columns(HSTMT StatementHandle, - SQLCHAR *CatalogName, SQLSMALLINT NameLength1, - SQLCHAR *SchemaName, SQLSMALLINT NameLength2, - SQLCHAR *TableName, SQLSMALLINT NameLength3, - SQLCHAR *ColumnName, SQLSMALLINT NameLength4); -RETCODE SQL_API PGAPI_Connect(HDBC ConnectionHandle, - SQLCHAR *ServerName, SQLSMALLINT NameLength1, - SQLCHAR *UserName, SQLSMALLINT NameLength2, - SQLCHAR *Authentication, SQLSMALLINT NameLength3); -RETCODE SQL_API PGAPI_DriverConnect(HDBC hdbc, HWND hwnd, - UCHAR FAR * szConnStrIn, SWORD cbConnStrIn, - UCHAR FAR * szConnStrOut, SWORD cbConnStrOutMax, - SWORD FAR * pcbConnStrOut, UWORD fDriverCompletion); -RETCODE SQL_API PGAPI_BrowseConnect(HDBC hdbc, - SQLCHAR *szConnStrIn, SQLSMALLINT cbConnStrIn, - SQLCHAR *szConnStrOut, SQLSMALLINT cbConnStrOutMax, - SQLSMALLINT *pcbConnStrOut); -RETCODE SQL_API PGAPI_DataSources(HENV EnvironmentHandle, - SQLUSMALLINT Direction, SQLCHAR *ServerName, - SQLSMALLINT BufferLength1, SQLSMALLINT *NameLength1, - SQLCHAR *Description, SQLSMALLINT BufferLength2, - SQLSMALLINT *NameLength2); -RETCODE SQL_API PGAPI_DescribeCol(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, - SQLSMALLINT BufferLength, SQLSMALLINT *NameLength, - SQLSMALLINT *DataType, SQLUINTEGER *ColumnSize, - SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable); -RETCODE SQL_API PGAPI_Disconnect(HDBC ConnectionHandle); -RETCODE SQL_API PGAPI_Error(HENV EnvironmentHandle, - HDBC ConnectionHandle, HSTMT StatementHandle, - SQLCHAR *Sqlstate, SQLINTEGER *NativeError, - SQLCHAR *MessageText, SQLSMALLINT BufferLength, - SQLSMALLINT *TextLength); -RETCODE SQL_API PGAPI_ExecDirect(HSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength); -RETCODE SQL_API PGAPI_Execute(HSTMT StatementHandle); -RETCODE SQL_API PGAPI_Fetch(HSTMT StatementHandle); -RETCODE SQL_API PGAPI_FreeConnect(HDBC ConnectionHandle); -RETCODE SQL_API PGAPI_FreeEnv(HENV EnvironmentHandle); -RETCODE SQL_API PGAPI_FreeStmt(HSTMT StatementHandle, - SQLUSMALLINT Option); -RETCODE SQL_API PGAPI_GetConnectOption(HDBC ConnectionHandle, - SQLUSMALLINT Option, PTR Value); -RETCODE SQL_API PGAPI_GetCursorName(HSTMT StatementHandle, - SQLCHAR *CursorName, SQLSMALLINT BufferLength, - SQLSMALLINT *NameLength); -RETCODE SQL_API PGAPI_GetData(HSTMT StatementHandle, - SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, - PTR TargetValue, SQLINTEGER BufferLength, - SQLINTEGER *StrLen_or_Ind); -RETCODE SQL_API PGAPI_GetFunctions(HDBC ConnectionHandle, - SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported); -RETCODE SQL_API PGAPI_GetFunctions30(HDBC ConnectionHandle, - SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported); -RETCODE SQL_API PGAPI_GetInfo(HDBC ConnectionHandle, - SQLUSMALLINT InfoType, PTR InfoValue, - SQLSMALLINT BufferLength, SQLSMALLINT *StringLength); -RETCODE SQL_API PGAPI_GetInfo30(HDBC ConnectionHandle, - SQLUSMALLINT InfoType, PTR InfoValue, - SQLSMALLINT BufferLength, SQLSMALLINT *StringLength); -RETCODE SQL_API PGAPI_GetStmtOption(HSTMT StatementHandle, - SQLUSMALLINT Option, PTR Value); -RETCODE SQL_API PGAPI_GetTypeInfo(HSTMT StatementHandle, - SQLSMALLINT DataType); -RETCODE SQL_API PGAPI_NumResultCols(HSTMT StatementHandle, - SQLSMALLINT *ColumnCount); -RETCODE SQL_API PGAPI_ParamData(HSTMT StatementHandle, - PTR *Value); -RETCODE SQL_API PGAPI_Prepare(HSTMT StatementHandle, - SQLCHAR *StatementText, SQLINTEGER TextLength); -RETCODE SQL_API PGAPI_PutData(HSTMT StatementHandle, - PTR Data, SQLINTEGER StrLen_or_Ind); -RETCODE SQL_API PGAPI_RowCount(HSTMT StatementHandle, - SQLINTEGER *RowCount); -RETCODE SQL_API PGAPI_SetConnectOption(HDBC ConnectionHandle, - SQLUSMALLINT Option, SQLUINTEGER Value); -RETCODE SQL_API PGAPI_SetCursorName(HSTMT StatementHandle, - SQLCHAR *CursorName, SQLSMALLINT NameLength); -RETCODE SQL_API PGAPI_SetParam(HSTMT StatementHandle, - SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, - SQLSMALLINT ParameterType, SQLUINTEGER LengthPrecision, - SQLSMALLINT ParameterScale, PTR ParameterValue, - SQLINTEGER *StrLen_or_Ind); -RETCODE SQL_API PGAPI_SetStmtOption(HSTMT StatementHandle, - SQLUSMALLINT Option, SQLUINTEGER Value); -RETCODE SQL_API PGAPI_SpecialColumns(HSTMT StatementHandle, - SQLUSMALLINT IdentifierType, SQLCHAR *CatalogName, - SQLSMALLINT NameLength1, SQLCHAR *SchemaName, - SQLSMALLINT NameLength2, SQLCHAR *TableName, - SQLSMALLINT NameLength3, SQLUSMALLINT Scope, - SQLUSMALLINT Nullable); -RETCODE SQL_API PGAPI_Statistics(HSTMT StatementHandle, - SQLCHAR *CatalogName, SQLSMALLINT NameLength1, - SQLCHAR *SchemaName, SQLSMALLINT NameLength2, - SQLCHAR *TableName, SQLSMALLINT NameLength3, - SQLUSMALLINT Unique, SQLUSMALLINT Reserved); -RETCODE SQL_API PGAPI_Tables(HSTMT StatementHandle, - SQLCHAR *CatalogName, SQLSMALLINT NameLength1, - SQLCHAR *SchemaName, SQLSMALLINT NameLength2, - SQLCHAR *TableName, SQLSMALLINT NameLength3, - SQLCHAR *TableType, SQLSMALLINT NameLength4); -RETCODE SQL_API PGAPI_Transact(HENV EnvironmentHandle, - HDBC ConnectionHandle, SQLUSMALLINT CompletionType); -RETCODE SQL_API PGAPI_ColAttributes( - HSTMT hstmt, - SQLUSMALLINT icol, - SQLUSMALLINT fDescType, - PTR rgbDesc, - SQLSMALLINT cbDescMax, - SQLSMALLINT *pcbDesc, - SQLINTEGER *pfDesc); -RETCODE SQL_API PGAPI_ColumnPrivileges( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szTableName, - SQLSMALLINT cbTableName, - SQLCHAR *szColumnName, - SQLSMALLINT cbColumnName); -RETCODE SQL_API PGAPI_DescribeParam( - HSTMT hstmt, - SQLUSMALLINT ipar, - SQLSMALLINT *pfSqlType, - SQLUINTEGER *pcbParamDef, - SQLSMALLINT *pibScale, - SQLSMALLINT *pfNullable); -RETCODE SQL_API PGAPI_ExtendedFetch( - HSTMT hstmt, - SQLUSMALLINT fFetchType, - SQLINTEGER irow, - SQLUINTEGER *pcrow, - SQLUSMALLINT *rgfRowStatus); -RETCODE SQL_API PGAPI_ForeignKeys( - HSTMT hstmt, - SQLCHAR *szPkCatalogName, - SQLSMALLINT cbPkCatalogName, - SQLCHAR *szPkSchemaName, - SQLSMALLINT cbPkSchemaName, - SQLCHAR *szPkTableName, - SQLSMALLINT cbPkTableName, - SQLCHAR *szFkCatalogName, - SQLSMALLINT cbFkCatalogName, - SQLCHAR *szFkSchemaName, - SQLSMALLINT cbFkSchemaName, - SQLCHAR *szFkTableName, - SQLSMALLINT cbFkTableName); -RETCODE SQL_API PGAPI_MoreResults( - HSTMT hstmt); -RETCODE SQL_API PGAPI_NativeSql( - HDBC hdbc, - SQLCHAR *szSqlStrIn, - SQLINTEGER cbSqlStrIn, - SQLCHAR *szSqlStr, - SQLINTEGER cbSqlStrMax, - SQLINTEGER *pcbSqlStr); -RETCODE SQL_API PGAPI_NumParams( - HSTMT hstmt, - SQLSMALLINT *pcpar); -RETCODE SQL_API PGAPI_ParamOptions( - HSTMT hstmt, - SQLUINTEGER crow, - SQLUINTEGER *pirow); -RETCODE SQL_API PGAPI_PrimaryKeys( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szTableName, - SQLSMALLINT cbTableName); -RETCODE SQL_API PGAPI_ProcedureColumns( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szProcName, - SQLSMALLINT cbProcName, - SQLCHAR *szColumnName, - SQLSMALLINT cbColumnName); -RETCODE SQL_API PGAPI_Procedures( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szProcName, - SQLSMALLINT cbProcName); -RETCODE SQL_API PGAPI_SetPos( - HSTMT hstmt, - SQLUSMALLINT irow, - SQLUSMALLINT fOption, - SQLUSMALLINT fLock); -RETCODE SQL_API PGAPI_TablePrivileges( - HSTMT hstmt, - SQLCHAR *szCatalogName, - SQLSMALLINT cbCatalogName, - SQLCHAR *szSchemaName, - SQLSMALLINT cbSchemaName, - SQLCHAR *szTableName, - SQLSMALLINT cbTableName); -RETCODE SQL_API PGAPI_BindParameter( - HSTMT hstmt, - SQLUSMALLINT ipar, - SQLSMALLINT fParamType, - SQLSMALLINT fCType, - SQLSMALLINT fSqlType, - SQLUINTEGER cbColDef, - SQLSMALLINT ibScale, - PTR rgbValue, - SQLINTEGER cbValueMax, - SQLINTEGER *pcbValue); -RETCODE SQL_API PGAPI_SetScrollOptions( - HSTMT hstmt, - UWORD fConcurrency, - SDWORD crowKeyset, - UWORD crowRowset); - -#endif /* define_PG_API_FUNC_H__ */ diff --git a/src/interfaces/odbc/windev/pgtypes.c b/src/interfaces/odbc/windev/pgtypes.c deleted file mode 100644 index 1388650a65..0000000000 --- a/src/interfaces/odbc/windev/pgtypes.c +++ /dev/null @@ -1,1109 +0,0 @@ -/*-------- - * 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. - *-------- - */ - -#include "pgtypes.h" - -#include "dlg_specific.h" -#include "statement.h" -#include "connection.h" -#include "qresult.h" - - - -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, - PG_TYPE_CHAR2, - PG_TYPE_CHAR4, - PG_TYPE_CHAR8, - PG_TYPE_CHAR16, - PG_TYPE_NAME, - PG_TYPE_VARCHAR, - PG_TYPE_BPCHAR, - PG_TYPE_DATE, - PG_TYPE_TIME, - PG_TYPE_DATETIME, - PG_TYPE_ABSTIME, - PG_TYPE_TIMESTAMP, - PG_TYPE_TEXT, - PG_TYPE_INT2, - PG_TYPE_INT4, - PG_TYPE_FLOAT4, - PG_TYPE_FLOAT8, - PG_TYPE_OID, - PG_TYPE_MONEY, - PG_TYPE_BOOL, - PG_TYPE_BYTEA, - PG_TYPE_LO, - 0 }; -*/ - - -/* These are NOW the SQL Types reported in SQLGetTypeInfo. */ -Int2 sqlTypes[] = { - SQL_BIGINT, - /* SQL_BINARY, -- Commented out because VarBinary is more correct. */ - SQL_BIT, - SQL_CHAR, - SQL_DATE, - SQL_DECIMAL, - SQL_DOUBLE, - SQL_FLOAT, - SQL_INTEGER, - SQL_LONGVARBINARY, - SQL_LONGVARCHAR, - SQL_NUMERIC, - SQL_REAL, - SQL_SMALLINT, - SQL_TIME, - SQL_TIMESTAMP, - SQL_TINYINT, - SQL_VARBINARY, - SQL_VARCHAR, - 0 -}; - - -Int4 -sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) -{ - Int4 pgType; - ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); - - switch (fSqlType) - { - case SQL_BINARY: - pgType = PG_TYPE_BYTEA; - break; - - case SQL_CHAR: - pgType = PG_TYPE_BPCHAR; - break; - - case SQL_BIT: - pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL; - break; - - case SQL_DATE: - pgType = PG_TYPE_DATE; - break; - - case SQL_DOUBLE: - case SQL_FLOAT: - pgType = PG_TYPE_FLOAT8; - break; - - case SQL_DECIMAL: - case SQL_NUMERIC: - pgType = PG_TYPE_NUMERIC; - break; - - case SQL_BIGINT: - pgType = PG_TYPE_INT8; - break; - - case SQL_INTEGER: - pgType = PG_TYPE_INT4; - break; - - case SQL_LONGVARBINARY: - pgType = PG_TYPE_LO; - break; - - case SQL_LONGVARCHAR: - pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; - break; - - case SQL_REAL: - pgType = PG_TYPE_FLOAT4; - break; - - case SQL_SMALLINT: - case SQL_TINYINT: - pgType = PG_TYPE_INT2; - break; - - case SQL_TIME: - pgType = PG_TYPE_TIME; - break; - - case SQL_TIMESTAMP: - pgType = PG_TYPE_DATETIME; - break; - - case SQL_VARBINARY: - pgType = PG_TYPE_BYTEA; - break; - - case SQL_VARCHAR: - pgType = PG_TYPE_VARCHAR; - break; - - default: - pgType = 0; /* ??? */ - break; - } - - 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) -{ - ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); - - switch (type) - { - case PG_TYPE_CHAR: - case PG_TYPE_CHAR2: - case PG_TYPE_CHAR4: - case PG_TYPE_CHAR8: - case PG_TYPE_NAME: - return SQL_CHAR; - - case PG_TYPE_BPCHAR: - return SQL_CHAR; - - case PG_TYPE_VARCHAR: - return SQL_VARCHAR; - - case PG_TYPE_TEXT: - return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; - - case PG_TYPE_BYTEA: - return SQL_VARBINARY; - case PG_TYPE_LO: - return SQL_LONGVARBINARY; - - case PG_TYPE_INT2: - return SQL_SMALLINT; - - case PG_TYPE_OID: - case PG_TYPE_XID: - 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; - - case PG_TYPE_NUMERIC: - return SQL_NUMERIC; - - case PG_TYPE_FLOAT4: - return SQL_REAL; - case PG_TYPE_FLOAT8: - return SQL_FLOAT; - case PG_TYPE_DATE: - return SQL_DATE; - case PG_TYPE_TIME: - return SQL_TIME; - case PG_TYPE_ABSTIME: - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP: - return SQL_TIMESTAMP; - case PG_TYPE_MONEY: - return SQL_FLOAT; - case PG_TYPE_BOOL: - return ci->drivers.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 ci->drivers.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; - } -} - - -Int2 -pgtype_to_ctype(StatementClass *stmt, Int4 type) -{ - ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); - - switch (type) - { - case PG_TYPE_INT8: - return SQL_C_CHAR; - case PG_TYPE_NUMERIC: - return SQL_C_CHAR; - case PG_TYPE_INT2: - return SQL_C_SSHORT; - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - return SQL_C_SLONG; - case PG_TYPE_FLOAT4: - return SQL_C_FLOAT; - case PG_TYPE_FLOAT8: - return SQL_C_DOUBLE; - case PG_TYPE_DATE: - return SQL_C_DATE; - case PG_TYPE_TIME: - return SQL_C_TIME; - case PG_TYPE_ABSTIME: - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP: - return SQL_C_TIMESTAMP; - case PG_TYPE_MONEY: - return SQL_C_FLOAT; - case PG_TYPE_BOOL: - return ci->drivers.bools_as_char ? SQL_C_CHAR : SQL_C_BIT; - - case PG_TYPE_BYTEA: - return SQL_C_BINARY; - case PG_TYPE_LO: - 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; - } -} - - -char * -pgtype_to_name(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_CHAR: - return "char"; - case PG_TYPE_CHAR2: - return "char2"; - case PG_TYPE_CHAR4: - return "char4"; - case PG_TYPE_CHAR8: - return "char8"; - case PG_TYPE_INT8: - return "int8"; - case PG_TYPE_NUMERIC: - return "numeric"; - case PG_TYPE_VARCHAR: - return "varchar"; - case PG_TYPE_BPCHAR: - return "char"; - case PG_TYPE_TEXT: - return "text"; - case PG_TYPE_NAME: - return "name"; - case PG_TYPE_INT2: - return "int2"; - case PG_TYPE_OID: - return "oid"; - case PG_TYPE_INT4: - return "int4"; - case PG_TYPE_FLOAT4: - return "float4"; - case PG_TYPE_FLOAT8: - return "float8"; - case PG_TYPE_DATE: - return "date"; - case PG_TYPE_TIME: - return "time"; - case PG_TYPE_ABSTIME: - return "abstime"; - case PG_TYPE_DATETIME: - return "datetime"; - case PG_TYPE_TIMESTAMP: - return "timestamp"; - case PG_TYPE_MONEY: - return "money"; - case PG_TYPE_BOOL: - return "bool"; - case PG_TYPE_BYTEA: - return "bytea"; - - case PG_TYPE_LO: - return PG_TYPE_LO_NAME; - - default: - /* hack until permanent type is available */ - if (type == stmt->hdbc->lobj_type) - return PG_TYPE_LO_NAME; - - /* - * "unknown" can actually be used in alter table because it is - * a real PG type! - */ - return "unknown"; - } -} - - -static Int2 -getNumericScale(StatementClass *stmt, Int4 type, int col) -{ - Int4 atttypmod; - QResultClass *result; - ColumnInfoClass *flds; - - mylog("getNumericScale: type=%d, col=%d\n", type, col); - - if (col < 0) - return PG_NUMERIC_MAX_SCALE; - - result = SC_get_Result(stmt); - - /* - * Manual Result Sets -- use assigned column width (i.e., from - * set_tuplefield_string) - */ - if (stmt->manual_result) - { - flds = result->fields; - if (flds) - return flds->adtsize[col]; - else - return PG_NUMERIC_MAX_SCALE; - } - - atttypmod = QR_get_atttypmod(result, col); - if (atttypmod > -1) - return (atttypmod & 0xffff); - else - return (QR_get_display_size(result, col) ? - QR_get_display_size(result, col) : - PG_NUMERIC_MAX_SCALE); -} - - -static Int4 -getNumericPrecision(StatementClass *stmt, Int4 type, int col) -{ - Int4 atttypmod; - QResultClass *result; - ColumnInfoClass *flds; - - mylog("getNumericPrecision: type=%d, col=%d\n", type, col); - - if (col < 0) - return PG_NUMERIC_MAX_PRECISION; - - result = SC_get_Result(stmt); - - /* - * Manual Result Sets -- use assigned column width (i.e., from - * set_tuplefield_string) - */ - if (stmt->manual_result) - { - flds = result->fields; - if (flds) - return flds->adtsize[col]; - else - return PG_NUMERIC_MAX_PRECISION; - } - - atttypmod = QR_get_atttypmod(result, col); - if (atttypmod > -1) - return (atttypmod >> 16) & 0xffff; - else - return (QR_get_display_size(result, col) >= 0 ? - QR_get_display_size(result, col) : - PG_NUMERIC_MAX_PRECISION); -} - - -Int4 -getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) -{ - int p = -1, - maxsize; - QResultClass *result; - ColumnInfoClass *flds; - ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); - - mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as); - - /* Assign Maximum size based on parameters */ - switch (type) - { - case PG_TYPE_TEXT: - if (ci->drivers.text_as_longvarchar) - maxsize = ci->drivers.max_longvarchar_size; - else - maxsize = ci->drivers.max_varchar_size; - break; - - case PG_TYPE_VARCHAR: - case PG_TYPE_BPCHAR: - maxsize = ci->drivers.max_varchar_size; - break; - - default: - if (ci->drivers.unknowns_as_longvarchar) - maxsize = ci->drivers.max_longvarchar_size; - else - maxsize = ci->drivers.max_varchar_size; - break; - } - - /* - * Static Precision (i.e., the Maximum Precision of the datatype) This - * has nothing to do with a result set. - */ - if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */ - { - if (PG_VERSION_GE(SC_get_conn(stmt), 7.1)) - maxsize = 0; - else - maxsize = TEXT_FIELD_SIZE; - } - if (col < 0) - return maxsize; - - result = SC_get_Result(stmt); - - /* - * Manual Result Sets -- use assigned column width (i.e., from - * set_tuplefield_string) - */ - if (stmt->manual_result) - { - flds = result->fields; - if (flds) - return flds->adtsize[col]; - else - return maxsize; - } - - /* Size is unknown -- handle according to parameter */ - if (QR_get_atttypmod(result, col) > -1) - return QR_get_atttypmod(result, col); - - if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST) - { - p = QR_get_display_size(result, col); - mylog("getCharPrecision: LONGEST: p = %d\n", p); - } - - if (p < 0 && handle_unknown_size_as == UNKNOWNS_AS_MAX) - return maxsize; - else - return p; -} - -static Int2 -getTimestampScale(StatementClass *stmt, Int4 type, int col) -{ - ConnectionClass *conn = SC_get_conn(stmt); - Int4 atttypmod; - QResultClass *result; - ColumnInfoClass *flds; - - mylog("getTimestampScale: type=%d, col=%d\n", type, col); - - if (col < 0) - return 0; - if (PG_VERSION_LT(conn, 7.2)) - return 0; - - result = SC_get_Result(stmt); - - /* - * Manual Result Sets -- use assigned column width (i.e., from - * set_tuplefield_string) - */ - atttypmod = 0; - if (stmt->manual_result) - { - flds = result->fields; - if (flds) - atttypmod = flds->atttypmod[col]; - mylog("atttypmod1=%d\n", atttypmod); - } - else - atttypmod = QR_get_atttypmod(result, col); - mylog("atttypmod2=%d\n", atttypmod); - return (atttypmod > -1 ? atttypmod : 0); -} - - -static Int4 -getTimestampPrecision(StatementClass *stmt, Int4 type, int col) -{ - Int4 fixed, - scale; - - mylog("getTimestampPrecision: type=%d, col=%d\n", type, col); - - switch (type) - { - case PG_TYPE_TIME: - fixed = 8; - break; - case PG_TYPE_TIME_WITH_TMZONE: - fixed = 11; - break; - case PG_TYPE_TIMESTAMP_NO_TMZONE: - fixed = 19; - break; - default: - fixed = 22; - break; - } - scale = getTimestampScale(stmt, type, col); - return (scale > 0) ? fixed + 1 + scale : fixed; -} - -/* - * 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: - return 2; - case PG_TYPE_CHAR4: - return 4; - case PG_TYPE_CHAR8: - return 8; - - case PG_TYPE_NAME: - return NAME_FIELD_SIZE; - - case PG_TYPE_INT2: - return 5; - - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - return 10; - - case PG_TYPE_INT8: - return 19; /* signed */ - - case PG_TYPE_NUMERIC: - return getNumericPrecision(stmt, type, col); - - case PG_TYPE_FLOAT4: - case PG_TYPE_MONEY: - return 7; - - case PG_TYPE_FLOAT8: - return 15; - - case PG_TYPE_DATE: - return 10; - case PG_TYPE_TIME: - return 8; - - case PG_TYPE_ABSTIME: - case PG_TYPE_TIMESTAMP: - return 22; - case PG_TYPE_DATETIME: - /* return 22; */ - return getTimestampPrecision(stmt, type, col); - - case PG_TYPE_BOOL: - return 1; - - case PG_TYPE_LO: - return SQL_NO_TOTAL; - - default: - - if (type == stmt->hdbc->lobj_type) /* hack until permanent - * type is available */ - return SQL_NO_TOTAL; - - /* Handle Character types and unknown types */ - return getCharPrecision(stmt, type, col, handle_unknown_size_as); - } -} - - -Int4 -pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) -{ - switch (type) - { - case PG_TYPE_INT2: - return 6; - - case PG_TYPE_OID: - case PG_TYPE_XID: - return 10; - - case PG_TYPE_INT4: - return 11; - - case PG_TYPE_INT8: - return 20; /* signed: 19 digits + sign */ - - case PG_TYPE_NUMERIC: - return getNumericPrecision(stmt, type, col) + 2; - - case PG_TYPE_MONEY: - return 15; /* ($9,999,999.99) */ - - case PG_TYPE_FLOAT4: - return 13; - - 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; - - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - return 4; - - case PG_TYPE_INT8: - return 20; /* signed: 19 digits + sign */ - - case PG_TYPE_NUMERIC: - return getNumericPrecision(stmt, type, col) + 2; - - case PG_TYPE_FLOAT4: - case PG_TYPE_MONEY: - return 4; - - case PG_TYPE_FLOAT8: - return 8; - - case PG_TYPE_DATE: - case PG_TYPE_TIME: - return 6; /* sizeof(DATE(TIME)_STRUCT) */ - - case PG_TYPE_ABSTIME: - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP: - return 16; /* sizeof(TIMESTAMP_STRUCT) */ - - /* Character types (and NUMERIC) use the default precision */ - case PG_TYPE_VARCHAR: - case PG_TYPE_BPCHAR: -#ifdef MULTIBYTE - /* after 7.2 */ - if (PG_VERSION_GE(SC_get_conn(stmt), 7.2)) - return 3 * pgtype_precision(stmt, type, col, handle_unknown_size_as); - else -#else - /* CR -> CR/LF */ - return 2 * pgtype_precision(stmt, type, col, handle_unknown_size_as); -#endif /* MULTIBYTE */ - default: - return pgtype_precision(stmt, type, col, handle_unknown_size_as); - } -} - - -Int2 -pgtype_scale(StatementClass *stmt, Int4 type, int col) -{ - switch (type) - { - case PG_TYPE_INT2: - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - case PG_TYPE_INT8: - case PG_TYPE_FLOAT4: - case PG_TYPE_FLOAT8: - 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_TIMESTAMP: - return 0; - case PG_TYPE_DATETIME: - /* return 0; */ - return getTimestampScale(stmt, type, col); - - case PG_TYPE_NUMERIC: - return getNumericScale(stmt, type, col); - - default: - return -1; - } -} - - -Int2 -pgtype_radix(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_INT2: - case PG_TYPE_OID: - case PG_TYPE_INT4: - case PG_TYPE_INT8: - case PG_TYPE_NUMERIC: - case PG_TYPE_FLOAT4: - case PG_TYPE_MONEY: - case PG_TYPE_FLOAT8: - return 10; - default: - return -1; - } -} - - -Int2 -pgtype_nullable(StatementClass *stmt, Int4 type) -{ - return SQL_NULLABLE; /* everything should be nullable */ -} - - -Int2 -pgtype_auto_increment(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_INT2: - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - case PG_TYPE_FLOAT4: - case PG_TYPE_MONEY: - case PG_TYPE_BOOL: - case PG_TYPE_FLOAT8: - case PG_TYPE_INT8: - case PG_TYPE_NUMERIC: - - case PG_TYPE_DATE: - case PG_TYPE_TIME: - case PG_TYPE_ABSTIME: - case PG_TYPE_DATETIME: - case PG_TYPE_TIMESTAMP: - return FALSE; - - default: - return -1; - } -} - - -Int2 -pgtype_case_sensitive(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_CHAR: - - case PG_TYPE_CHAR2: - case PG_TYPE_CHAR4: - case PG_TYPE_CHAR8: - - case PG_TYPE_VARCHAR: - case PG_TYPE_BPCHAR: - case PG_TYPE_TEXT: - case PG_TYPE_NAME: - return TRUE; - - default: - return FALSE; - } -} - - -Int2 -pgtype_money(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_MONEY: - return TRUE; - default: - return FALSE; - } -} - - -Int2 -pgtype_searchable(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_CHAR: - case PG_TYPE_CHAR2: - case PG_TYPE_CHAR4: - case PG_TYPE_CHAR8: - - case PG_TYPE_VARCHAR: - case PG_TYPE_BPCHAR: - case PG_TYPE_TEXT: - case PG_TYPE_NAME: - return SQL_SEARCHABLE; - - default: - return SQL_ALL_EXCEPT_LIKE; - } -} - - -Int2 -pgtype_unsigned(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_OID: - case PG_TYPE_XID: - return TRUE; - - case PG_TYPE_INT2: - case PG_TYPE_INT4: - case PG_TYPE_INT8: - case PG_TYPE_NUMERIC: - case PG_TYPE_FLOAT4: - case PG_TYPE_FLOAT8: - case PG_TYPE_MONEY: - return FALSE; - - default: - return -1; - } -} - - -char * -pgtype_literal_prefix(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_INT2: - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - case PG_TYPE_INT8: - case PG_TYPE_NUMERIC: - case PG_TYPE_FLOAT4: - case PG_TYPE_FLOAT8: - case PG_TYPE_MONEY: - return NULL; - - default: - return "'"; - } -} - - -char * -pgtype_literal_suffix(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_INT2: - case PG_TYPE_OID: - case PG_TYPE_XID: - case PG_TYPE_INT4: - case PG_TYPE_INT8: - case PG_TYPE_NUMERIC: - case PG_TYPE_FLOAT4: - case PG_TYPE_FLOAT8: - case PG_TYPE_MONEY: - return NULL; - - default: - return "'"; - } -} - - -char * -pgtype_create_params(StatementClass *stmt, Int4 type) -{ - switch (type) - { - case PG_TYPE_CHAR: - case PG_TYPE_VARCHAR: - return "max. length"; - default: - return NULL; - } -} - - -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: - case SQL_VARCHAR: - case SQL_LONGVARCHAR: - case SQL_DECIMAL: - case SQL_NUMERIC: - case SQL_BIGINT: - return SQL_C_CHAR; - - case SQL_BIT: - return SQL_C_BIT; - - case SQL_TINYINT: - return SQL_C_STINYINT; - - case SQL_SMALLINT: - return SQL_C_SSHORT; - - case SQL_INTEGER: - return SQL_C_SLONG; - - case SQL_REAL: - return SQL_C_FLOAT; - - case SQL_FLOAT: - case SQL_DOUBLE: - return SQL_C_DOUBLE; - - case SQL_BINARY: - case SQL_VARBINARY: - case SQL_LONGVARBINARY: - return SQL_C_BINARY; - - case SQL_DATE: - return SQL_C_DATE; - - case SQL_TIME: - return SQL_C_TIME; - - case SQL_TIMESTAMP: - return SQL_C_TIMESTAMP; - - default: - /* should never happen */ - return SQL_C_CHAR; - } -} - -Int4 -ctype_length(Int2 ctype) -{ - switch (ctype) - { - case SQL_C_SSHORT: - case SQL_C_SHORT: - return sizeof(SWORD); - - case SQL_C_USHORT: - return sizeof(UWORD); - - case SQL_C_SLONG: - case SQL_C_LONG: - return sizeof(SDWORD); - - case SQL_C_ULONG: - return sizeof(UDWORD); - - case SQL_C_FLOAT: - return sizeof(SFLOAT); - - case SQL_C_DOUBLE: - return sizeof(SDOUBLE); - - case SQL_C_BIT: - return sizeof(UCHAR); - - case SQL_C_STINYINT: - case SQL_C_TINYINT: - return sizeof(SCHAR); - - case SQL_C_UTINYINT: - return sizeof(UCHAR); - - case SQL_C_DATE: - return sizeof(DATE_STRUCT); - - case SQL_C_TIME: - return sizeof(TIME_STRUCT); - - case SQL_C_TIMESTAMP: - return sizeof(TIMESTAMP_STRUCT); - - case SQL_C_BINARY: - case SQL_C_CHAR: - return 0; - - default: /* should never happen */ - return 0; - } -} diff --git a/src/interfaces/odbc/windev/pgtypes.h b/src/interfaces/odbc/windev/pgtypes.h deleted file mode 100644 index 1d276432ce..0000000000 --- a/src/interfaces/odbc/windev/pgtypes.h +++ /dev/null @@ -1,99 +0,0 @@ -/* File: pgtypes.h - * - * Description: See "pgtypes.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __PGTYPES_H__ -#define __PGTYPES_H__ - -#include "psqlodbc.h" - -/* the type numbers are defined by the OID's of the types' rows */ -/* in table pg_type */ - - -#if 0 -#define PG_TYPE_LO ???? /* waiting for permanent type */ -#endif - -#define PG_TYPE_BOOL 16 -#define PG_TYPE_BYTEA 17 -#define PG_TYPE_CHAR 18 -#define PG_TYPE_NAME 19 -#define PG_TYPE_INT8 20 -#define PG_TYPE_INT2 21 -#define PG_TYPE_INT2VECTOR 22 -#define PG_TYPE_INT4 23 -#define PG_TYPE_REGPROC 24 -#define PG_TYPE_TEXT 25 -#define PG_TYPE_OID 26 -#define PG_TYPE_TID 27 -#define PG_TYPE_XID 28 -#define PG_TYPE_CID 29 -#define PG_TYPE_OIDVECTOR 30 -#define PG_TYPE_SET 32 -#define PG_TYPE_CHAR2 409 -#define PG_TYPE_CHAR4 410 -#define PG_TYPE_CHAR8 411 -#define PG_TYPE_POINT 600 -#define PG_TYPE_LSEG 601 -#define PG_TYPE_PATH 602 -#define PG_TYPE_BOX 603 -#define PG_TYPE_POLYGON 604 -#define PG_TYPE_FILENAME 605 -#define PG_TYPE_FLOAT4 700 -#define PG_TYPE_FLOAT8 701 -#define PG_TYPE_ABSTIME 702 -#define PG_TYPE_RELTIME 703 -#define PG_TYPE_TINTERVAL 704 -#define PG_TYPE_UNKNOWN 705 -#define PG_TYPE_MONEY 790 -#define PG_TYPE_OIDINT2 810 -#define PG_TYPE_OIDINT4 910 -#define PG_TYPE_OIDNAME 911 -#define PG_TYPE_BPCHAR 1042 -#define PG_TYPE_VARCHAR 1043 -#define PG_TYPE_DATE 1082 -#define PG_TYPE_TIME 1083 -#define PG_TYPE_TIMESTAMP_NO_TMZONE 1114 /* since 7.2 */ -#define PG_TYPE_DATETIME 1184 -#define PG_TYPE_TIME_WITH_TMZONE 1266 /* since 7.1 */ -#define PG_TYPE_TIMESTAMP 1296 /* deprecated since 7.0 */ -#define PG_TYPE_NUMERIC 1700 - -/* extern Int4 pgtypes_defined[]; */ -extern Int2 sqlTypes[]; - -/* Defines for pgtype_precision */ -#define PG_STATIC (-1) - -Int4 sqltype_to_pgtype(StatementClass *stmt, Int2 fSqlType); - -Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type); -Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type); -char *pgtype_to_name(StatementClass *stmt, Int4 type); - -/* These functions can use static numbers or result sets(col parameter) */ -Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); -Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); -Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); - -Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col); -Int2 pgtype_radix(StatementClass *stmt, Int4 type); -Int2 pgtype_nullable(StatementClass *stmt, Int4 type); -Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type); -Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type); -Int2 pgtype_money(StatementClass *stmt, Int4 type); -Int2 pgtype_searchable(StatementClass *stmt, Int4 type); -Int2 pgtype_unsigned(StatementClass *stmt, Int4 type); -char *pgtype_literal_prefix(StatementClass *stmt, Int4 type); -char *pgtype_literal_suffix(StatementClass *stmt, Int4 type); -char *pgtype_create_params(StatementClass *stmt, Int4 type); - -Int2 sqltype_to_default_ctype(Int2 sqltype); -Int4 ctype_length(Int2 ctype); - -#endif diff --git a/src/interfaces/odbc/windev/psqlodbc.c b/src/interfaces/odbc/windev/psqlodbc.c deleted file mode 100644 index cc8d8b7bfb..0000000000 --- a/src/interfaces/odbc/windev/psqlodbc.c +++ /dev/null @@ -1,132 +0,0 @@ -/*-------- - * 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. - *-------- - */ - -#include "psqlodbc.h" -#include "dlg_specific.h" - -#ifdef WIN32 -#include -#endif - -GLOBAL_VALUES globals; - -RETCODE SQL_API SQLDummyOrdinal(void); - -#ifdef WIN32 -HINSTANCE NEAR s_hModule; /* Saved module handle. */ - -/* This is where the Driver Manager attaches to this Driver */ -BOOL WINAPI -DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) -{ - WORD wVersionRequested; - WSADATA wsaData; - - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - s_hModule = hInst; /* Save for dialog boxes */ - - /* Load the WinSock Library */ - wVersionRequested = MAKEWORD(1, 1); - - if (WSAStartup(wVersionRequested, &wsaData)) - return FALSE; - - /* Verify that this is the minimum version of WinSock */ - if (LOBYTE(wsaData.wVersion) != 1 || - HIBYTE(wsaData.wVersion) != 1) - { - WSACleanup(); - return FALSE; - } - - getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); - break; - - case DLL_THREAD_ATTACH: - break; - - case DLL_PROCESS_DETACH: - WSACleanup(); - return TRUE; - - case DLL_THREAD_DETACH: - break; - - default: - break; - } - - return TRUE; - - UNREFERENCED_PARAMETER(lpReserved); -} - -#else /* not WIN32 */ - -#ifndef TRUE -#define TRUE (BOOL)1 -#endif -#ifndef FALSE -#define FALSE (BOOL)0 -#endif - -#ifdef __GNUC__ - -/* This function is called at library initialization time. */ - -static BOOL -__attribute__((constructor)) -init(void) -{ - getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); - return TRUE; -} - -#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 -_init(void) -{ - getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL); - return TRUE; -} - -BOOL -_fini(void) -{ - return TRUE; -} -#endif /* not __GNUC__ */ -#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) -{ - return SQL_SUCCESS; -} diff --git a/src/interfaces/odbc/windev/psqlodbc.h b/src/interfaces/odbc/windev/psqlodbc.h deleted file mode 100644 index fa87918bd9..0000000000 --- a/src/interfaces/odbc/windev/psqlodbc.h +++ /dev/null @@ -1,268 +0,0 @@ -/* File: psqlodbc.h - * - * Description: This file contains defines and declarations that are related to - * the entire driver. - * - * Comments: See "notice.txt" for copyright and license information. - * - * $Id: psqlodbc.h,v 1.1 2002/01/11 02:50:01 inoue Exp $ - * - */ - -#ifndef __PSQLODBC_H__ -#define __PSQLODBC_H__ - -#ifndef WIN32 -#include "pg_config.h" -#else -#include -#endif - -#include /* for FILE* pointers: see GLOBAL_VALUES */ - -/* Must come before sql.h */ -#ifndef ODBCVER -#define ODBCVER 0x0250 -#endif /* ODBCVER_REP */ - - -#if defined(WIN32) || defined(WITH_UNIXODBC) || defined(WITH_IODBC) -#include -#include -#else -#include "iodbc.h" -#include "isql.h" -#include "isqlext.h" -#endif - -#if defined(WIN32) -#include -#elif defined(WITH_UNIXODBC) -#include -#elif defined(WITH_IODBC) -#include -#else -#include "gpps.h" -#endif - -#ifndef WIN32 -#define Int4 long int -#define UInt4 unsigned int -#define Int2 short -#define UInt2 unsigned short - -#if !defined(WITH_UNIXODBC) && !defined(WITH_IODBC) -typedef float SFLOAT; -typedef double SDOUBLE; -#endif - -#ifndef CALLBACK -#define CALLBACK -#endif - -#else -#define Int4 int -#define UInt4 unsigned int -#define Int2 short -#define UInt2 unsigned short -#endif - -typedef UInt4 Oid; - -#ifndef WIN32 -#define stricmp strcasecmp -#define strnicmp strncasecmp -#endif - -/* Driver stuff */ - -#define DRIVERNAME "PostgreSQL ODBC" -#if (ODBCVER >= 0x0300) -#define DRIVER_ODBC_VER "03.00" -#define DBMS_NAME "PostgreSQL30" -#else -#define DRIVER_ODBC_VER "02.50" -#define DBMS_NAME "PostgreSQL" -#endif /* ODBCVER */ - -#define POSTGRESDRIVERVERSION "07.01.0009" - -#ifdef WIN32 -#if (ODBCVER >= 0x0300) -#define DRIVER_FILE_NAME "PSQLODBC30.DLL" -#else -#define DRIVER_FILE_NAME "PSQLODBC.DLL" -#endif /* ODBCVER */ -#else -#define DRIVER_FILE_NAME "libpsqlodbc.so" -#endif /* WIN32 */ - -/* Limits */ -#ifdef WIN32 -#define BLCKSZ 4096 -#endif - -#define MAX_MESSAGE_LEN 65536 /* This puts a limit on - * query size but I don't */ - /* see an easy way round this - DJP 24-1-2001 */ -#define MAX_CONNECT_STRING 4096 -#define ERROR_MSG_LENGTH 4096 -#define FETCH_MAX 100 /* default number of rows to cache - * for declare/fetch */ -#define TUPLE_MALLOC_INC 100 -#define SOCK_BUFFER_SIZE 4096 /* default socket buffer - * size */ -#define MAX_CONNECTIONS 128 /* conns per environment - * (arbitrary) */ -#define MAX_FIELDS 512 -#define BYTELEN 8 -#define VARHDRSZ sizeof(Int4) - -#define MAX_TABLE_LEN 32 -#define MAX_COLUMN_LEN 32 -#define MAX_CURSOR_LEN 32 - -/* Registry length limits */ -#define LARGE_REGISTRY_LEN 4096 /* used for special cases */ -#define MEDIUM_REGISTRY_LEN 256 /* normal size for - * user,database,etc. */ -#define SMALL_REGISTRY_LEN 10 /* for 1/0 settings */ - - -/* These prefixes denote system tables */ -#define POSTGRES_SYS_PREFIX "pg_" -#define KEYS_TABLE "dd_fkey" - -/* Info limits */ -#define MAX_INFO_STRING 128 -#define MAX_KEYPARTS 20 -#define MAX_KEYLEN 512 /* max key of the form - * "date+outlet+invoice" */ -#define MAX_ROW_SIZE 0 /* Unlimited rowsize with the - * Tuple Toaster */ -#define MAX_STATEMENT_LEN 0 /* Unlimited statement size with - * 7.0 */ - -/* Previously, numerous query strings were defined of length MAX_STATEMENT_LEN */ -/* Now that's 0, lets use this instead. DJP 24-1-2001 */ -#define STD_STATEMENT_LEN MAX_MESSAGE_LEN - -#define PG62 "6.2" /* "Protocol" key setting - * to force Postgres 6.2 */ -#define PG63 "6.3" /* "Protocol" key setting - * to force postgres 6.3 */ -#define PG64 "6.4" - -typedef struct ConnectionClass_ ConnectionClass; -typedef struct StatementClass_ StatementClass; -typedef struct QResultClass_ QResultClass; -typedef struct SocketClass_ SocketClass; -typedef struct BindInfoClass_ BindInfoClass; -typedef struct ParameterInfoClass_ ParameterInfoClass; -typedef struct ColumnInfoClass_ ColumnInfoClass; -typedef struct TupleListClass_ TupleListClass; -typedef struct EnvironmentClass_ EnvironmentClass; -typedef struct TupleNode_ TupleNode; -typedef struct TupleField_ TupleField; - -typedef struct col_info COL_INFO; -typedef struct lo_arg LO_ARG; - -typedef struct GlobalValues_ -{ - int fetch_max; - int socket_buffersize; - int unknown_sizes; - int max_varchar_size; - int max_longvarchar_size; - char debug; - char commlog; - char disable_optimizer; - char ksqo; - char unique_index; - char onlyread; /* readonly is reserved on Digital C++ - * compiler */ - char use_declarefetch; - char text_as_longvarchar; - char unknowns_as_longvarchar; - char bools_as_char; - char lie; - char parse; - char cancel_as_freestmt; - char extra_systable_prefixes[MEDIUM_REGISTRY_LEN]; - char conn_settings[LARGE_REGISTRY_LEN]; - char protocol[SMALL_REGISTRY_LEN]; -} GLOBAL_VALUES; - -typedef struct StatementOptions_ -{ - int maxRows; - int maxLength; - int rowset_size; - int keyset_size; - int cursor_type; - int scroll_concurrency; - int retrieve_data; - int bind_size; /* size of each structure if using Row - * Binding */ - int use_bookmarks; - UInt4 *rowsFetched; - UInt2 *rowStatusArray; - void *bookmark_ptr; - UInt2 *row_operation_ptr; - UInt4 *row_offset_ptr; - UInt4 paramset_size; - UInt4 param_bind_type; - UInt4 *param_processed_ptr; - UInt2 *param_status_ptr; - UInt2 *param_operation_ptr; - UInt4 *param_offset_ptr; -} StatementOptions; - -/* Used to pass extra query info to send_query */ -typedef struct QueryInfo_ -{ - int row_size; - QResultClass *result_in; - char *cursor; -} QueryInfo; - -void logs_on_off(int cnopen, int, int); - -#define PG_TYPE_LO (-999) /* hack until permanent - * type available */ -#define PG_TYPE_LO_NAME "lo" -#define OID_ATTNUM (-2) /* the attnum in pg_index - * of the oid */ - -/* sizes */ -#define TEXT_FIELD_SIZE 8190 /* size of text fields - * (not including null - * term) */ -#define NAME_FIELD_SIZE 32 /* size of name fields */ -#define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not - * including null term) */ - -#define PG_NUMERIC_MAX_PRECISION 1000 -#define PG_NUMERIC_MAX_SCALE 1000 - -#define INFO_INQUIRY_LEN 8192 /* this seems sufficiently big for - * queries used in info.c inoue - * 2001/05/17 */ - -#include "misc.h" - -#ifdef _MEMORY_DEBUG_ -void *debug_alloc(size_t); -void *debug_realloc(void *, size_t); -char *debug_strdup(const char *); -void debug_free(void *); -void debug_memory_check(void); - -#define malloc debug_alloc -#define realloc debug_realloc -#define strdup debug_strdup -#define free debug_free -#endif /* _MEMORY_DEBUG_ */ - -#endif diff --git a/src/interfaces/odbc/windev/psqlodbc.rc b/src/interfaces/odbc/windev/psqlodbc.rc deleted file mode 100644 index 30a7ff7203..0000000000 --- a/src/interfaces/odbc/windev/psqlodbc.rc +++ /dev/null @@ -1,425 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -#ifdef MULTIBYTE -DLG_CONFIG DIALOG DISCARDABLE 65, 43, 299, 113 -STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | - WS_SYSMENU -CAPTION "PostgreSQL Driver Setup" -FONT 10, "Terminal" -BEGIN - RTEXT "&Data Source:",IDC_DSNAMETEXT,3,9,49,8,NOT WS_GROUP - EDITTEXT IDC_DSNAME,59,9,72,12,ES_AUTOHSCROLL | WS_GROUP - RTEXT "Des&cription:",IDC_DESCTEXT,135,10,49,8,NOT WS_GROUP - EDITTEXT IDC_DESC,185,10,110,25,ES_AUTOHSCROLL - RTEXT "Data&base:",IDC_STATIC,15,24,37,8,NOT WS_GROUP - EDITTEXT IDC_DATABASE,59,24,72,12,ES_AUTOHSCROLL - RTEXT "&Server:",IDC_STATIC,23,38,29,8,NOT WS_GROUP - EDITTEXT IDC_SERVER,59,38,72,12,ES_AUTOHSCROLL - RTEXT "&Port:",IDC_STATIC,161,38,21,8 - EDITTEXT IDC_PORT,185,38,37,12,ES_AUTOHSCROLL - RTEXT "&User Name:",IDC_STATIC,11,53,41,8 - EDITTEXT IDC_USER,59,53,72,12,ES_AUTOHSCROLL - RTEXT "Pass&word:",IDC_STATIC,145,53,37,8 - EDITTEXT IDC_PASSWORD,185,53,72,12,ES_PASSWORD | ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,27,88,40,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,81,88,40,14 - GROUPBOX "Options (Advanced):",IDC_OPTIONS,141,72,140,35, - BS_CENTER - PUSHBUTTON "Driver",IDC_DRIVER,149,89,50,14 - PUSHBUTTON "DataSource",IDC_DATASOURCE,221,88,50,14 - CTEXT "Please supply any missing information needed to connect.", - DRV_MSG_LABEL,25,4,238,10 -END - -DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 306, 226 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Advanced Options (Driver)" -FONT 10, "Terminal" -BEGIN - CONTROL "Disable Genetic &Optimizer",DRV_OPTIMIZER,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,13,11,116,10 - CONTROL "Comm&Log (C:\\psqlodbc.log)",DRV_COMMLOG,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,164,11,120,10 - CONTROL "&KSQO (Keyset Query Optimization)",DRV_KSQO,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,23,144,10 - CONTROL "&ReadOnly (Default)",DRV_READONLY,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,164,24,88,10 - CONTROL "Recognize Unique &Indexes",DRV_UNIQUEINDEX,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,35,112,10 - CONTROL "P&arse Statements",DRV_PARSE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,164,37,80,10 - CONTROL "&Use Declare/Fetch",DRV_USEDECLAREFETCH,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,47,84,10 - CONTROL "Cancel as FreeStmt (Exp)",DRV_CANCELASFREESTMT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,164,50,112,10 - CONTROL "Mylog(Debug ouput)",DRV_DEBUG,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,164,63,112,10 - GROUPBOX "Unknown Sizes",IDC_STATIC,13,76,175,24 - CONTROL "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,21,84,44,10 - CONTROL "Don't Know",DRV_UNKNOWN_DONTKNOW,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,72,84,56,10 - CONTROL "Longest",DRV_UNKNOWN_LONGEST,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,135,84,44,10 - GROUPBOX "Data Type Options",IDC_STATIC,13,104,282,23 - CONTROL "Text as LongVarChar",DRV_TEXT_LONGVARCHAR,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,115,92,10 - CONTROL "Unknowns as LongVarChar",DRV_UNKNOWNS_LONGVARCHAR, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,115,108,10 - CONTROL "Bools as Char",DRV_BOOLS_CHAR,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,225,115,68,10 - LTEXT "&Cache Size:",IDC_STATIC,15,133,45,8 - EDITTEXT DRV_CACHE_SIZE,61,129,35,12,ES_AUTOHSCROLL - LTEXT "Max &Varchar:",IDC_STATIC,99,133,49,8 - EDITTEXT DRV_VARCHAR_SIZE,149,129,35,12,ES_AUTOHSCROLL - LTEXT "Max Lon&gVarChar:",IDC_STATIC,192,133,65,8 - EDITTEXT DRV_LONGVARCHAR_SIZE,259,129,35,12,ES_AUTOHSCROLL - LTEXT "SysTable &Prefixes:",IDC_STATIC,23,144,36,20 - EDITTEXT DRV_EXTRASYSTABLEPREFIXES,61,153,75,12,ES_AUTOHSCROLL - LTEXT "Connect &Settings:",IDC_STATIC,22,165,35,20 - EDITTEXT DRV_CONNSETTINGS,61,165,225,25,ES_MULTILINE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,59,201,50,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,124,201,50,14 - PUSHBUTTON "Defaults",IDDEFAULTS,189,201,50,15 - CONTROL "Default",DRV_OR_DSN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | - BS_NOTIFY | WS_TABSTOP,247,205,40,10 -END - -DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Advanced Options (DataSource)" -FONT 10, "Terminal" -BEGIN - CONTROL "&ReadOnly",DS_READONLY,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,45,13,48,10 - CONTROL "Row &Versioning",DS_ROWVERSIONING,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,149,13,72,10 - CONTROL "Show System &Tables",DS_SHOWSYSTEMTABLES,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,45,28,88,10 - CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,149,28,86,10 - GROUPBOX "Protocol",IDC_STATIC,43,44,180,25 - CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,53,54,47,10 - CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, - 131,54,26,10 - CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, - 187,54,26,10 - GROUPBOX "OID Options",IDC_STATIC,43,74,180,25 - CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,53,85,59,10 - CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,161,85,55,10 - LTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25 - EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14 -END -#else -DLG_CONFIG DIALOG DISCARDABLE 65, 43, 292, 116 -STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | - WS_SYSMENU -CAPTION "PostgreSQL Driver Setup" -FONT 8, "MS Sans Serif" -BEGIN - RTEXT "&Data Source:",IDC_DSNAMETEXT,5,10,50,12,NOT WS_GROUP - EDITTEXT IDC_DSNAME,57,10,72,12,ES_AUTOHSCROLL | WS_GROUP - RTEXT "Des&cription:",IDC_DESCTEXT,135,10,39,12,NOT WS_GROUP - EDITTEXT IDC_DESC,175,10,108,12,ES_AUTOHSCROLL - RTEXT "Data&base:",IDC_STATIC,17,25,38,12,NOT WS_GROUP - EDITTEXT IDC_DATABASE,57,25,72,12,ES_AUTOHSCROLL - RTEXT "&Server:",IDC_STATIC,27,40,29,12,NOT WS_GROUP - EDITTEXT IDC_SERVER,57,40,72,12,ES_AUTOHSCROLL - RTEXT "&Port:",IDC_STATIC,153,40,22,12 - EDITTEXT IDC_PORT,175,40,37,12,ES_AUTOHSCROLL - RTEXT "&User Name:",IDC_STATIC,17,55,39,12 - EDITTEXT IDC_USER,57,55,72,12,ES_AUTOHSCROLL - RTEXT "Pass&word:",IDC_STATIC,141,55,34,12 - EDITTEXT IDC_PASSWORD,175,55,72,12,ES_PASSWORD | ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,25,90,40,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,80,90,40,14 - GROUPBOX "Options (Advanced):",IDC_OPTIONS,140,74,140,35, - BS_CENTER - PUSHBUTTON "Driver",IDC_DRIVER,160,90,50,14 - PUSHBUTTON "DataSource",IDC_DATASOURCE,220,90,50,14 - CTEXT "Please supply any missing information needed to connect.", - DRV_MSG_LABEL,36,5,220,15 -END - -DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 287, 241 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Advanced Options (Driver)" -FONT 8, "MS Sans Serif" -BEGIN - CONTROL "Disable Genetic &Optimizer",DRV_OPTIMIZER,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,5,97,10 - CONTROL "Comm&Log (C:\\psqlodbc.log)",DRV_COMMLOG,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,140,5,113,10 - CONTROL "&KSQO (Keyset Query Optimization)",DRV_KSQO,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,15,20,124,10 - CONTROL "&ReadOnly (Default)",DRV_READONLY,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,140,20,80,10 - CONTROL "Recognize Unique &Indexes",DRV_UNIQUEINDEX,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,15,35,101,10 - CONTROL "P&arse Statements",DRV_PARSE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,140,35,80,10 - CONTROL "&Use Declare/Fetch",DRV_USEDECLAREFETCH,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,15,50,80,10 - CONTROL "Cancel as FreeStmt (Exp)",DRV_CANCELASFREESTMT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,140,50,105,10 - CONTROL "Mylog(Debug ouput)",DRV_DEBUG,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,140,65,112,10 - GROUPBOX "Unknown Sizes",IDC_STATIC,10,80,175,25 - CONTROL "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,15,91,45,10 - CONTROL "Don't Know",DRV_UNKNOWN_DONTKNOW,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,70,91,53,10 - CONTROL "Longest",DRV_UNKNOWN_LONGEST,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,130,91,50,10 - GROUPBOX "Data Type Options",IDC_STATIC,10,110,270,25 - CONTROL "Text as LongVarChar",DRV_TEXT_LONGVARCHAR,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,120,80,10 - CONTROL "Unknowns as LongVarChar",DRV_UNKNOWNS_LONGVARCHAR, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,120,100,10 - CONTROL "Bools as Char",DRV_BOOLS_CHAR,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,215,120,60,10 - LTEXT "&Cache Size:",IDC_STATIC,10,145,40,10 - EDITTEXT DRV_CACHE_SIZE,50,145,35,12,ES_AUTOHSCROLL - LTEXT "Max &Varchar:",IDC_STATIC,90,145,45,10 - EDITTEXT DRV_VARCHAR_SIZE,135,145,35,12,ES_AUTOHSCROLL - LTEXT "Max Lon&gVarChar:",IDC_STATIC,180,145,60,10 - EDITTEXT DRV_LONGVARCHAR_SIZE,240,145,35,12,ES_AUTOHSCROLL - LTEXT "SysTable &Prefixes:",IDC_STATIC,15,160,35,20 - EDITTEXT DRV_EXTRASYSTABLEPREFIXES,50,166,75,12,ES_AUTOHSCROLL - RTEXT "Connect &Settings:",IDC_STATIC,10,185,35,20 - EDITTEXT DRV_CONNSETTINGS,50,185,225,25,ES_MULTILINE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,45,220,50,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,110,220,50,14 - PUSHBUTTON "Defaults",IDDEFAULTS,175,220,50,15 - CONTROL "Default",DRV_OR_DSN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | - BS_NOTIFY | WS_TABSTOP,233,224,40,10 -END - -DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Advanced Options (DataSource)" -FONT 8, "MS Sans Serif" -BEGIN - CONTROL "&ReadOnly",DS_READONLY,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,25,10,53,10 - CONTROL "Row &Versioning",DS_ROWVERSIONING,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,130,10,85,10 - CONTROL "Show System &Tables",DS_SHOWSYSTEMTABLES,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,25,25,85,10 - CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,130,25,85,10 - GROUPBOX "Protocol",IDC_STATIC,15,40,180,25 - CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | WS_GROUP,25, - 50,35,10 - CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, - 75,50,26,10 - CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, - 130,50,26,10 - GROUPBOX "OID Options",IDC_STATIC,15,70,180,25 - CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,25,81,59,10 - CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,115,81,51,10 - RTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25 - EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP - PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14 -END -#endif - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -#ifdef MULTIBYTE -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - DLG_CONFIG, DIALOG - BEGIN - BOTTOMMARGIN, 112 - END - - DLG_OPTIONS_DRV, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 301 - TOPMARGIN, 5 - BOTTOMMARGIN, 206 - END - - DLG_OPTIONS_DS, DIALOG - BEGIN - LEFTMARGIN, 5 - RIGHTMARGIN, 260 - TOPMARGIN, 7 - BOTTOMMARGIN, 154 - END -END -#else -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - DLG_CONFIG, DIALOG - BEGIN - BOTTOMMARGIN, 115 - END - - DLG_OPTIONS_DRV, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 280 - TOPMARGIN, 7 - BOTTOMMARGIN, 219 - END - - DLG_OPTIONS_DS, DIALOG - BEGIN - LEFTMARGIN, 5 - RIGHTMARGIN, 260 - VERTGUIDE, 55 - TOPMARGIN, 7 - BOTTOMMARGIN, 154 - END -END -#endif // MULTIBYTE -#endif // APSTUDIO_INVOKED - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 7,1,0,9 - PRODUCTVERSION 7,1,0,9 - FILEFLAGSMASK 0x3L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "Comments", "PostgreSQL ODBC driver\0" -#ifdef MULTIBYTE - VALUE "CompanyName", "Insight Distribution Systems & Sankyo Unyu Service (MULTIBYTE support)\0" -#else - VALUE "CompanyName", "Insight Distribution Systems\0" -#endif - VALUE "FileDescription", "PostgreSQL Driver\0" - VALUE "FileVersion", " 07.01.0009\0" - VALUE "InternalName", "psqlodbc\0" - VALUE "LegalCopyright", "\0" - VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0" - VALUE "OriginalFilename", "psqlodbc.dll\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "Microsoft Open Database Connectivity\0" - VALUE "ProductVersion", " 07.01.0009\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // !_MAC - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_BADDSN "Invalid DSN entry, please recheck." - IDS_MSGTITLE "Invalid DSN" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/interfaces/odbc/windev/psqlodbc.reg b/src/interfaces/odbc/windev/psqlodbc.reg deleted file mode 100644 index ac4322f942..0000000000 --- a/src/interfaces/odbc/windev/psqlodbc.reg +++ /dev/null @@ -1,17 +0,0 @@ -REGEDIT4 - -[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI] - -[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers] -"PostgreSQL"="Installed" - -[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL] -"APILevel"="1" -"ConnectFunctions"="YYN" -"Driver"="PSQLODBC.DLL" -"DriverODBCVer"="02.50" -"FileUsage"="0" -"Setup"="PSQLODBC.DLL" -"SQLLevel"="1" -"UsageCount"=dword:00000001 - diff --git a/src/interfaces/odbc/windev/psqlodbc_win32.def b/src/interfaces/odbc/windev/psqlodbc_win32.def deleted file mode 100644 index 23a5a82b39..0000000000 --- a/src/interfaces/odbc/windev/psqlodbc_win32.def +++ /dev/null @@ -1,60 +0,0 @@ -LIBRARY psqlodbc -EXPORTS -SQLAllocConnect @1 -SQLAllocEnv @2 -SQLAllocStmt @3 -SQLBindCol @4 -SQLCancel @5 -SQLColAttributes @6 -SQLConnect @7 -SQLDescribeCol @8 -SQLDisconnect @9 -SQLError @10 -SQLExecDirect @11 -SQLExecute @12 -SQLFetch @13 -SQLFreeConnect @14 -SQLFreeEnv @15 -SQLFreeStmt @16 -SQLGetCursorName @17 -SQLNumResultCols @18 -SQLPrepare @19 -SQLRowCount @20 -SQLSetCursorName @21 -SQLTransact @23 -SQLColumns @40 -SQLDriverConnect @41 -SQLGetConnectOption @42 -SQLGetData @43 -SQLGetFunctions @44 -SQLGetInfo @45 -SQLGetStmtOption @46 -SQLGetTypeInfo @47 -SQLParamData @48 -SQLPutData @49 -SQLSetConnectOption @50 -SQLSetStmtOption @51 -SQLSpecialColumns @52 -SQLStatistics @53 -SQLTables @54 -SQLBrowseConnect @55 -SQLColumnPrivileges @56 -SQLDescribeParam @58 -SQLExtendedFetch @59 -SQLForeignKeys @60 -SQLMoreResults @61 -SQLNativeSql @62 -SQLNumParams @63 -SQLParamOptions @64 -SQLPrimaryKeys @65 -SQLProcedureColumns @66 -SQLProcedures @67 -SQLSetPos @68 -SQLSetScrollOptions @69 -SQLTablePrivileges @70 -SQLBindParameter @72 -SQLDummyOrdinal @199 -dconn_FDriverConnectProc @200 -DllMain @201 -ConfigDSN @202 - diff --git a/src/interfaces/odbc/windev/qresult.c b/src/interfaces/odbc/windev/qresult.c deleted file mode 100644 index ca7a6dee9e..0000000000 --- a/src/interfaces/odbc/windev/qresult.c +++ /dev/null @@ -1,712 +0,0 @@ -/*--------- - * 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" - -#include "misc.h" -#include -#include - -#ifndef TRUE -#define TRUE (BOOL)1 -#endif -#ifndef FALSE -#define FALSE (BOOL)0 -#endif - - -/* - * 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) -{ - mylog("in QR_set_num_fields\n"); - - CI_set_num_fields(self->fields, new_num_fields); - if (self->manual_tuples) - TL_Destructor(self->manual_tuples); - - self->manual_tuples = TL_Constructor(new_num_fields); - - mylog("exit QR_set_num_fields\n"); -} - - -void -QR_set_position(QResultClass *self, int pos) -{ - self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields); -} - - -void -QR_set_cache_size(QResultClass *self, int cache_size) -{ - self->cache_size = cache_size; -} - - -void -QR_set_rowset_size(QResultClass *self, int rowset_size) -{ - self->rowset_size = rowset_size; -} - - -void -QR_inc_base(QResultClass *self, int base_inc) -{ - self->base += base_inc; -} - - -/* - * CLASS QResult - */ -QResultClass * -QR_Constructor() -{ - QResultClass *rv; - - mylog("in QR_Constructor\n"); - rv = (QResultClass *) malloc(sizeof(QResultClass)); - - if (rv != NULL) - { - rv->status = PGRES_EMPTY_QUERY; - - /* construct the column info */ - if (!(rv->fields = CI_Constructor())) - { - free(rv); - return NULL; - } - rv->manual_tuples = NULL; - rv->backend_tuples = NULL; - rv->message = NULL; - rv->command = NULL; - rv->notice = NULL; - rv->conn = NULL; - rv->inTuples = FALSE; - rv->fcount = 0; - rv->fetch_count = 0; - rv->base = 0; - rv->currTuple = -1; - rv->num_fields = 0; - rv->tupleField = NULL; - rv->cursor = NULL; - rv->aborted = FALSE; - - rv->cache_size = 0; - rv->rowset_size = 1; - } - - mylog("exit QR_Constructor\n"); - return rv; -} - - -void -QR_Destructor(QResultClass *self) -{ - mylog("QResult: in DESTRUCTOR\n"); - - /* manual result set tuples */ - 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 */ - - QR_free_memory(self); /* safe to call anyway */ - - /* Should have been freed in the close() but just in case... */ - if (self->cursor) - free(self->cursor); - - /* Free up column info */ - if (self->fields) - CI_Destructor(self->fields); - - /* Free command info (this is from strdup()) */ - if (self->command) - free(self->command); - - /* Free notice info (this is from strdup()) */ - if (self->notice) - free(self->notice); - - free(self); - - mylog("QResult: exit DESTRUCTOR\n"); -} - - -void -QR_set_command(QResultClass *self, char *msg) -{ - if (self->command) - free(self->command); - - self->command = msg ? strdup(msg) : NULL; -} - - -void -QR_set_notice(QResultClass *self, char *msg) -{ - if (self->notice) - free(self->notice); - - self->notice = msg ? strdup(msg) : NULL; -} - - -void -QR_free_memory(QResultClass *self) -{ - register int lf, - row; - register TupleField *tuple = self->backend_tuples; - int fcount = self->fcount; - int num_fields = self->num_fields; - - mylog("QResult: free memory in, fcount=%d\n", fcount); - - if (self->backend_tuples) - { - for (row = 0; row < fcount; row++) - { - mylog("row = %d, num_fields = %d\n", row, num_fields); - for (lf = 0; lf < num_fields; lf++) - { - if (tuple[lf].value != NULL) - { - mylog("free [lf=%d] %u\n", lf, tuple[lf].value); - free(tuple[lf].value); - } - } - tuple += num_fields; /* next row */ - } - - free(self->backend_tuples); - self->backend_tuples = NULL; - } - - self->fcount = 0; - - mylog("QResult: free memory out\n"); -} - - -/* This function is called by send_query() */ -char -QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor) -{ - 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) - { - ConnInfo *ci = &(conn->connInfo); - BOOL fetch_cursor = (ci->drivers.use_declarefetch && cursor && cursor[0]); - - self->conn = conn; - - mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor == NULL) ? "" : cursor, self->cursor); - - if (self->cursor) - free(self->cursor); - - if (fetch_cursor) - { - if (!cursor || cursor[0] == '\0') - { - self->status = PGRES_INTERNAL_ERROR; - QR_set_message(self, "Internal Error -- no cursor for fetch"); - return FALSE; - } - 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; - self->num_fields = CI_get_num_fields(self->fields); - } - else - { - self->status = PGRES_BAD_RESPONSE; - QR_set_message(self, "Error reading field information"); - return FALSE; - } - - mylog("QR_fetch_tuples: past CI_read_fields: num_fields = %d\n", self->num_fields); - - if (fetch_cursor) - tuple_size = self->cache_size; - else - tuple_size = TUPLE_MALLOC_INC; - - /* allocate memory for the tuple cache */ - mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size); - self->count_allocated = 0; - self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size); - if (!self->backend_tuples) - { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Could not get memory for tuple cache."); - return FALSE; - } - self->count_allocated = tuple_size; - - self->inTuples = TRUE; - - /* Force a read to occur in next_tuple */ - self->fcount = tuple_size + 1; - self->fetch_count = tuple_size + 1; - self->base = 0; - - return QR_next_tuple(self); - } - else - { - /* - * Always have to read the field attributes. But we dont have to - * reallocate memory for them! - */ - - if (!CI_read_fields(NULL, self->conn)) - { - self->status = PGRES_BAD_RESPONSE; - QR_set_message(self, "Error reading field information"); - return FALSE; - } - return TRUE; - } -} - - -/* - * 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) -{ - QResultClass *res; - - if (self->conn && self->cursor && self->conn->connInfo.drivers.use_declarefetch) - { - char buf[64]; - - sprintf(buf, "close %s", self->cursor); - mylog("QResult: closing cursor: '%s'\n", buf); - - res = CC_send_query(self->conn, buf, NULL); - - self->inTuples = FALSE; - self->currTuple = -1; - - free(self->cursor); - self->cursor = NULL; - - if (res == NULL) - { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Error closing cursor."); - return FALSE; - } - QR_Destructor(res); - - /* End the transaction if there are no cursors left on this conn */ - if (CC_is_in_autocommit(self->conn) && CC_cursor_count(self->conn) == 0) - { - mylog("QResult: END transaction on conn=%u\n", self->conn); - - res = CC_send_query(self->conn, "END", NULL); - - CC_set_no_trans(self->conn); - - if (res == NULL) - { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Error ending transaction."); - return FALSE; - } - QR_Destructor(res); - } - } - - return TRUE; -} - - -/* This function is called by fetch_tuples() AND SQLFetch() */ -int -QR_next_tuple(QResultClass *self) -{ - int id; - QResultClass *res; - SocketClass *sock; - - /* Speed up access */ - int fetch_count = self->fetch_count; - int fcount = self->fcount; - int fetch_size, - offset = 0; - int end_tuple = self->rowset_size + self->base; - char corrected = FALSE; - TupleField *the_tuples = self->backend_tuples; - - /* ERROR_MSG_LENGTH is sufficient */ - static char msgbuffer[ERROR_MSG_LENGTH + 1]; - - /* QR_set_command() dups this string so doesn't need static */ - char cmdbuffer[ERROR_MSG_LENGTH + 1]; - char fetch[128]; - QueryInfo qi; - ConnInfo *ci = NULL; - - 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, - * just fall through and read the tuples. - */ - self->tupleField = NULL; - - if (!self->inTuples) - { - ci = &(self->conn->connInfo); - if (!self->cursor || !ci->drivers.use_declarefetch) - { - mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count); - self->tupleField = NULL; - self->status = PGRES_END_TUPLES; - return -1; /* end of tuples */ - } - - if (self->base == fcount) - { - /* not a correction */ - /* Determine the optimum cache size. */ - if (ci->drivers.fetch_max % self->rowset_size == 0) - fetch_size = ci->drivers.fetch_max; - else if (self->rowset_size < ci->drivers.fetch_max) - fetch_size = (ci->drivers.fetch_max / self->rowset_size) * self->rowset_size; - else - fetch_size = self->rowset_size; - - self->cache_size = fetch_size; - self->fetch_count = 1; - } - else - { - /* need to correct */ - corrected = TRUE; - - fetch_size = end_tuple - fcount; - - self->cache_size += fetch_size; - - offset = self->fetch_count; - self->fetch_count++; - } - - if (!self->backend_tuples || self->cache_size > self->count_allocated) - { - self->count_allocated = 0; - self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size); - if (!self->backend_tuples) - { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Out of memory while reading tuples."); - return FALSE; - } - self->count_allocated = self->cache_size; - } - sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor); - - mylog("next_tuple: sending actual fetch (%d) query '%s'\n", fetch_size, fetch); - - /* don't read ahead for the next tuple (self) ! */ - qi.row_size = self->cache_size; - qi.result_in = self; - qi.cursor = NULL; - res = CC_send_query(self->conn, fetch, &qi); - if (res == NULL || QR_get_aborted(res)) - { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Error fetching next group."); - if (res) - QR_Destructor(res); - return FALSE; - } - self->inTuples = TRUE; - } - else - { - mylog("next_tuple: inTuples = true, falling through: fcount = %d, fetch_count = %d\n", self->fcount, self->fetch_count); - - /* - * This is a pre-fetch (fetching rows right after query but - * before any real SQLFetch() calls. This is done so the - * field attributes are available. - */ - self->fetch_count = 0; - } - } - - if (!corrected) - { - self->base = 0; - self->fcount = 0; - } - - sock = CC_get_socket(self->conn); - self->tupleField = NULL; - ci = &(self->conn->connInfo); - - 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"); - return FALSE; - case 'B': /* Tuples in binary format */ - case 'D': /* Tuples in ASCII format */ - - if ((!self->cursor || !ci->drivers.use_declarefetch) && self->fcount >= self->count_allocated) - { - int tuple_size = self->count_allocated; - - mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size); - tuple_size *= 2; - self->backend_tuples = (TupleField *) realloc(self->backend_tuples, - tuple_size * self->num_fields * sizeof(TupleField)); - if (!self->backend_tuples) - { - self->status = PGRES_FATAL_ERROR; - QR_set_message(self, "Out of memory while reading tuples."); - return FALSE; - } - self->count_allocated = tuple_size; - } - - if (!QR_read_tuple(self, (char) (id == 0))) - { - self->status = PGRES_BAD_RESPONSE; - 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, ERROR_MSG_LENGTH); - QR_set_command(self, cmdbuffer); - - mylog("end of tuple list -- setting inUse to false: this = %u\n", self); - - 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); - - /* set to first row */ - self->tupleField = self->backend_tuples + (offset * self->num_fields); - 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 */ - } - - case 'E': /* Error */ - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - QR_set_message(self, msgbuffer); - self->status = PGRES_FATAL_ERROR; - - if (!strncmp(msgbuffer, "FATAL", 5)) - CC_set_no_trans(self->conn); - - qlog("ERROR from backend in next_tuple: '%s'\n", msgbuffer); - - return FALSE; - - case 'N': /* Notice */ - SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); - QR_set_message(self, msgbuffer); - self->status = PGRES_NONFATAL_ERROR; - qlog("NOTICE from backend in next_tuple: '%s'\n", msgbuffer); - continue; - - default: /* this should only happen if the backend - * dumped core */ - mylog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id); - qlog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id); - QR_set_message(self, "Unexpected result from backend. It probably crashed"); - self->status = PGRES_FATAL_ERROR; - CC_set_no_trans(self->conn); - return FALSE; - } - } - return TRUE; -} - - -char -QR_read_tuple(QResultClass *self, char binary) -{ - Int2 field_lf; - TupleField *this_tuplefield; - char bmp, - bitmap[MAX_FIELDS]; /* Max. len of the bitmap */ - Int2 bitmaplen; /* len of the bitmap in bytes */ - Int2 bitmap_pos; - Int2 bitcnt; - Int4 len; - char *buffer; - int num_fields = self->num_fields; /* speed up access */ - 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); - - bitmaplen = (Int2) num_fields / BYTELEN; - if ((num_fields % BYTELEN) > 0) - bitmaplen++; - - /* - * At first the server sends a bitmap that indicates which database - * fields are null - */ - SOCK_get_n_char(sock, bitmap, bitmaplen); - - bitmap_pos = 0; - bitcnt = 0; - bmp = bitmap[bitmap_pos]; - - for (field_lf = 0; field_lf < num_fields; field_lf++) - { - /* Check if the current field is NULL */ - if (!(bmp & 0200)) - { - /* YES, it is NULL ! */ - this_tuplefield[field_lf].len = 0; - this_tuplefield[field_lf].value = 0; - } - else - { - /* - * NO, the field is not null. so get at first the length of - * the field (four bytes) - */ - len = SOCK_get_int(sock, VARHDRSZ); - if (!binary) - len -= VARHDRSZ; - - buffer = (char *) malloc(len + 1); - SOCK_get_n_char(sock, buffer, len); - buffer[len] = '\0'; - - mylog("qresult: len=%d, buffer='%s'\n", len, buffer); - - this_tuplefield[field_lf].len = len; - this_tuplefield[field_lf].value = buffer; - - /* - * This can be used to set the longest length of the column - * for any row in the tuple cache. It would not be accurate - * for varchar and text fields to use this since a tuple cache - * is only 100 rows. Bpchar can be handled since the strlen of - * all rows is fixed, assuming there are not 100 nulls in a - * row! - */ - - flds = self->fields; - if (flds->display_size[field_lf] < len) - flds->display_size[field_lf] = len; - } - - /* - * Now adjust for the next bit to be scanned in the next loop. - */ - bitcnt++; - if (BYTELEN == bitcnt) - { - bitmap_pos++; - bmp = bitmap[bitmap_pos]; - bitcnt = 0; - } - else - bmp <<= 1; - } - self->currTuple++; - return TRUE; -} diff --git a/src/interfaces/odbc/windev/qresult.h b/src/interfaces/odbc/windev/qresult.h deleted file mode 100644 index 251bc449c1..0000000000 --- a/src/interfaces/odbc/windev/qresult.h +++ /dev/null @@ -1,131 +0,0 @@ -/* File: qresult.h - * - * Description: See "qresult.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __QRESULT_H__ -#define __QRESULT_H__ - -#include "psqlodbc.h" - -#include "connection.h" -#include "socket.h" -#include "columninfo.h" -#include "tuplelist.h" -#include "tuple.h" - -enum QueryResultCode_ -{ - PGRES_EMPTY_QUERY = 0, - PGRES_COMMAND_OK, /* a query command that doesn't return */ - /* anything was executed properly by the backend */ - PGRES_TUPLES_OK, /* a query command that returns tuples */ - /* was executed properly by the backend, PGresult */ - /* contains the resulttuples */ - PGRES_COPY_OUT, - PGRES_COPY_IN, - PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from - * the backend */ - PGRES_NONFATAL_ERROR, - PGRES_FATAL_ERROR, - PGRES_FIELDS_OK, /* field information from a query was - * successful */ - PGRES_END_TUPLES, - PGRES_INTERNAL_ERROR -}; -typedef enum QueryResultCode_ QueryResultCode; - - -struct QResultClass_ -{ - ColumnInfoClass *fields; /* the Column information */ - TupleListClass *manual_tuples; /* manual result tuple list */ - ConnectionClass *conn; /* the connection this result is using - * (backend) */ - - /* Stuff for declare/fetch tuples */ - int count_allocated; /* m(re)alloced count */ - int fetch_count; /* logical rows read so far */ - int fcount; /* actual rows read in the fetch */ - int currTuple; - int base; - - int num_fields; /* number of fields in the result */ - int cache_size; - int rowset_size; - - QueryResultCode status; - - char *message; - char *cursor; /* The name of the cursor for select - * statements */ - char *command; - char *notice; - - TupleField *backend_tuples; /* data from the backend (the tuple cache) */ - TupleField *tupleField; /* current backend tuple being retrieved */ - - char inTuples; /* is a fetch of rows from the backend in - * progress? */ - char aborted; /* was aborted? */ -}; - -#define QR_get_fields(self) (self->fields) - - -/* These functions are for retrieving data from the qresult */ -#define QR_get_value_manual(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno)) -#define QR_get_value_backend(self, fieldno) (self->tupleField[fieldno].value) -#define QR_get_value_backend_row(self, tupleno, fieldno) ((self->backend_tuples + (tupleno * self->num_fields))[fieldno].value) - -/* These functions are used by both manual and backend results */ -#define QR_NumResultCols(self) (CI_get_num_fields(self->fields)) -#define QR_get_fieldname(self, fieldno_) (CI_get_fieldname(self->fields, fieldno_)) -#define QR_get_fieldsize(self, fieldno_) (CI_get_fieldsize(self->fields, fieldno_)) -#define QR_get_display_size(self, fieldno_) (CI_get_display_size(self->fields, fieldno_)) -#define QR_get_atttypmod(self, fieldno_) (CI_get_atttypmod(self->fields, fieldno_)) -#define QR_get_field_type(self, fieldno_) (CI_get_oid(self->fields, fieldno_)) - -/* These functions are used only for manual result sets */ -#define QR_get_num_tuples(self) (self->manual_tuples ? TL_get_num_tuples(self->manual_tuples) : self->fcount) -#define QR_add_tuple(self, new_tuple) (TL_add_tuple(self->manual_tuples, new_tuple)) -#define QR_set_field_info(self, field_num, name, adtid, adtsize) (CI_set_field_info(self->fields, field_num, name, adtid, adtsize, -1)) - -/* status macros */ -#define QR_command_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR)) -#define QR_command_nonfatal(self) ( self->status == PGRES_NONFATAL_ERROR) -#define QR_end_tuples(self) ( self->status == PGRES_END_TUPLES) -#define QR_set_status(self, condition) ( self->status = condition ) -#define QR_set_message(self, message_) ( self->message = message_) -#define QR_set_aborted(self, aborted_) ( self->aborted = aborted_) - -#define QR_get_message(self) (self->message) -#define QR_get_command(self) (self->command) -#define QR_get_notice(self) (self->notice) -#define QR_get_status(self) (self->status) -#define QR_get_aborted(self) (self->aborted) - -#define QR_aborted(self) (!self || self->aborted) - -/* Core Functions */ -QResultClass *QR_Constructor(void); -void QR_Destructor(QResultClass *self); -char QR_read_tuple(QResultClass *self, char binary); -int QR_next_tuple(QResultClass *self); -int QR_close(QResultClass *self); -char QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor); -void QR_free_memory(QResultClass *self); -void QR_set_command(QResultClass *self, char *msg); -void QR_set_notice(QResultClass *self, char *msg); - -void QR_set_num_fields(QResultClass *self, int new_num_fields); /* manual result only */ - -void QR_inc_base(QResultClass *self, int base_inc); -void QR_set_cache_size(QResultClass *self, int cache_size); -void QR_set_rowset_size(QResultClass *self, int rowset_size); -void QR_set_position(QResultClass *self, int pos); - -#endif diff --git a/src/interfaces/odbc/windev/resource.h b/src/interfaces/odbc/windev/resource.h deleted file mode 100644 index b8bbd4fcfc..0000000000 --- a/src/interfaces/odbc/windev/resource.h +++ /dev/null @@ -1,66 +0,0 @@ -/* {{NO_DEPENDENCIES}} */ -/* Microsoft Developer Studio generated include file. */ -/* Used by psqlodbc.rc */ -/* */ -#define IDS_BADDSN 1 -#define IDS_MSGTITLE 2 -#define DLG_OPTIONS_DRV 102 -#define DLG_OPTIONS_DS 103 -#define IDC_DSNAME 400 -#define IDC_DSNAMETEXT 401 -#define IDC_DESC 404 -#define IDC_SERVER 407 -#define IDC_DATABASE 408 -#define DLG_CONFIG 1001 -#define IDC_PORT 1002 -#define IDC_USER 1006 -#define IDC_PASSWORD 1009 -#define DS_READONLY 1011 -#define DS_SHOWOIDCOLUMN 1012 -#define DS_FAKEOIDINDEX 1013 -#define DRV_COMMLOG 1014 -#define DS_PG62 1016 -#define IDC_DATASOURCE 1018 -#define DRV_OPTIMIZER 1019 -#define DS_CONNSETTINGS 1020 -#define IDC_DRIVER 1021 -#define DRV_CONNSETTINGS 1031 -#define DRV_UNIQUEINDEX 1032 -#define DRV_UNKNOWN_MAX 1035 -#define DRV_UNKNOWN_DONTKNOW 1036 -#define DRV_READONLY 1037 -#define IDC_DESCTEXT 1039 -#define DRV_MSG_LABEL 1040 -#define DRV_UNKNOWN_LONGEST 1041 -#define DRV_TEXT_LONGVARCHAR 1043 -#define DRV_UNKNOWNS_LONGVARCHAR 1044 -#define DRV_CACHE_SIZE 1045 -#define DRV_VARCHAR_SIZE 1046 -#define DRV_LONGVARCHAR_SIZE 1047 -#define IDDEFAULTS 1048 -#define DRV_USEDECLAREFETCH 1049 -#define DRV_BOOLS_CHAR 1050 -#define DS_SHOWSYSTEMTABLES 1051 -#define DRV_EXTRASYSTABLEPREFIXES 1051 -#define DS_ROWVERSIONING 1052 -#define DRV_PARSE 1052 -#define DRV_CANCELASFREESTMT 1053 -#define IDC_OPTIONS 1054 -#define DRV_KSQO 1055 -#define DS_PG64 1057 -#define DS_PG63 1058 -#define DRV_OR_DSN 1059 -#define DRV_DEBUG 1060 -#define DS_DISALLOWPREMATURE 1061 - -/* Next default values for new objects */ -/* */ -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 105 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1062 -#define _APS_NEXT_SYMED_VALUE 101 -#endif /* */ - -#endif /* */ diff --git a/src/interfaces/odbc/windev/results.c b/src/interfaces/odbc/windev/results.c deleted file mode 100644 index 3bc5a5c0e1..0000000000 --- a/src/interfaces/odbc/windev/results.c +++ /dev/null @@ -1,1937 +0,0 @@ -/*------- - * 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. - *------- - */ - -#include "psqlodbc.h" - -#include -#include "dlg_specific.h" -#include "environ.h" -#include "connection.h" -#include "statement.h" -#include "bind.h" -#include "qresult.h" -#include "convert.h" -#include "pgtypes.h" - -#include - -#include "pgapifunc.h" - - - -RETCODE SQL_API -PGAPI_RowCount( - HSTMT hstmt, - SDWORD FAR * pcrow) -{ - static char *func = "PGAPI_RowCount"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - char *msg, - *ptr; - ConnInfo *ci; - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - if (stmt->manual_result) - { - if (pcrow) - *pcrow = -1; - return SQL_SUCCESS; - } - - if (stmt->statement_type == STMT_TYPE_SELECT) - { - if (stmt->status == STMT_FINISHED) - { - res = SC_get_Result(stmt); - - if (res && pcrow) - { - *pcrow = SC_is_fetchcursor(stmt) ? -1 : QR_get_num_tuples(res); - return SQL_SUCCESS; - } - } - } - else - { - res = SC_get_Result(stmt); - if (res && pcrow) - { - msg = QR_get_command(res); - mylog("*** msg = '%s'\n", msg); - trim(msg); /* get rid of trailing spaces */ - ptr = strrchr(msg, ' '); - if (ptr) - { - *pcrow = atoi(ptr + 1); - mylog("**** PGAPI_RowCount(): THE ROWS: *pcrow = %d\n", *pcrow); - } - else - { - *pcrow = -1; - mylog("**** PGAPI_RowCount(): NO ROWS: *pcrow = %d\n", *pcrow); - } - - return SQL_SUCCESS; - } - } - - SC_log_error(func, "Bad return value", stmt); - return SQL_ERROR; -} - - -/* - * This returns the number of columns associated with the database - * attached to "hstmt". - */ -RETCODE SQL_API -PGAPI_NumResultCols( - HSTMT hstmt, - SWORD FAR * pccol) -{ - static char *func = "PGAPI_NumResultCols"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *result; - char parse_ok; - ConnInfo *ci; - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - - SC_clear_error(stmt); - - parse_ok = FALSE; - if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT) - { - if (stmt->parse_status == STMT_PARSE_NONE) - { - mylog("PGAPI_NumResultCols: calling parse_statement on stmt=%u\n", stmt); - parse_statement(stmt); - } - - if (stmt->parse_status != STMT_PARSE_FATAL) - { - parse_ok = TRUE; - *pccol = stmt->nfld; - mylog("PARSE: PGAPI_NumResultCols: *pccol = %d\n", *pccol); - } - } - - if (!parse_ok) - { - SC_pre_execute(stmt); - result = SC_get_Result(stmt); - - mylog("PGAPI_NumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1); - if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) - { - /* no query has been executed on this statement */ - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "No query has been executed with that handle"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - *pccol = QR_NumResultCols(result); - /* updatable cursors */ - if (ci->updatable_cursors && - stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY) - *pccol -= 2; - } - - return SQL_SUCCESS; -} - - -/* - * Return information about the database column the user wants - * information about. - */ -RETCODE SQL_API -PGAPI_DescribeCol( - HSTMT hstmt, - UWORD icol, - UCHAR FAR * szColName, - SWORD cbColNameMax, - SWORD FAR * pcbColName, - SWORD FAR * pfSqlType, - UDWORD FAR * pcbColDef, - SWORD FAR * pibScale, - SWORD FAR * pfNullable) -{ - static char *func = "PGAPI_DescribeCol"; - - /* gets all the information about a specific column */ - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - char *col_name = NULL; - Int4 fieldtype = 0; - int precision = 0, - scale = 0; - ConnInfo *ci; - char parse_ok; - char buf[255]; - int len = 0; - RETCODE result; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - ci = &(SC_get_conn(stmt)->connInfo); - - 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 (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT) - { - if (stmt->parse_status == STMT_PARSE_NONE) - { - mylog("PGAPI_DescribeCol: 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; - stmt->errormsg = "Invalid column number in DescribeCol."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - mylog("DescribeCol: getting info for icol=%d\n", icol); - - fieldtype = stmt->fi[icol]->type; - if (stmt->fi[icol]->alias[0]) - col_name = stmt->fi[icol]->alias; - else - col_name = stmt->fi[icol]->name; - precision = stmt->fi[icol]->precision; - scale = stmt->fi[icol]->scale; - - mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision); - if (fieldtype > 0) - parse_ok = TRUE; - } - } - - /* - * 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) - { - SC_pre_execute(stmt); - - res = SC_get_Result(stmt); - - mylog("**** PGAPI_DescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE); - if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) - { - /* no query has been executed on this statement */ - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "No query has been assigned to this statement."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (icol >= QR_NumResultCols(res)) - { - stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; - stmt->errormsg = "Invalid column number in DescribeCol."; - sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(res)); - SC_log_error(func, buf, stmt); - return SQL_ERROR; - } - - col_name = QR_get_fieldname(res, icol); - fieldtype = QR_get_field_type(res, icol); - - /* atoi(ci->unknown_sizes) */ - precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.unknown_sizes); - scale = pgtype_scale(stmt, fieldtype, icol); - } - - 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) - *pcbColName = len; - - if (szColName) - { - strncpy_null(szColName, col_name, cbColNameMax); - - if (len >= cbColNameMax) - { - result = SQL_SUCCESS_WITH_INFO; - stmt->errornumber = STMT_TRUNCATED; - stmt->errormsg = "The buffer was too small for the colName."; - } - } - - /* - * SQL TYPE - */ - if (pfSqlType) - { - *pfSqlType = pgtype_to_sqltype(stmt, fieldtype); - - mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType); - } - - /* - * PRECISION - */ - if (pcbColDef) - { - if (precision < 0) - precision = 0; /* "I dont know" */ - - *pcbColDef = precision; - - mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef); - } - - /* - * SCALE - */ - if (pibScale) - { - if (scale < 0) - scale = 0; - - *pibScale = scale; - mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale); - } - - /* - * NULLABILITY - */ - if (pfNullable) - { - *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype); - - mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable); - } - - return result; -} - - -/* Returns result column descriptor information for a result set. */ -RETCODE SQL_API -PGAPI_ColAttributes( - HSTMT hstmt, - UWORD icol, - UWORD fDescType, - PTR rgbDesc, - SWORD cbDescMax, - SWORD FAR * pcbDesc, - SDWORD FAR * pfDesc) -{ - static char *func = "PGAPI_ColAttributes"; - StatementClass *stmt = (StatementClass *) hstmt; - Int4 field_type = 0; - ConnInfo *ci; - int unknown_sizes; - int cols = 0; - char parse_ok; - RETCODE result; - char *p = NULL; - int len = 0, - value = 0; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - ci = &(SC_get_conn(stmt)->connInfo); - - /* - * Dont check for bookmark column. This is the responsibility of the - * driver manager. For certain types of arguments, the column number - * is ignored anyway, so it may be 0. - */ - - icol--; - - /* atoi(ci->unknown_sizes); */ - unknown_sizes = ci->drivers.unknown_sizes; - - /* not appropriate for SQLColAttributes() */ - if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) - unknown_sizes = UNKNOWNS_AS_MAX; - - parse_ok = FALSE; - if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT) - { - if (stmt->parse_status == STMT_PARSE_NONE) - { - mylog("PGAPI_ColAttributes: calling parse_statement\n"); - parse_statement(stmt); - } - - cols = stmt->nfld; - - /* - * Column Count is a special case. The Column number is ignored - * in this case. - */ - if (fDescType == SQL_COLUMN_COUNT) - { - if (pfDesc) - *pfDesc = cols; - - return SQL_SUCCESS; - } - - if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) - { - if (icol >= cols) - { - stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; - stmt->errormsg = "Invalid column number in ColAttributes."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - field_type = stmt->fi[icol]->type; - if (field_type > 0) - parse_ok = TRUE; - } - } - - if (!parse_ok) - { - SC_pre_execute(stmt); - - mylog("**** PGAPI_ColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1); - - if ((NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) - { - stmt->errormsg = "Can't get column attributes: no result found."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - cols = QR_NumResultCols(stmt->result); - - /* - * Column Count is a special case. The Column number is ignored - * in this case. - */ - if (fDescType == SQL_COLUMN_COUNT) - { - if (pfDesc) - *pfDesc = cols; - - return SQL_SUCCESS; - } - - if (icol >= cols) - { - stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; - stmt->errormsg = "Invalid column number in ColAttributes."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - field_type = QR_get_field_type(stmt->result, icol); - } - - mylog("colAttr: col %d field_type = %d\n", icol, field_type); - - switch (fDescType) - { - case SQL_COLUMN_AUTO_INCREMENT: - value = pgtype_auto_increment(stmt, field_type); - if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */ - value = FALSE; - - break; - - 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); - - mylog("PGAPI_ColAttributes: col %d, display_size= %d\n", icol, value); - - break; - - case SQL_COLUMN_LABEL: - if (parse_ok && stmt->fi[icol]->alias[0] != '\0') - { - p = stmt->fi[icol]->alias; - - mylog("PGAPI_ColAttr: 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("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p); - break; - - case SQL_COLUMN_LENGTH: - value = (parse_ok) ? stmt->fi[icol]->length : pgtype_length(stmt, field_type, icol, unknown_sizes); - - mylog("PGAPI_ColAttributes: col %d, length = %d\n", icol, value); - break; - - case SQL_COLUMN_MONEY: - value = pgtype_money(stmt, field_type); - break; - - case SQL_COLUMN_NULLABLE: - value = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, field_type); - break; - - case SQL_COLUMN_OWNER_NAME: - p = ""; - break; - - case SQL_COLUMN_PRECISION: - value = (parse_ok) ? stmt->fi[icol]->precision : pgtype_precision(stmt, field_type, icol, unknown_sizes); - - mylog("PGAPI_ColAttributes: col %d, precision = %d\n", icol, value); - break; - - case SQL_COLUMN_QUALIFIER_NAME: - p = ""; - break; - - case SQL_COLUMN_SCALE: - value = pgtype_scale(stmt, field_type, icol); - break; - - case SQL_COLUMN_SEARCHABLE: - value = pgtype_searchable(stmt, field_type); - break; - - case SQL_COLUMN_TABLE_NAME: - p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : ""; - - mylog("PGAPI_ColAttr: TABLE_NAME = '%s'\n", p); - break; - - case SQL_COLUMN_TYPE: - value = pgtype_to_sqltype(stmt, field_type); - break; - - case SQL_COLUMN_TYPE_NAME: - p = pgtype_to_name(stmt, field_type); - break; - - case SQL_COLUMN_UNSIGNED: - value = pgtype_unsigned(stmt, field_type); - if (value == -1) /* non-numeric becomes TRUE (ODBC Doc) */ - value = TRUE; - - 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("PGAPI_ColAttr: UPDATEABLE = %d\n", value); - break; - } - - result = SQL_SUCCESS; - - if (p) - { /* char/binary data */ - len = strlen(p); - - if (rgbDesc) - { - strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax); - - if (len >= cbDescMax) - { - result = SQL_SUCCESS_WITH_INFO; - stmt->errornumber = STMT_TRUNCATED; - stmt->errormsg = "The buffer was too small for the rgbDesc."; - } - } - - if (pcbDesc) - *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 -PGAPI_GetData( - HSTMT hstmt, - UWORD icol, - SWORD fCType, - PTR rgbValue, - SDWORD cbValueMax, - SDWORD FAR * pcbValue) -{ - static char *func = "PGAPI_GetData"; - QResultClass *res; - StatementClass *stmt = (StatementClass *) hstmt; - int num_cols, - num_rows; - Int4 field_type; - void *value = NULL; - int result; - char get_bookmark = FALSE; - ConnInfo *ci; - - mylog("PGAPI_GetData: enter, stmt=%u\n", stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - res = stmt->result; - - if (STMT_EXECUTING == stmt->status) - { - stmt->errormsg = "Can't get data while statement is still executing."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->status != STMT_FINISHED) - { - stmt->errornumber = STMT_STATUS_ERROR; - stmt->errormsg = "GetData can only be called after the successful execution on a SQL statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (icol == 0) - { - if (stmt->options.use_bookmarks == SQL_UB_OFF) - { - stmt->errornumber = STMT_COLNUM_ERROR; - stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* Make sure it is the bookmark data type */ - if (fCType != SQL_C_BOOKMARK) - { - stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK"; - stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - get_bookmark = TRUE; - } - else - { - /* use zero-based column numbers */ - icol--; - - /* make sure the column number is valid */ - num_cols = QR_NumResultCols(res); - if (icol >= num_cols) - { - stmt->errormsg = "Invalid column number."; - stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - - if (stmt->manual_result || !SC_is_fetchcursor(stmt)) - { - /* make sure we're positioned on a valid row */ - num_rows = QR_get_num_tuples(res); - if ((stmt->currTuple < 0) || - (stmt->currTuple >= num_rows)) - { - stmt->errormsg = "Not positioned on a valid row for GetData."; - stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - mylog(" num_rows = %d\n", num_rows); - - if (!get_bookmark) - { - if (stmt->manual_result) - value = QR_get_value_manual(res, stmt->currTuple, icol); - else - value = QR_get_value_backend_row(res, stmt->currTuple, icol); - mylog(" value = '%s'\n", value); - } - } - 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."; - stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (!get_bookmark) - value = QR_get_value_backend(res, icol); - - mylog(" socket: value = '%s'\n", value); - } - - if (get_bookmark) - { - *((UDWORD *) rgbValue) = SC_get_bookmark(stmt); - - if (pcbValue) - *pcbValue = 4; - - return SQL_SUCCESS; - } - - field_type = QR_get_field_type(res, icol); - - mylog("**** PGAPI_GetData: icol = %d, fCType = %d, field_type = %d, value = '%s'\n", icol, fCType, field_type, value); - - stmt->current_col = icol; - - result = copy_and_convert_field(stmt, field_type, value, - fCType, rgbValue, cbValueMax, pcbValue); - - stmt->current_col = -1; - - switch (result) - { - case COPY_OK: - return SQL_SUCCESS; - - case COPY_UNSUPPORTED_TYPE: - stmt->errormsg = "Received an unsupported type from Postgres."; - stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - - case COPY_UNSUPPORTED_CONVERSION: - stmt->errormsg = "Couldn't handle the necessary data type conversion."; - stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - - case COPY_RESULT_TRUNCATED: - stmt->errornumber = STMT_TRUNCATED; - stmt->errormsg = "The buffer was too small for the GetData."; - return SQL_SUCCESS_WITH_INFO; - - case COPY_GENERAL_ERROR: /* error msg already filled in */ - SC_log_error(func, "", stmt); - return SQL_ERROR; - - case COPY_NO_DATA_FOUND: - /* SC_log_error(func, "no data found", stmt); */ - return SQL_NO_DATA_FOUND; - - default: - stmt->errormsg = "Unrecognized return value from copy_and_convert_field."; - stmt->errornumber = STMT_INTERNAL_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } -} - - -/* - * Returns data for bound columns in the current row ("hstmt->iCursor"), - * advances the cursor. - */ -RETCODE SQL_API -PGAPI_Fetch( - HSTMT hstmt) -{ - static char *func = "PGAPI_Fetch"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - - mylog("PGAPI_Fetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - SC_clear_error(stmt); - - if (!(res = stmt->result)) - { - stmt->errormsg = "Null statement result in PGAPI_Fetch."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* Not allowed to bind a bookmark column when using SQLFetch. */ - if (stmt->bookmark.buffer) - { - stmt->errornumber = STMT_COLNUM_ERROR; - stmt->errormsg = "Not allowed to bind a bookmark column when using PGAPI_Fetch"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->status == STMT_EXECUTING) - { - stmt->errormsg = "Can't fetch while statement is still executing."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->status != STMT_FINISHED) - { - stmt->errornumber = STMT_STATUS_ERROR; - stmt->errormsg = "Fetch can only be called after the successful execution on a SQL statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->bindings == NULL) - { - /* just to avoid a crash if the user insists on calling this */ - /* function even if SQL_ExecDirect has reported an Error */ - stmt->errormsg = "Bindings were not allocated properly."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - QR_set_rowset_size(res, 1); - QR_inc_base(res, stmt->last_fetch_count); - - return SC_fetch(stmt); -} - - -/* This fetchs a block of data (rowset). */ -RETCODE SQL_API -PGAPI_ExtendedFetch( - HSTMT hstmt, - UWORD fFetchType, - SDWORD irow, - UDWORD FAR * pcrow, - UWORD FAR * rgfRowStatus) -{ - static char *func = "PGAPI_ExtendedFetch"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - int num_tuples, - i, - save_rowset_size; - RETCODE result; - char truncated, - error; - ConnInfo *ci; - - mylog("PGAPI_ExtendedFetch: stmt=%u\n", stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - - if (SC_is_fetchcursor(stmt) && !stmt->manual_result) - { - if (fFetchType != SQL_FETCH_NEXT) - { - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Unsupported fetch type for PGAPI_ExtendedFetch with UseDeclareFetch option."; - return SQL_ERROR; - } - } - - SC_clear_error(stmt); - - if (!(res = stmt->result)) - { - stmt->errormsg = "Null statement result in PGAPI_ExtendedFetch."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* - * If a bookmark colunmn is bound but bookmark usage is off, then - * error - */ - if (stmt->bookmark.buffer && stmt->options.use_bookmarks == SQL_UB_OFF) - { - stmt->errornumber = STMT_COLNUM_ERROR; - stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->status == STMT_EXECUTING) - { - stmt->errormsg = "Can't fetch while statement is still executing."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->status != STMT_FINISHED) - { - stmt->errornumber = STMT_STATUS_ERROR; - stmt->errormsg = "ExtendedFetch can only be called after the successful execution on a SQL statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->bindings == NULL) - { - /* just to avoid a crash if the user insists on calling this */ - /* function even if SQL_ExecDirect has reported an Error */ - stmt->errormsg = "Bindings were not allocated properly."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* Initialize to no rows fetched */ - if (rgfRowStatus) - for (i = 0; i < stmt->options.rowset_size; i++) - *(rgfRowStatus + i) = SQL_ROW_NOROW; - - if (pcrow) - *pcrow = 0; - - num_tuples = QR_get_num_tuples(res); - - /* Save and discard the saved rowset size */ - save_rowset_size = stmt->save_rowset_size; - stmt->save_rowset_size = -1; - - 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 - * SQL_FETCH_FIRST. - */ - - if (stmt->rowset_start < 0) - 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) - { - if (stmt->options.rowset_size > num_tuples) - { - stmt->errornumber = STMT_POS_BEFORE_RECORDSET; - stmt->errormsg = "fetch prior from eof and before the beggining"; - } - stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size); - - } - else - { - if (stmt->rowset_start < stmt->options.rowset_size) - { - stmt->errormsg = "fetch prior and before the beggining"; - stmt->errornumber = STMT_POS_BEFORE_RECORDSET; - } - stmt->rowset_start -= stmt->options.rowset_size; - } - break; - - case SQL_FETCH_FIRST: - mylog("SQL_FETCH_FIRST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); - - stmt->rowset_start = 0; - break; - - case SQL_FETCH_LAST: - mylog("SQL_FETCH_LAST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); - - stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size); - break; - - case SQL_FETCH_ABSOLUTE: - mylog("SQL_FETCH_ABSOLUTE: num_tuples=%d, currtuple=%d, irow=%d\n", num_tuples, stmt->currTuple, irow); - - /* Position before result set, but dont fetch anything */ - if (irow == 0) - { - stmt->rowset_start = -1; - stmt->currTuple = -1; - return SQL_NO_DATA_FOUND; - } - /* Position before the desired row */ - else if (irow > 0) - stmt->rowset_start = irow - 1; - /* 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 - */ - if (irow == 0) - break; - - stmt->rowset_start += irow; - break; - - case SQL_FETCH_BOOKMARK: - stmt->rowset_start = irow - 1; - break; - - default: - SC_log_error(func, "Unsupported PGAPI_ExtendedFetch Direction", stmt); - return SQL_ERROR; - } - - /* - * CHECK FOR PROPER CURSOR STATE - */ - - /* - * Handle Declare Fetch style specially because the end is not really - * the end... - */ - if (SC_is_fetchcursor(stmt) && !stmt->manual_result) - { - if (QR_end_tuples(res)) - return SQL_NO_DATA_FOUND; - } - else - { - /* If *new* rowset is after the result_set, return no data found */ - if (stmt->rowset_start >= num_tuples) - { - stmt->rowset_start = num_tuples; - return SQL_NO_DATA_FOUND; - } - } - - /* If *new* rowset is prior to result_set, return no data found */ - if (stmt->rowset_start < 0) - { - if (stmt->rowset_start + stmt->options.rowset_size <= 0) - { - stmt->rowset_start = -1; - return SQL_NO_DATA_FOUND; - } - else - { /* overlap with beginning of result set, - * so get first rowset */ - stmt->rowset_start = 0; - } - } - - /* currTuple is always 1 row prior to the rowset */ - stmt->currTuple = stmt->rowset_start - 1; - - /* increment the base row in the tuple cache */ - QR_set_rowset_size(res, stmt->options.rowset_size); - /* QR_inc_base(res, stmt->last_fetch_count); */ - /* Is inc_base right ? */ - res->base = stmt->rowset_start; - - /* Physical Row advancement occurs for each row fetched below */ - - mylog("PGAPI_ExtendedFetch: new currTuple = %d\n", stmt->currTuple); - - truncated = error = FALSE; - for (i = 0; i < stmt->options.rowset_size; i++) - { - stmt->bind_row = i; /* set the binding location */ - result = SC_fetch(stmt); - - /* Determine Function status */ - if (result == SQL_NO_DATA_FOUND) - break; - else if (result == SQL_SUCCESS_WITH_INFO) - truncated = TRUE; - else if (result == SQL_ERROR) - error = TRUE; - - /* Determine Row Status */ - if (rgfRowStatus) - { - if (result == SQL_ERROR) - *(rgfRowStatus + i) = SQL_ROW_ERROR; -#ifdef DRIVER_CURSOR_IMPLEMENT - /* this should be refined */ - else if (result > 10 && result < 20) - *(rgfRowStatus + i) = result - 10; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - else - *(rgfRowStatus + i) = SQL_ROW_SUCCESS; - } - } - - /* Save the fetch count for SQLSetPos */ - stmt->last_fetch_count = i; - - /* Reset next binding row */ - stmt->bind_row = 0; - - /* Move the cursor position to the first row in the result set. */ - stmt->currTuple = stmt->rowset_start; - - /* For declare/fetch, need to reset cursor to beginning of rowset */ - if (SC_is_fetchcursor(stmt) && !stmt->manual_result) - QR_set_position(res, 0); - - /* Set the number of rows retrieved */ - if (pcrow) - *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 if (stmt->errornumber == STMT_POS_BEFORE_RECORDSET) - 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 -PGAPI_MoreResults( - HSTMT hstmt) -{ - return SQL_NO_DATA_FOUND; -} - - -#ifdef DRIVER_CURSOR_IMPLEMENT -/* - * Stuff for updatable cursors. - */ -static QResultClass * -positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, const char *tidval) -{ - int i; - QResultClass *qres; - char selstr[4096]; - - sprintf(selstr, "select"); - for (i = 0; i < res_cols; i++) - sprintf(selstr, "%s \"%s\",", selstr, stmt->fi[i]->name); - sprintf(selstr, "%s CTID, OID from \"%s\" where", selstr, stmt->ti[0]->name); - if (tidval) - { - if (latest) - sprintf(selstr, "%s ctid = currtid2('%s', '%s') and", - selstr, stmt->ti[0]->name, tidval); - else - sprintf(selstr, "%s ctid = '%s' and", selstr, tidval); - } - sprintf(selstr, "%s oid = %u", selstr, oid), - mylog("selstr=%s\n", selstr); - qres = CC_send_query(SC_get_conn(stmt), selstr, NULL); - if (qres && QR_aborted(qres)) - { - QR_Destructor(qres); - qres = (QResultClass *) 0; - } - return qres; -} - -RETCODE SQL_API -SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count) -{ - int i, - res_cols; - UWORD rcnt, - global_ridx; - UInt4 oid; - QResultClass *res, - *qres; - RETCODE ret = SQL_ERROR; - char *tidval, - *oidval; - - mylog("positioned load fi=%x ti=%x\n", stmt->fi, stmt->ti); - rcnt = 0; - if (count) - *count = 0; - if (!(res = stmt->result)) - return SQL_ERROR; - if (!stmt->ti) - parse_statement(stmt); /* not preferable */ - if (!stmt->ti || stmt->ntab != 1) - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - return SQL_ERROR; - } - global_ridx = irow + stmt->rowset_start; - res_cols = QR_NumResultCols(res); - if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1))) - return SQL_SUCCESS_WITH_INFO; - sscanf(oidval, "%u", &oid); - tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2); - res_cols -= 2; - if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres) - { - TupleField *tupleo, - *tuplen; - - rcnt = QR_get_num_tuples(qres); - tupleo = res->backend_tuples + res->num_fields * global_ridx; - if (rcnt == 1) - { - QR_set_position(qres, 0); - tuplen = res->tupleField; - for (i = 0; i < res->num_fields; i++) - { - if (tupleo[i].value) - free(tupleo[i].value); - tupleo[i].len = tuplen[i].len; - tuplen[i].len = 0; - tupleo[i].value = tuplen[i].value; - tuplen[i].value = NULL; - } - ret = SQL_SUCCESS; - } - else - { - stmt->errornumber = STMT_ROW_VERSION_CHANGED; - stmt->errormsg = "the content was deleted after last fetch"; - ret = SQL_SUCCESS_WITH_INFO; - if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN) - { - if (tupleo[res_cols + 1].value) - free(tupleo[res_cols + 1].value); - tupleo[res_cols + 1].value = NULL; - tupleo[res_cols + 1].len = 0; - } - } - QR_Destructor(qres); - } - else if (stmt->errornumber == 0) - stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND; - if (count) - *count = rcnt; - return ret; -} - -RETCODE SQL_API -SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval) -{ - int i; - QResultClass *res, - *qres; - RETCODE ret = SQL_ERROR; - - mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti); - if (!(res = stmt->result)) - return SQL_ERROR; - if (!stmt->ti) - parse_statement(stmt); /* not preferable */ - if (!stmt->ti || stmt->ntab != 1) - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - return SQL_ERROR; - } - if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres) - { - TupleField *tupleo, - *tuplen; - int count = QR_get_num_tuples(qres); - - QR_set_position(qres, 0); - if (count == 1) - { - tuplen = qres->tupleField; - if (res->fcount >= res->count_allocated) - { - int tuple_size; - - if (!res->count_allocated) - tuple_size = TUPLE_MALLOC_INC; - else - tuple_size = res->count_allocated * 2; - res->backend_tuples = (TupleField *) realloc( - res->backend_tuples, - res->num_fields * sizeof(TupleField) * tuple_size); - if (!res->backend_tuples) - { - stmt->errornumber = res->status = PGRES_FATAL_ERROR; - stmt->errormsg = "Out of memory while reading tuples."; - QR_Destructor(qres); - return SQL_ERROR; - } - res->count_allocated = tuple_size; - } - tupleo = res->backend_tuples + res->num_fields * res->fcount; - for (i = 0; i < res->num_fields; i++) - { - tupleo[i].len = tuplen[i].len; - tuplen[i].len = 0; - tupleo[i].value = tuplen[i].value; - tuplen[i].value = NULL; - } - res->fcount++; - ret = SQL_SUCCESS; - } - else - { - stmt->errornumber = STMT_ROW_VERSION_CHANGED; - stmt->errormsg = "the content was changed before updation"; - ret = SQL_SUCCESS_WITH_INFO; - } - QR_Destructor(qres); - /* stmt->currTuple = stmt->rowset_start + irow; */ - } - return ret; -} - -RETCODE SQL_API -SC_pos_update(StatementClass *stmt, - UWORD irow) -{ - int i, - res_cols, - num_cols, - upd_cols; - UWORD global_ridx; - QResultClass *res; - BindInfoClass *bindings = stmt->bindings; - char updstr[4096]; - RETCODE ret; - char *tidval, - *oidval; - - mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, stmt->result->base, stmt->fi, stmt->ti); - if (!(res = stmt->result)) - return SQL_ERROR; - if (!stmt->ti) - parse_statement(stmt); /* not preferable */ - if (!stmt->ti || stmt->ntab != 1) - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - return SQL_ERROR; - } - global_ridx = irow + stmt->rowset_start; - res_cols = QR_NumResultCols(res); - if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1))) - { - stmt->errormsg = "The row is already deleted"; - return SQL_ERROR; - } - tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2); - - sprintf(updstr, "update \"%s\" set", stmt->ti[0]->name); - num_cols = stmt->nfld; - for (i = upd_cols = 0; i < num_cols; i++) - { - if (bindings[i].used) - { - mylog("%d used=%d\n", i, *bindings[i].used); - if (*bindings[i].used != SQL_IGNORE) - { - if (upd_cols) - sprintf(updstr, "%s, \"%s\" = ?", updstr, stmt->fi[i]->name); - else - sprintf(updstr, "%s \"%s\" = ?", updstr, stmt->fi[i]->name); - upd_cols++; - } - } - else - mylog("%d null bind\n", i); - } - if (upd_cols > 0) - { - HSTMT hstmt; - int j; - int res_cols = QR_NumResultCols(res); - StatementClass *qstmt; - - sprintf(updstr, "%s where ctid = '%s' and oid = %s", updstr, - tidval, oidval); - mylog("updstr=%s\n", updstr); - if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS) - return SQL_ERROR; - qstmt = (StatementClass *) hstmt; - for (i = j = 0; i < num_cols; i++) - { - if (bindings[i].used) - { - mylog("%d used=%d\n", i, *bindings[i].used); - if (*bindings[i].used != SQL_IGNORE) - { - PGAPI_BindParameter(hstmt, (SQLUSMALLINT) ++j, - SQL_PARAM_INPUT, bindings[i].returntype, - pgtype_to_sqltype(stmt, QR_get_field_type(res, i)), - QR_get_fieldsize(res, i), - (SQLSMALLINT) stmt->fi[i]->precision, - bindings[i].buffer, - bindings[i].buflen, - bindings[i].used); - } - } - } - ret = PGAPI_ExecDirect(hstmt, updstr, strlen(updstr)); - if (ret == SQL_ERROR) - { - stmt->errornumber = qstmt->errornumber; - stmt->errormsg = qstmt->errormsg; - } - else if (ret == SQL_NEED_DATA) /* must be fixed */ - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; - stmt->errormsg = "SetPos with data_at_exec not yet supported"; - ret = SQL_ERROR; - } - if (ret != SQL_ERROR) - { - int updcnt; - const char *cmdstr = QR_get_command(qstmt->result); - - if (cmdstr && - sscanf(cmdstr, "UPDATE %d", &updcnt) == 1) - { - if (updcnt == 1) - SC_pos_reload(stmt, irow, (UWORD *) 0); - else if (updcnt == 0) - { - stmt->errornumber = STMT_ROW_VERSION_CHANGED; - stmt->errormsg = "the content was changed before updation"; - ret = SQL_ERROR; - if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN) - SC_pos_reload(stmt, irow, (UWORD *) 0); - } - else - ret = SQL_ERROR; - stmt->currTuple = stmt->rowset_start + irow; - } - else - ret = SQL_ERROR; - if (ret == SQL_ERROR && stmt->errornumber == 0) - { - stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND; - stmt->errormsg = "SetPos update return error"; - } - } - PGAPI_FreeStmt(hstmt, SQL_DROP); - } - else - ret = SQL_SUCCESS_WITH_INFO; - return ret; -} -RETCODE SQL_API -SC_pos_delete(StatementClass *stmt, - UWORD irow) -{ - int res_cols; - UWORD global_ridx; - QResultClass *res, - *qres; - BindInfoClass *bindings = stmt->bindings; - char dltstr[4096]; - RETCODE ret; - char *oidval; - - mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti); - if (!(res = stmt->result)) - return SQL_ERROR; - if (!stmt->ti) - parse_statement(stmt); /* not preferable */ - if (!stmt->ti || stmt->ntab != 1) - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - return SQL_ERROR; - } - res_cols = QR_NumResultCols(res); - global_ridx = irow + stmt->rowset_start; - if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1))) - { - stmt->errormsg = "The row is already deleted"; - return SQL_ERROR; - } - sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s", - stmt->ti[0]->name, - QR_get_value_backend_row(stmt->result, global_ridx, res_cols - 2), - oidval); - - mylog("dltstr=%s\n", dltstr); - qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL); - if (qres && QR_command_successful(qres)) - { - int dltcnt; - const char *cmdstr = QR_get_command(qres); - - if (cmdstr && - sscanf(cmdstr, "DELETE %d", &dltcnt) == 1) - { - if (dltcnt == 1) - SC_pos_reload(stmt, irow, (UWORD *) 0); - else if (dltcnt == 0) - { - stmt->errornumber = STMT_ROW_VERSION_CHANGED; - stmt->errormsg = "the content was changed before deletion"; - ret = SQL_ERROR; - if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN) - SC_pos_reload(stmt, irow, (UWORD *) 0); - } - else - ret = SQL_ERROR; - stmt->currTuple = stmt->rowset_start + irow; - } - else - ret = SQL_ERROR; - } - else - ret = SQL_ERROR; - if (ret == SQL_ERROR && stmt->errornumber == 0) - { - stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND; - stmt->errormsg = "SetPos delete return error"; - } - if (qres) - QR_Destructor(qres); - return ret; -} -RETCODE SQL_API -SC_pos_add(StatementClass *stmt, - UWORD irow) -{ - int num_cols, - add_cols, - i; - HSTMT hstmt; - QResultClass *res; - BindInfoClass *bindings = stmt->bindings; - char addstr[4096]; - RETCODE ret; - - mylog("POS ADD fi=%x ti=%x\n", stmt->fi, stmt->ti); - if (!(res = stmt->result)) - return SQL_ERROR; - if (!stmt->ti) - parse_statement(stmt); /* not preferable */ - if (!stmt->ti || stmt->ntab != 1) - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - return SQL_ERROR; - } - num_cols = stmt->nfld; - sprintf(addstr, "insert into \"%s\" (", stmt->ti[0]->name); - if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS) - return SQL_ERROR; - for (i = add_cols = 0; i < num_cols; i++) - { - if (bindings[i].used) - { - mylog("%d used=%d\n", i, *bindings[i].used); - if (*bindings[i].used != SQL_IGNORE) - { - if (add_cols) - sprintf(addstr, "%s, \"%s\"", addstr, stmt->fi[i]->name); - else - sprintf(addstr, "%s\"%s\"", addstr, stmt->fi[i]->name); - PGAPI_BindParameter(hstmt, (SQLUSMALLINT) ++add_cols, - SQL_PARAM_INPUT, bindings[i].returntype, - pgtype_to_sqltype(stmt, QR_get_field_type(res, i)), - QR_get_fieldsize(res, i), - (SQLSMALLINT) stmt->fi[i]->precision, - bindings[i].buffer, - bindings[i].buflen, - bindings[i].used); - } - } - else - mylog("%d null bind\n", i); - } - if (add_cols > 0) - { - StatementClass *qstmt = (StatementClass *) hstmt; - - sprintf(addstr, "%s) values (", addstr); - for (i = 0; i < add_cols; i++) - { - if (i) - strcat(addstr, ", ?"); - else - strcat(addstr, "?"); - } - strcat(addstr, ")"); - mylog("addstr=%s\n", addstr); - ret = PGAPI_ExecDirect(hstmt, addstr, strlen(addstr)); - if (ret == SQL_NEED_DATA) /* must be fixed */ - { - stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY; - stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; - stmt->errormsg = "SetPos with data_at_exec not yet supported"; - ret = SQL_ERROR; - } - if (ret == SQL_ERROR) - { - stmt->errornumber = qstmt->errornumber; - stmt->errormsg = qstmt->errormsg; - } - else - { - int addcnt; - UInt4 oid; - const char *cmdstr = QR_get_command(qstmt->result); - - if (cmdstr && - sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 && - addcnt == 1) - { - SC_pos_newload(stmt, oid, NULL); - if (stmt->bookmark.buffer) - { - char buf[32]; - - sprintf(buf, "%ld", res->fcount); - copy_and_convert_field(stmt, 0, buf, - SQL_C_ULONG, stmt->bookmark.buffer, - 0, stmt->bookmark.used); - } - } - else - { - stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND; - stmt->errormsg = "SetPos insert return error"; - ret = SQL_ERROR; - } - } - } - else - ret = SQL_SUCCESS_WITH_INFO; - PGAPI_FreeStmt(hstmt, SQL_DROP); - return ret; -} - -/* - * Stuff for updatable cursors end. - */ -#endif /* DRIVER_CURSOR_IMPLEMENT */ - -/* - * 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 -PGAPI_SetPos( - HSTMT hstmt, - UWORD irow, - UWORD fOption, - UWORD fLock) -{ - static char *func = "PGAPI_SetPos"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - int num_cols, - i; - BindInfoClass *bindings = stmt->bindings; - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - -#ifdef DRIVER_CURSOR_IMPLEMENT - mylog("SetPos fOption=%d irow=%d lock=%d currt=%d\n", fOption, irow, fLock, stmt->currTuple); - if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY) - ; - else -#endif /* DRIVER_CURSOR_IMPLEMENT */ - if (fOption != SQL_POSITION && fOption != SQL_REFRESH) - { - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Only SQL_POSITION/REFRESH is supported for PGAPI_SetPos"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (!(res = stmt->result)) - { - stmt->errormsg = "Null statement result in PGAPI_SetPos."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - num_cols = QR_NumResultCols(res); - - if (irow == 0) - { - stmt->errornumber = STMT_ROW_OUT_OF_RANGE; - stmt->errormsg = "Driver does not support Bulk operations."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (irow > stmt->last_fetch_count) - { - stmt->errornumber = STMT_ROW_OUT_OF_RANGE; - stmt->errormsg = "Row value out of range"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - irow--; - -#ifdef DRIVER_CURSOR_IMPLEMENT - switch (fOption) - { - case SQL_UPDATE: - return SC_pos_update(stmt, irow); - case SQL_DELETE: - return SC_pos_delete(stmt, irow); - case SQL_ADD: - return SC_pos_add(stmt, irow); - } -#endif /* DRIVER_CURSOR_IMPLEMENT */ - /* Reset for SQLGetData */ - for (i = 0; i < num_cols; i++) - bindings[i].data_left = -1; - - if (fOption == SQL_REFRESH) - { - /* save the last_fetch_count */ - int last_fetch = stmt->last_fetch_count; - int bind_save = stmt->bind_row; - -#ifdef DRIVER_CURSOR_IMPLEMENT - if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN) - SC_pos_reload(stmt, irow, (UWORD *) 0); -#endif /* DRIVER_CURSOR_IMPLEMENT */ - stmt->currTuple = stmt->rowset_start + irow - 1; - stmt->bind_row = irow; - SC_fetch(stmt); - /* restore the last_fetch_count */ - stmt->last_fetch_count = last_fetch; - stmt->bind_row = bind_save; - } - else - stmt->currTuple = stmt->rowset_start + irow; - QR_set_position(res, irow); - - return SQL_SUCCESS; -} - - -/* Sets options that control the behavior of cursors. */ -RETCODE SQL_API -PGAPI_SetScrollOptions( - HSTMT hstmt, - UWORD fConcurrency, - SDWORD crowKeyset, - UWORD crowRowset) -{ - static char *func = "PGAPI_SetScrollOptions"; - StatementClass *stmt = (StatementClass *) hstmt; - - mylog("PGAPI_SetScrollOptions fConcurrency=%d crowKeyset=%d crowRowset=%d\n", - fConcurrency, crowKeyset, crowRowset); - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "SetScroll option not implemeted"; - - SC_log_error(func, "Function not implemented", hstmt); - return SQL_ERROR; -} - - -/* Set the cursor name on a statement handle */ -RETCODE SQL_API -PGAPI_SetCursorName( - HSTMT hstmt, - UCHAR FAR * szCursor, - SWORD cbCursor) -{ - static char *func = "PGAPI_SetCursorName"; - StatementClass *stmt = (StatementClass *) hstmt; - int len; - - mylog("PGAPI_SetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n", hstmt, szCursor, cbCursor); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor; - - if (len <= 0 || len > sizeof(stmt->cursor_name) - 1) - { - stmt->errornumber = STMT_INVALID_CURSOR_NAME; - stmt->errormsg = "Invalid Cursor Name"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - strncpy_null(stmt->cursor_name, szCursor, len + 1); - return SQL_SUCCESS; -} - - -/* Return the cursor name for a statement handle */ -RETCODE SQL_API -PGAPI_GetCursorName( - HSTMT hstmt, - UCHAR FAR * szCursor, - SWORD cbCursorMax, - SWORD FAR * pcbCursor) -{ - static char *func = "PGAPI_GetCursorName"; - StatementClass *stmt = (StatementClass *) hstmt; - int len = 0; - RETCODE result; - - mylog("PGAPI_GetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - if (stmt->cursor_name[0] == '\0') - { - stmt->errornumber = STMT_NO_CURSOR_NAME; - stmt->errormsg = "No Cursor name available"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - result = SQL_SUCCESS; - len = strlen(stmt->cursor_name); - - if (szCursor) - { - strncpy_null(szCursor, stmt->cursor_name, cbCursorMax); - - if (len >= cbCursorMax) - { - result = SQL_SUCCESS_WITH_INFO; - stmt->errornumber = STMT_TRUNCATED; - stmt->errormsg = "The buffer was too small for the GetCursorName."; - } - } - - if (pcbCursor) - *pcbCursor = len; - - return result; -} diff --git a/src/interfaces/odbc/windev/setup.c b/src/interfaces/odbc/windev/setup.c deleted file mode 100644 index 6bcc01bd89..0000000000 --- a/src/interfaces/odbc/windev/setup.c +++ /dev/null @@ -1,425 +0,0 @@ -/*------- - * Module: setup.c - * - * Description: This module contains the setup functions for - * adding/modifying a Data Source in the ODBC.INI portion - * of the registry. - * - * Classes: n/a - * - * API functions: ConfigDSN - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "psqlodbc.h" - -#include "connection.h" -#include -#include -#include -#include "resource.h" -#include "dlg_specific.h" - - -#define INTFUNC __stdcall - -extern HINSTANCE NEAR s_hModule; /* Saved module handle. */ - -/* Constants */ -#define MIN(x,y) ((x) < (y) ? (x) : (y)) - -#ifdef WIN32 -#define MAXPGPATH (255+1) -#endif - -#define MAXKEYLEN (15+1) /* Max keyword length */ -#define MAXDESC (255+1) /* Max description length */ -#define MAXDSNAME (32+1) /* Max data source name length */ - - -/* Globals */ -/* NOTE: All these are used by the dialog procedures */ -typedef struct tagSETUPDLG -{ - HWND hwndParent; /* Parent window handle */ - LPCSTR lpszDrvr; /* Driver description */ - ConnInfo ci; - char szDSN[MAXDSNAME]; /* Original data source name */ - BOOL fNewDSN; /* New data source flag */ - BOOL fDefault; /* Default data source flag */ - -} SETUPDLG, FAR * LPSETUPDLG; - - - -/* 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, - WORD fRequest, - LPCSTR lpszDriver, - LPCSTR lpszAttributes) -{ - BOOL fSuccess; /* Success/fail flag */ - GLOBALHANDLE hglbAttr; - LPSETUPDLG lpsetupdlg; - - - /* Allocate attribute array */ - hglbAttr = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(SETUPDLG)); - if (!hglbAttr) - return FALSE; - lpsetupdlg = (LPSETUPDLG) GlobalLock(hglbAttr); - - /* Parse attribute string */ - if (lpszAttributes) - ParseAttributes(lpszAttributes, lpsetupdlg); - - /* Save original data source name */ - if (lpsetupdlg->ci.dsn[0]) - lstrcpy(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn); - else - lpsetupdlg->szDSN[0] = '\0'; - - /* Remove data source */ - if (ODBC_REMOVE_DSN == fRequest) - { - /* Fail if no data source name was supplied */ - if (!lpsetupdlg->ci.dsn[0]) - fSuccess = FALSE; - - /* Otherwise remove data source from ODBC.INI */ - else - fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn); - } - /* Add or Configure data source */ - else - { - /* Save passed variables for global access (e.g., dialog access) */ - lpsetupdlg->hwndParent = hwnd; - lpsetupdlg->lpszDrvr = lpszDriver; - lpsetupdlg->fNewDSN = (ODBC_ADD_DSN == fRequest); - lpsetupdlg->fDefault = !lstrcmpi(lpsetupdlg->ci.dsn, INI_DSN); - - /* - * Display the appropriate dialog (if parent window handle - * supplied) - */ - if (hwnd) - { - /* Display dialog(s) */ - fSuccess = (IDOK == DialogBoxParam(s_hModule, - MAKEINTRESOURCE(DLG_CONFIG), - hwnd, - ConfigDlgProc, - (LONG) (LPSTR) lpsetupdlg)); - } - else if (lpsetupdlg->ci.dsn[0]) - fSuccess = SetDSNAttributes(hwnd, lpsetupdlg); - else - fSuccess = FALSE; - } - - GlobalUnlock(hglbAttr); - GlobalFree(hglbAttr); - - return fSuccess; -} - - -/*------- - * CenterDialog - * - * Description: Center the dialog over the frame window - * Input : hdlg -- Dialog window handle - * Output : None - *------- - */ -void INTFUNC -CenterDialog(HWND hdlg) -{ - HWND hwndFrame; - RECT rcDlg, - rcScr, - rcFrame; - int cx, - cy; - - hwndFrame = GetParent(hdlg); - - GetWindowRect(hdlg, &rcDlg); - cx = rcDlg.right - rcDlg.left; - cy = rcDlg.bottom - rcDlg.top; - - GetClientRect(hwndFrame, &rcFrame); - ClientToScreen(hwndFrame, (LPPOINT) (&rcFrame.left)); - ClientToScreen(hwndFrame, (LPPOINT) (&rcFrame.right)); - rcDlg.top = rcFrame.top + (((rcFrame.bottom - rcFrame.top) - cy) >> 1); - rcDlg.left = rcFrame.left + (((rcFrame.right - rcFrame.left) - cx) >> 1); - rcDlg.bottom = rcDlg.top + cy; - rcDlg.right = rcDlg.left + cx; - - GetWindowRect(GetDesktopWindow(), &rcScr); - if (rcDlg.bottom > rcScr.bottom) - { - rcDlg.bottom = rcScr.bottom; - rcDlg.top = rcDlg.bottom - cy; - } - if (rcDlg.right > rcScr.right) - { - rcDlg.right = rcScr.right; - rcDlg.left = rcDlg.right - cx; - } - - if (rcDlg.left < 0) - rcDlg.left = 0; - if (rcDlg.top < 0) - rcDlg.top = 0; - - 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) -{ - LPSETUPDLG lpsetupdlg; - ConnInfo *ci; - - switch (wMsg) - { - /* Initialize the dialog */ - case WM_INITDIALOG: - lpsetupdlg = (LPSETUPDLG) lParam; - ci = &lpsetupdlg->ci; - - /* Hide the driver connect message */ - ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL), SW_HIDE); - - SetWindowLong(hdlg, DWL_USER, lParam); - CenterDialog(hdlg); /* Center dialog */ - - /* - * NOTE: Values supplied in the attribute string will always - */ - /* override settings in ODBC.INI */ - - /* Get the rest of the common attributes */ - getDSNinfo(ci, CONN_DONT_OVERWRITE); - - /* Fill in any defaults */ - getDSNdefaults(ci); - - /* Initialize dialog fields */ - SetDlgStuff(hdlg, ci); - - if (lpsetupdlg->fDefault) - { - EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE); - EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE); - } - else - SendDlgItemMessage(hdlg, IDC_DSNAME, - EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L); - - SendDlgItemMessage(hdlg, IDC_DESC, - EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); - return TRUE; /* Focus was not set */ - - /* Process buttons */ - case WM_COMMAND: - switch (GET_WM_COMMAND_ID(wParam, lParam)) - { - /* - * Ensure the OK button is enabled only when a data - * source name - */ - /* is entered */ - case IDC_DSNAME: - if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) - { - char szItem[MAXDSNAME]; /* Edit control text */ - - /* Enable/disable the OK button */ - EnableWindow(GetDlgItem(hdlg, IDOK), - GetDlgItemText(hdlg, IDC_DSNAME, - szItem, sizeof(szItem))); - return TRUE; - } - break; - - /* Accept results */ - case IDOK: - lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); - /* Retrieve dialog values */ - if (!lpsetupdlg->fDefault) - GetDlgItemText(hdlg, IDC_DSNAME, - lpsetupdlg->ci.dsn, - sizeof(lpsetupdlg->ci.dsn)); - /* Get Dialog Values */ - GetDlgStuff(hdlg, &lpsetupdlg->ci); - - /* Update ODBC.INI */ - SetDSNAttributes(hdlg, lpsetupdlg); - - /* Return to caller */ - case IDCANCEL: - EndDialog(hdlg, wParam); - return TRUE; - - case IDC_DRIVER: - lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), - hdlg, driver_optionsProc, (LPARAM) &lpsetupdlg->ci); - return TRUE; - - case IDC_DATASOURCE: - lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER); - - DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS), - hdlg, ds_optionsProc, (LPARAM) &lpsetupdlg->ci); - - return TRUE; - } - break; - } - - /* Message not processed */ - return FALSE; -} - - -/*------- - * 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) -{ - LPCSTR lpsz; - LPCSTR lpszStart; - char aszKey[MAXKEYLEN]; - int cbKey; - char value[MAXPGPATH]; - - 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++) - { - if (!*lpsz) - return; /* No key was found */ - else if (*lpsz == '=') - break; /* Valid key found */ - } - /* Determine the key's index in the key table (-1 if not found) */ - 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)); - - mylog("aszKey='%s', value='%s'\n", aszKey, value); - - /* Copy the appropriate value to the conninfo */ - copyAttributes(&lpsetupdlg->ci, aszKey, value); - } - return; -} - - -/*-------- - * 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) -{ - LPCSTR lpszDSN; /* Pointer to data source name */ - - lpszDSN = lpsetupdlg->ci.dsn; - - /* Validate arguments */ - if (lpsetupdlg->fNewDSN && !*lpsetupdlg->ci.dsn) - return FALSE; - - /* Write the data source name */ - if (!SQLWriteDSNToIni(lpszDSN, lpsetupdlg->lpszDrvr)) - { - if (hwndParent) - { - char szBuf[MAXPGPATH]; - char szMsg[MAXPGPATH]; - - LoadString(s_hModule, IDS_BADDSN, szBuf, sizeof(szBuf)); - wsprintf(szMsg, szBuf, lpszDSN); - LoadString(s_hModule, IDS_MSGTITLE, szBuf, sizeof(szBuf)); - MessageBox(hwndParent, szMsg, szBuf, MB_ICONEXCLAMATION | MB_OK); - } - 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)) - SQLRemoveDSNFromIni(lpsetupdlg->szDSN); - return TRUE; -} diff --git a/src/interfaces/odbc/windev/setup.rul b/src/interfaces/odbc/windev/setup.rul deleted file mode 100644 index a4f52a03f7..0000000000 --- a/src/interfaces/odbc/windev/setup.rul +++ /dev/null @@ -1,495 +0,0 @@ -/* -# Insight Distribution Systems - System V - Apr 1998 -#ident "@(#)setup.rul 1.13 :/sccs/sql/odbc/s.setup.rul 1/6/99 14:47:48" -*/ - -/*----------------------------------------------------------------------------*\ - * - * PostgreSQL ODBC Driver Installation Script for InstallShield - * -\*----------------------------------------------------------------------------*/ - - -#define APP_NAME "PostgreSQL ODBC Driver" -#define DRIVER_NAME "PostgreSQL" -#define DRIVER_FILE "PSQLODBC.DLL" -#define OLD_DRIVER_FILE "PODBC32.DLL" -#define OLD_DRIVER_FILE_RENAMED "podbc32_sav.dll" - -#define COMPANY_NAME "Insight" -#define PRODUCT_NAME "PostgreSQL ODBC Driver" -#define PRODUCT_VERSION "6.3" -#define PRODUCT_KEY "PSQLODBC.DLL" -#define UNINSTALL_KEY "PSQLODBCv6.3" - -#define ODBC_DM_KEY "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs" -#define ODBC_COMP_KEY "\\SOFTWARE\\ODBC\\ODBCINST.INI" -#define ODBC_CORE_KEY "\\SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Core" -#define ODBC_DRIVERS_KEY "\\SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers" - - -declare - // functions - prototype SetupScreen(); - prototype FileCompare(STRING, STRING, STRING, STRING); - - // variables - STRING svMainDirectory [_MAX_STRING], svGrp, svUninstLogFile, svPath; - STRING svValue, szName, szKey, szMessage; - STRING szMsg, szTmp, szTmp2, szFileSet, szProgram; - NUMBER nResult, pos, nvType, nvSize, nStartup, ComponentUsageCount; - - NUMBER nvDoNot, nvVersion, nvInstall, nCore, nDM; - STRING dm, core, szFileName, svFileName; - NUMBER options, nvInfo, nvResult; - LONG lResult; - STRING svCompVersion, svFileVersion, svCompDate, svCompTime, svFileDate, svFileTime; - -program - -StartHere: - Disable( BACKGROUND ); - - // Set up the installation screen. - SetupScreen(); - InstallationInfo(COMPANY_NAME, PRODUCT_NAME, PRODUCT_VERSION, PRODUCT_KEY); - RegDBSetAppInfo("Location", REGDB_STRING, WINSYSDIR ^ DRIVER_FILE, -1); - -// Create a Welcome dialog. -WelcomeDlg: - Disable( BACKBUTTON ); - Welcome( "Welcome to the PostgreSQL Odbc Driver Installation", 0 ); - Enable( BACKBUTTON ); - Enable( NEXTBUTTON ); - -GetTargetDirectory: - svMainDirectory = WINSYSDIR; - -OptionsDlg: - RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); - szKey = ODBC_DM_KEY; - nCore = RegDBKeyExist(szKey); - - szName = WINSYSDIR ^ "ODBC32.DLL"; - nDM = RegDBGetKeyValueEx(szKey, szName, nvType, svValue, nvSize); - - szMessage = "Select options for installing the ODBC Driver Manager.\n" + - "Analysis of your system suggests that the ODBC Driver Manager\n"; - - nvDoNot = FALSE; - nvInstall = FALSE; - nvVersion = FALSE; - if (nCore >= 0 && nDM >= 0) then - nvDoNot = TRUE; - szMessage = szMessage + "is already installed. Therefore, you may choose not to install it."; - else - nvInstall = TRUE; - szMessage = szMessage + "is not installed. Therefore, you should install it now."; - endif; - - Enable(FINISHBUTTON); - nResult = AskOptions(EXCLUSIVE, szMessage, - "Do not install Driver Manager", nvDoNot, - "Install Driver Manager ", nvInstall, - "Install Driver Manager (with version checking)", nvVersion); - - if (nResult = BACK) then - Disable(FINISHBUTTON); - goto WelcomeDlg; - endif; - -Version: - CompressInfo("driver.z", DRIVER_FILE, COMP_INFO_VERSIONMS|COMP_INFO_VERSIONLS, nvInfo, svCompVersion); - - szFileName = WINSYSDIR ^ DRIVER_FILE; - nResult = VerGetFileVersion(szFileName, svFileVersion); - - // MessageBox("System file PSQLODBC.dll version is " + svFileVersion, INFORMATION); - - lResult = VerCompare(svCompVersion, svFileVersion, VERSION); - - if (lResult = EQUALS) then - //date - CompressInfo("driver.z", DRIVER_FILE, COMP_INFO_DATE, nvInfo, svCompDate); - GetFileInfo(szFileName, FILE_DATE, nvResult, svFileDate); - - //time - CompressInfo("driver.z", DRIVER_FILE, COMP_INFO_TIME, nvInfo, svCompTime); - GetFileInfo(szFileName, FILE_TIME, nvResult, svFileTime); - - // If compressed file date/time is earlier than system file date/time - // then - nResult = FileCompare(svCompDate, svCompTime, svFileDate, svFileTime); - if (nResult < 0) then - lResult = LESS_THAN; - endif; - - NumToStr(szTmp, nResult); - // MessageBox("File Compare = " + szTmp, INFORMATION); - endif; - - if (lResult = LESS_THAN) then - MessageBeep(0); - nResult = AskYesNo("The " + PRODUCT_NAME + " is already installed on your system \nand is a newer version than the one that is about to be installed.\n\n" + - "Would you like to continue the installation anyway (not recommended)?", NO); - if (nResult = NO) then - MessageBeep(0); - MessageBox("Installation has been aborted.\nNo changes have been made to your system.", WARNING); - exit; - endif; - else - /* - nResult = AskYesNo("Ready to install " + PRODUCT_NAME + ".\n\nPress Yes to proceed with the installation.\nPress No to abort the installation.", YES); - if (nResult = NO) then - MessageBeep(0); - MessageBox("Installation has been aborted.\nNo changes have been made to your system.", WARNING); - exit; - endif; - */ - endif; - -CheckRegistry: - Enable(STATUSDLG); - - SetStatusWindow(5, "Checking registry entries..."); - Delay(1); - - RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); - szKey = ODBC_DM_KEY; - nResult = RegDBKeyExist(szKey); - if (nResult < 0 && nvDoNot = TRUE) then - MessageBeep(0); - MessageBox("ODBC Core Components are not installed!", SEVERE); - Disable(STATUSDLG); - MessageBeep(0); - MessageBox("Please install the ODBC Core Components\nand rerun this setup program.", INFORMATION); - exit; - endif; - - szName = WINSYSDIR ^ "ODBC32.DLL"; - nResult = RegDBGetKeyValueEx(szKey, szName, nvType, svValue, nvSize); - if (nResult < 0 && nvDoNot = TRUE) then - MessageBeep(0); - MessageBox("ODBC Driver Manager (ODBC32.DLL) is not installed!", SEVERE); - Disable(STATUSDLG); - MessageBeep(0); - MessageBox("Please install the ODBC Driver Manager\nand rerun this setup program.", INFORMATION); - exit; - endif; - - -FileSetup: - - SetStatusWindow( 10, "Copying program files..."); - StatusUpdate(ON, 90); - - DeinstallStart(svMainDirectory, svUninstLogFile, UNINSTALL_KEY, 0); - - // Show the uninstall under Add/Remove Programs in Control Panel - RegDBSetItem(REGDB_UNINSTALL_NAME, PRODUCT_NAME); - - szFileSet = "psqlodbc"; - - TARGETDIR = svMainDirectory; // winsys - - FileSetBeginDefine(szFileSet); - - - nResult = CompressGet("driver.z", "*.*", COMP_NORMAL); - if (nResult < 0) then - NumToStr(szTmp, nResult); - MessageBox("Compress Get Error on driver.z files.\n\nError # " + szTmp, SEVERE); - exit; - endif; - - TARGETDIR = svMainDirectory; // winsys - - // Driver Manager stuff - if (! nvDoNot) then - if (nvVersion) then - options = COMP_UPDATE_VERSION; - else - options = COMP_NORMAL; - endif; - - // The File usage count increments are handled by CompressGet - // with the SHAREDFILE option. - - nResult = CompressGet("redist.z", "*.*", options|SHAREDFILE); - if (nResult < 0) then - NumToStr(szTmp, nResult); - MessageBox("Compress Get Error on redist.z files.\n\nError # " + szTmp, SEVERE); - exit; - endif; - endif; - - - FileSetEndDefine(szFileSet); - -FileTransfer: - nResult = FileSetPerformEz(szFileSet, 0); - - switch(nResult) - case FS_DONE: - case FS_CREATEDIR: - MessageBeep(0); - MessageBox("Unable to create a required subdirectory under " + TARGETDIR + "." - + "\nPlease check write access to this directory.", SEVERE); - - abort; - default: - NumToStr(szTmp, nResult); - MessageBeep(0); - MessageBox("Error copying files to " + TARGETDIR + "." - + "\nPlease check this location and try again." - + "\n\nError Number:"+szTmp, SEVERE); - - abort; - - endswitch; - - -UpdateRegistry: - SetStatusWindow(95, "Creating registry entries..."); - Delay(2); - - RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); - - Disable(LOGGING); - - // Create ODBC Core Subkey (if it doesn't exist) - // (But don't create uninstall information for it) - szKey = ODBC_CORE_KEY; - nResult = RegDBCreateKeyEx(szKey, ""); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create ODBC Core subkey.", SEVERE); - exit; - endif; - - // Create Installed Driver Key (if it doesn't exist) - // (But don't create uninstall information for it) - szKey = ODBC_DRIVERS_KEY; - nResult = RegDBCreateKeyEx(szKey, ""); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create ODBC Drivers subkey.", SEVERE); - exit; - endif; - - - // Increment Driver Manager Component UsageCount - szKey = ODBC_CORE_KEY; - szName = "UsageCount"; - if (RegDBGetKeyValueEx(szKey, szName, nvType, svValue, nvSize) < 0) then - ComponentUsageCount = 0; - endif; - - // MessageBox("Current Driver Manager Component Usage Count = " + svValue, INFORMATION); - - StrToNum(ComponentUsageCount, svValue); - ComponentUsageCount = ComponentUsageCount + 1; - NumToStr(szTmp, ComponentUsageCount); - // MessageBox("New Driver Manager Component Usage Count = " + szTmp, INFORMATION); - - nResult = RegDBSetKeyValueEx(szKey, szName, REGDB_NUMBER, szTmp, -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to increment Driver Manager component usage count.", SEVERE); - exit; - endif; - - // Re-enable logging now - Enable(LOGGING); - - // set ODBC Drivers Subkey (installed) - szKey = ODBC_DRIVERS_KEY; - nResult = RegDBSetKeyValueEx(szKey, DRIVER_NAME, REGDB_STRING, "Installed", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'Installed' key value.", SEVERE); - exit; - endif; - - - // Driver Specification Subkey (PostgreSQL) - szKey = ODBC_COMP_KEY + "\\" + DRIVER_NAME; - nResult = RegDBCreateKeyEx(szKey, ""); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create ODBC Driver Key.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "APILevel", REGDB_STRING, "1", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'APILevel' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "ConnectFunctions", REGDB_STRING, "YYN", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'ConnectFunctions' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "Driver", REGDB_STRING, WINSYSDIR ^ DRIVER_FILE, -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'Driver' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "DriverODBCVer", REGDB_STRING, "02.00", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'DriverODBCVer' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "FileUsage", REGDB_STRING, "0", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'FileUsage' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "Setup", REGDB_STRING, WINSYSDIR ^ DRIVER_FILE, -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'Setup' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "SQLLevel", REGDB_STRING, "1", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'SQLLevel' key value.", SEVERE); - exit; - endif; - - nResult = RegDBSetKeyValueEx(szKey, "UsageCount", REGDB_NUMBER, "1", -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'UsageCount' key value.", SEVERE); - exit; - endif; - - pos = StrFind(CMDLINE, "UseDeclareFetch="); - if (pos >= 0) then - StrSub(svValue, CMDLINE, pos + 16, 1); - nResult = RegDBSetKeyValueEx(szKey, "UseDeclareFetch", REGDB_STRING, svValue, -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'UseDeclareFetch' key value.", SEVERE); - exit; - endif; - endif; - - pos = StrFind(CMDLINE, "Protocol="); - if (pos >= 0) then - StrSub(svValue, CMDLINE, pos + 9, 3); - nResult = RegDBSetKeyValueEx(szKey, "Protocol", REGDB_STRING, svValue, -1); - if (nResult < 0) then - MessageBeep(0); - MessageBox("Unable to create 'Protocol' key value.", SEVERE); - exit; - endif; - endif; - -RenameOld: - if (FindFile(WINSYSDIR, OLD_DRIVER_FILE, svFileName) = 0) then - szMessage = "Renaming old driver to " + OLD_DRIVER_FILE_RENAMED + " ..."; - SetStatusWindow(98, szMessage); - Delay(1); - - Disable(LOGGING); - - SRCDIR= WINSYSDIR; - TARGETDIR = WINSYSDIR; - - RenameFile(OLD_DRIVER_FILE, OLD_DRIVER_FILE_RENAMED); - - Enable(LOGGING); - endif; - -Done: - Delay(1); - SetStatusWindow(100, "Installation complete"); - - Delay(1); - Disable(STATUSDLG); - - if (BATCH_INSTALL = TRUE) then - szMsg = "Some files could not be updated because they are " + - "currently in use by other programs on the system. " + - "Files in use will be updated the next time you restart " + - "your system."; - RebootDialog("Restart Windows", szMsg, SYS_BOOTMACHINE); - CommitSharedFiles(0); - szMsg = "Driver setup complete.\n\nReboot your system to complete the installation."; - MessageBeep(0); - MessageBox(szMsg, INFORMATION); - else - - szMsg = "Driver installation completed successfully."; - MessageBeep(0); - MessageBox(szMsg, INFORMATION); - endif; - - exit; - -/*---------------------------------------------------------------------------*\ - * - * Function: SetupScreen - * - * Purpose: This function will set up the screen look. This includes - * colors, fonts, text to be displayed, etc. - * - * - * Input: - * - * Returns: - * - * Comments: -\*---------------------------------------------------------------------------*/ - -function SetupScreen() - begin - - Enable( INDVFILESTATUS ); - - SetTitle( APP_NAME + " Setup", 28, WHITE ); - - SetTitle( "Setup", 0, BACKGROUNDCAPTION ); // Caption bar text. - - Enable( BACKGROUND ); - - end; - -function FileCompare(szCompInfoDate, szCompInfoTime, szFileInfoDate, szFileInfoTime) - STRING year, month, day, file_date, file_time; - NUMBER nResult; - begin - StrSub(year, szFileInfoDate, 2, 2); - StrSub(month, szFileInfoDate, 5, 2); - StrSub(day, szFileInfoDate, 8, 2); - file_date = month + "-" + day + "-" + year; - - nResult = StrCompare(szCompInfoDate, file_date); - if (nResult != 0) then - return nResult; - endif; - - StrSub(file_time, szFileInfoTime, 0, 5); - - // MessageBox("Comp = " + szCompInfoDate + " " + szCompInfoTime + ", File = " + file_date + " " + file_time, INFORMATION); - nResult = StrCompare(szCompInfoTime, file_time); - - return nResult; - end; - - - diff --git a/src/interfaces/odbc/windev/socket.c b/src/interfaces/odbc/windev/socket.c deleted file mode 100644 index 031a6779cb..0000000000 --- a/src/interfaces/odbc/windev/socket.c +++ /dev/null @@ -1,355 +0,0 @@ -/*------- - * Module: socket.c - * - * Description: This module contains functions for low level socket - * operations (connecting/reading/writing to the backend) - * - * Classes: SocketClass (Functions prefix: "SOCK_") - * - * API functions: none - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "socket.h" - -#include "connection.h" - -#ifndef WIN32 -#include -#include /* for memset */ -#endif - -extern GLOBAL_VALUES globals; - -#ifndef BOOL -#define BOOL int -#endif -#ifndef TRUE -#define TRUE (BOOL)1 -#endif -#ifndef FALSE -#define FALSE (BOOL)0 -#endif - - -void -SOCK_clear_error(SocketClass *self) -{ - self->errornumber = 0; - self->errormsg = NULL; -} - - -SocketClass * -SOCK_Constructor(const ConnectionClass *conn) -{ - SocketClass *rv; - - rv = (SocketClass *) malloc(sizeof(SocketClass)); - - if (rv != NULL) - { - rv->socket = (SOCKETFD) - 1; - rv->buffer_filled_in = 0; - rv->buffer_filled_out = 0; - rv->buffer_read_in = 0; - - if (rv) - rv->buffer_size = conn->connInfo.drivers.socket_buffersize; - else - rv->buffer_size = globals.socket_buffersize; - rv->buffer_in = (unsigned char *) malloc(rv->buffer_size); - if (!rv->buffer_in) - { - free(rv); - return NULL; - } - - rv->buffer_out = (unsigned char *) malloc(rv->buffer_size); - if (!rv->buffer_out) - { - free(rv->buffer_in); - free(rv); - return NULL; - } - rv->errormsg = NULL; - rv->errornumber = 0; - rv->reverse = FALSE; - } - return rv; -} - - -void -SOCK_Destructor(SocketClass *self) -{ - mylog("SOCK_Destructor\n"); - if (self->socket != -1) - { - SOCK_put_char(self, 'X'); - SOCK_flush_output(self); - closesocket(self->socket); - } - - if (self->buffer_in) - free(self->buffer_in); - - if (self->buffer_out) - free(self->buffer_out); - - free(self); -} - - -char -SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname) -{ - struct hostent *host; - struct sockaddr_in sadr; - unsigned long iaddr; - - if (self->socket != -1) - { - self->errornumber = SOCKET_ALREADY_CONNECTED; - self->errormsg = "Socket is already connected"; - return 0; - } - - memset((char *) &sadr, 0, sizeof(sadr)); - - /* - * If it is a valid IP address, use it. Otherwise use hostname lookup. - */ - iaddr = inet_addr(hostname); - if (iaddr == INADDR_NONE) - { - host = gethostbyname(hostname); - if (host == NULL) - { - self->errornumber = SOCKET_HOST_NOT_FOUND; - self->errormsg = "Could not resolve hostname."; - return 0; - } - memcpy(&(sadr.sin_addr), host->h_addr, host->h_length); - } - else - memcpy(&(sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr)); - - sadr.sin_family = AF_INET; - sadr.sin_port = htons(port); - - self->socket = socket(AF_INET, SOCK_STREAM, 0); - if (self->socket == -1) - { - self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET; - self->errormsg = "Could not create Socket."; - return 0; - } - - 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); - self->socket = (SOCKETFD) - 1; - return 0; - } - return 1; -} - - -void -SOCK_get_n_char(SocketClass *self, char *buffer, int len) -{ - int lf; - - if (!buffer) - { - self->errornumber = SOCKET_NULLPOINTER_PARAMETER; - self->errormsg = "get_n_char was called with NULL-Pointer"; - return; - } - - for (lf = 0; lf < len; lf++) - buffer[lf] = SOCK_get_next_byte(self); -} - - -void -SOCK_put_n_char(SocketClass *self, char *buffer, int len) -{ - int lf; - - if (!buffer) - { - self->errornumber = SOCKET_NULLPOINTER_PARAMETER; - self->errormsg = "put_n_char was called with NULL-Pointer"; - return; - } - - for (lf = 0; lf < len; lf++) - SOCK_put_next_byte(self, (unsigned char) buffer[lf]); -} - - -/* - * bufsize must include room for the null terminator - * will read at most bufsize-1 characters + null. - * returns TRUE if truncation occurs. - */ -BOOL -SOCK_get_string(SocketClass *self, char *buffer, int bufsize) -{ - register int lf = 0; - - for (lf = 0; lf < bufsize - 1; lf++) - if (!(buffer[lf] = SOCK_get_next_byte(self))) - return FALSE; - - buffer[bufsize - 1] = '\0'; - return TRUE; -} - - -void -SOCK_put_string(SocketClass *self, char *string) -{ - register int lf; - int len; - - len = strlen(string) + 1; - - for (lf = 0; lf < len; lf++) - SOCK_put_next_byte(self, (unsigned char) string[lf]); -} - - -int -SOCK_get_int(SocketClass *self, short len) -{ - switch (len) - { - case 2: - { - unsigned short buf; - - SOCK_get_n_char(self, (char *) &buf, len); - if (self->reverse) - return buf; - else - return ntohs(buf); - } - - case 4: - { - unsigned int buf; - - SOCK_get_n_char(self, (char *) &buf, len); - if (self->reverse) - return buf; - else - return ntohl(buf); - } - - default: - self->errornumber = SOCKET_GET_INT_WRONG_LENGTH; - self->errormsg = "Cannot read ints of that length"; - return 0; - } -} - - -void -SOCK_put_int(SocketClass *self, int value, short len) -{ - unsigned int rv; - - switch (len) - { - case 2: - rv = self->reverse ? value : htons((unsigned short) value); - SOCK_put_n_char(self, (char *) &rv, 2); - return; - - case 4: - rv = self->reverse ? value : htonl((unsigned int) value); - SOCK_put_n_char(self, (char *) &rv, 4); - return; - - default: - self->errornumber = SOCKET_PUT_INT_WRONG_LENGTH; - self->errormsg = "Cannot write ints of that length"; - return; - } -} - - -void -SOCK_flush_output(SocketClass *self) -{ - int written; - - written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0); - if (written != self->buffer_filled_out) - { - self->errornumber = SOCKET_WRITE_ERROR; - self->errormsg = "Could not flush socket buffer."; - } - self->buffer_filled_out = 0; -} - - -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, self->buffer_size, 0); - - mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size); - - if (self->buffer_filled_in < 0) - { - self->errornumber = SOCKET_READ_ERROR; - self->errormsg = "Error while reading from the socket."; - self->buffer_filled_in = 0; - return 0; - } - if (self->buffer_filled_in == 0) - { - self->errornumber = SOCKET_CLOSED; - self->errormsg = "Socket has been closed."; - self->buffer_filled_in = 0; - return 0; - } - } - return self->buffer_in[self->buffer_read_in++]; -} - - -void -SOCK_put_next_byte(SocketClass *self, unsigned char next_byte) -{ - int bytes_sent; - - self->buffer_out[self->buffer_filled_out++] = next_byte; - - if (self->buffer_filled_out == self->buffer_size) - { - /* buffer is full, so write it out */ - bytes_sent = send(self->socket, (char *) self->buffer_out, self->buffer_size, 0); - if (bytes_sent != self->buffer_size) - { - self->errornumber = SOCKET_WRITE_ERROR; - self->errormsg = "Error while writing to the socket."; - } - self->buffer_filled_out = 0; - } -} diff --git a/src/interfaces/odbc/windev/socket.h b/src/interfaces/odbc/windev/socket.h deleted file mode 100644 index c49d9fe88d..0000000000 --- a/src/interfaces/odbc/windev/socket.h +++ /dev/null @@ -1,94 +0,0 @@ -/* File: socket.h - * - * Description: See "socket.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __SOCKET_H__ -#define __SOCKET_H__ - -#include "psqlodbc.h" - -#ifndef WIN32 -#include -#include -#include -#include -#include -#include - -#define closesocket(xxx) close(xxx) -#define SOCKETFD int - -#ifndef INADDR_NONE -#ifndef _IN_ADDR_T -#define _IN_ADDR_T -typedef unsigned int in_addr_t; -#endif -#define INADDR_NONE ((in_addr_t)-1) -#endif - -#else -#include -#define SOCKETFD SOCKET -#endif - -#define SOCKET_ALREADY_CONNECTED 1 -#define SOCKET_HOST_NOT_FOUND 2 -#define SOCKET_COULD_NOT_CREATE_SOCKET 3 -#define SOCKET_COULD_NOT_CONNECT 4 -#define SOCKET_READ_ERROR 5 -#define SOCKET_WRITE_ERROR 6 -#define SOCKET_NULLPOINTER_PARAMETER 7 -#define SOCKET_PUT_INT_WRONG_LENGTH 8 -#define SOCKET_GET_INT_WRONG_LENGTH 9 -#define SOCKET_CLOSED 10 - - -struct SocketClass_ -{ - - int buffer_size; - int buffer_filled_in; - int buffer_filled_out; - int buffer_read_in; - unsigned char *buffer_in; - unsigned char *buffer_out; - - SOCKETFD socket; - - char *errormsg; - int errornumber; - - char reverse; /* used to handle Postgres 6.2 protocol - * (reverse byte order) */ - -}; - -#define SOCK_get_char(self) (SOCK_get_next_byte(self)) -#define SOCK_put_char(self, c) (SOCK_put_next_byte(self, c)) - - -/* error functions */ -#define SOCK_get_errcode(self) (self->errornumber) -#define SOCK_get_errmsg(self) (self->errormsg) - - -/* Socket prototypes */ -SocketClass *SOCK_Constructor(const ConnectionClass *conn); -void SOCK_Destructor(SocketClass *self); -char SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname); -void SOCK_get_n_char(SocketClass *self, char *buffer, int len); -void SOCK_put_n_char(SocketClass *self, char *buffer, int len); -BOOL SOCK_get_string(SocketClass *self, char *buffer, int bufsize); -void SOCK_put_string(SocketClass *self, char *string); -int SOCK_get_int(SocketClass *self, short len); -void SOCK_put_int(SocketClass *self, int value, short len); -void SOCK_flush_output(SocketClass *self); -unsigned char SOCK_get_next_byte(SocketClass *self); -void SOCK_put_next_byte(SocketClass *self, unsigned char next_byte); -void SOCK_clear_error(SocketClass *self); - -#endif diff --git a/src/interfaces/odbc/windev/statement.c b/src/interfaces/odbc/windev/statement.c deleted file mode 100644 index bfdb8a2fc0..0000000000 --- a/src/interfaces/odbc/windev/statement.c +++ /dev/null @@ -1,1161 +0,0 @@ -/*------- - * Module: statement.c - * - * Description: This module contains functions related to creating - * and manipulating a statement. - * - * Classes: StatementClass (Functions prefix: "SC_") - * - * API functions: SQLAllocStmt, SQLFreeStmt - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "statement.h" - -#include "bind.h" -#include "connection.h" -#include "qresult.h" -#include "convert.h" -#include "environ.h" - -#include -#include -#include - -#include "pgapifunc.h" - - -#define PRN_NULLCHECK - - -/* Map sql commands to statement types */ -static struct -{ - int type; - char *s; -} Statement_Type[] = - -{ - { - STMT_TYPE_SELECT, "SELECT" - }, - { - STMT_TYPE_INSERT, "INSERT" - }, - { - STMT_TYPE_UPDATE, "UPDATE" - }, - { - STMT_TYPE_DELETE, "DELETE" - }, - { - STMT_TYPE_CREATE, "CREATE" - }, - { - STMT_TYPE_ALTER, "ALTER" - }, - { - STMT_TYPE_DROP, "DROP" - }, - { - STMT_TYPE_GRANT, "GRANT" - }, - { - STMT_TYPE_REVOKE, "REVOKE" - }, - { - STMT_TYPE_PROCCALL, "{" - }, - { - 0, NULL - } -}; - - -RETCODE SQL_API -PGAPI_AllocStmt(HDBC hdbc, - HSTMT FAR * phstmt) -{ - static char *func = "PGAPI_AllocStmt"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - StatementClass *stmt; - - mylog("%s: entering...\n", func); - - if (!conn) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - stmt = SC_Constructor(); - - mylog("**** PGAPI_AllocStmt: hdbc = %u, stmt = %u\n", hdbc, stmt); - - if (!stmt) - { - conn->errornumber = CONN_STMT_ALLOC_ERROR; - conn->errormsg = "No more memory to allocate a further SQL-statement"; - *phstmt = SQL_NULL_HSTMT; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - if (!CC_add_statement(conn, stmt)) - { - conn->errormsg = "Maximum number of connections exceeded."; - conn->errornumber = CONN_STMT_ALLOC_ERROR; - CC_log_error(func, "", conn); - SC_Destructor(stmt); - *phstmt = SQL_NULL_HSTMT; - return SQL_ERROR; - } - - *phstmt = (HSTMT) stmt; - - /* Copy default statement options based from Connection options */ - stmt->options = conn->stmtOptions; - - stmt->stmt_size_limit = CC_get_max_query_len(conn); - /* Save the handle for later */ - stmt->phstmt = phstmt; - - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_FreeStmt(HSTMT hstmt, - UWORD fOption) -{ - static char *func = "PGAPI_FreeStmt"; - StatementClass *stmt = (StatementClass *) hstmt; - - mylog("%s: entering...hstmt=%u, fOption=%d\n", func, hstmt, fOption); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - SC_clear_error(stmt); - - if (fOption == SQL_DROP) - { - ConnectionClass *conn = stmt->hdbc; - - /* Remove the statement from the connection's statement list */ - if (conn) - { - if (!CC_remove_statement(conn, stmt)) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "Statement is currently executing a transaction."; - SC_log_error(func, "", stmt); - return SQL_ERROR; /* stmt may be executing a - * transaction */ - } - - /* Free any cursors and discard any result info */ - if (stmt->result) - { - QR_Destructor(stmt->result); - stmt->result = NULL; - } - } - - /* 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 - { - stmt->errormsg = "Invalid option passed to PGAPI_FreeStmt."; - stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - return SQL_SUCCESS; -} - - -/* - * StatementClass implementation - */ -void -InitializeStatementOptions(StatementOptions *opt) -{ - memset(opt, 0, sizeof(StatementOptions)); - opt->maxRows = 0; /* driver returns all rows */ - opt->maxLength = 0; /* driver returns all data for char/binary */ - opt->rowset_size = 1; - opt->keyset_size = 0; /* fully keyset driven is the default */ - opt->scroll_concurrency = SQL_CONCUR_READ_ONLY; - opt->cursor_type = SQL_CURSOR_FORWARD_ONLY; - opt->bind_size = 0; /* default is to bind by column */ - opt->retrieve_data = SQL_RD_ON; - opt->use_bookmarks = SQL_UB_OFF; - opt->paramset_size = 1; - opt->param_bind_type = 0; /* default is column-wise binding */ -} - - -StatementClass * -SC_Constructor(void) -{ - StatementClass *rv; - - rv = (StatementClass *) malloc(sizeof(StatementClass)); - if (rv) - { - rv->hdbc = NULL; /* no connection associated yet */ - rv->phstmt = NULL; - rv->result = NULL; - rv->manual_result = FALSE; - rv->prepare = FALSE; - rv->status = STMT_ALLOCATED; - rv->internal = FALSE; - - rv->errormsg = NULL; - rv->errornumber = 0; - rv->errormsg_created = FALSE; - rv->errormsg_malloced = FALSE; - - rv->statement = NULL; - rv->stmt_with_params = NULL; - rv->stmt_size_limit = -1; - rv->statement_type = STMT_TYPE_UNKNOWN; - - rv->bindings = NULL; - rv->bindings_allocated = 0; - - rv->bookmark.buffer = NULL; - rv->bookmark.used = NULL; - - rv->parameters_allocated = 0; - rv->parameters = 0; - - rv->currTuple = -1; - rv->rowset_start = -1; - rv->current_col = -1; - rv->bind_row = 0; - rv->last_fetch_count = 0; - rv->save_rowset_size = -1; - - rv->data_at_exec = -1; - rv->current_exec_param = -1; - rv->put_data = FALSE; - - rv->lobj_fd = -1; - rv->cursor_name[0] = '\0'; - - /* Parse Stuff */ - rv->ti = NULL; - rv->fi = NULL; - rv->ntab = 0; - rv->nfld = 0; - rv->parse_status = STMT_PARSE_NONE; - - /* Clear Statement Options -- defaults will be set in AllocStmt */ - memset(&rv->options, 0, sizeof(StatementOptions)); - - rv->pre_executing = FALSE; - rv->inaccurate_result = FALSE; - rv->miscinfo = 0; - } - return rv; -} - - -char -SC_Destructor(StatementClass *self) -{ - mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc); - SC_clear_error(self); - if (STMT_EXECUTING == self->status) - { - self->errornumber = STMT_SEQUENCE_ERROR; - self->errormsg = "Statement is currently executing a transaction."; - return FALSE; - } - - if (self->result) - { - if (!self->hdbc) - self->result->conn = NULL; /* prevent any dbase activity */ - - QR_Destructor(self->result); - } - - if (self->statement) - free(self->statement); - if (self->stmt_with_params) - { - free(self->stmt_with_params); - self->stmt_with_params = NULL; - } - - SC_free_params(self, STMT_FREE_PARAMS_ALL); - - /* - * 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) - { - int lf; - - for (lf = 0; lf < self->bindings_allocated; lf++) - { - if (self->bindings[lf].ttlbuf != NULL) - free(self->bindings[lf].ttlbuf); - } - free(self->bindings); - } - - /* Free the parsed table information */ - if (self->ti) - { - int i; - - for (i = 0; i < self->ntab; i++) - free(self->ti[i]); - - free(self->ti); - } - - /* Free the parsed field information */ - if (self->fi) - { - int i; - - for (i = 0; i < self->nfld; i++) - free(self->fi[i]); - free(self->fi); - } - - free(self); - - mylog("SC_Destructor: EXIT\n"); - - 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) -{ - int i; - - mylog("SC_free_params: ENTER, self=%d\n", self); - - if (!self->parameters) - return; - - for (i = 0; i < self->parameters_allocated; i++) - { - if (self->parameters[i].data_at_exec == TRUE) - { - if (self->parameters[i].EXEC_used) - { - free(self->parameters[i].EXEC_used); - self->parameters[i].EXEC_used = NULL; - } - - if (self->parameters[i].EXEC_buffer) - { - if (self->parameters[i].SQLType != SQL_LONGVARBINARY) - free(self->parameters[i].EXEC_buffer); - self->parameters[i].EXEC_buffer = NULL; - } - } - } - self->data_at_exec = -1; - self->current_exec_param = -1; - self->put_data = FALSE; - - if (option == STMT_FREE_PARAMS_ALL) - { - free(self->parameters); - self->parameters = NULL; - self->parameters_allocated = 0; - } - - mylog("SC_free_params: EXIT\n"); -} - - -int -statement_type(char *statement) -{ - int i; - - /* ignore leading whitespace in query string */ - while (*statement && isspace((unsigned char) *statement)) - statement++; - - for (i = 0; Statement_Type[i].s; i++) - if (!strnicmp(statement, Statement_Type[i].s, strlen(Statement_Type[i].s))) - return Statement_Type[i].type; - - return STMT_TYPE_OTHER; -} - - -/* - * Called from SQLPrepare if STMT_PREMATURE, or - * from SQLExecute if STMT_FINISHED, or - * from SQLFreeStmt(SQL_CLOSE) - */ -char -SC_recycle_statement(StatementClass *self) -{ - ConnectionClass *conn; - - mylog("recycle statement: self= %u\n", self); - - SC_clear_error(self); - /* This would not happen */ - if (self->status == STMT_EXECUTING) - { - self->errornumber = STMT_SEQUENCE_ERROR; - self->errormsg = "Statement is currently executing a transaction."; - return FALSE; - } - - switch (self->status) - { - case STMT_ALLOCATED: - /* this statement does not need to be recycled */ - return TRUE; - - case STMT_READY: - break; - - case STMT_PREMATURE: - - /* - * Premature execution of the statement might have caused the - * start of a transaction. If so, we have to rollback that - * transaction. - */ - conn = SC_get_conn(self); - if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) - { - if (SC_is_pre_executable(self) && !conn->connInfo.disallow_premature) - CC_abort(conn); - } - break; - - case STMT_FINISHED: - break; - - default: - self->errormsg = "An internal error occured while recycling statements"; - self->errornumber = STMT_INTERNAL_ERROR; - return FALSE; - } - - /* Free the parsed table information */ - if (self->ti) - { - int i; - - for (i = 0; i < self->ntab; i++) - free(self->ti[i]); - - free(self->ti); - self->ti = NULL; - self->ntab = 0; - } - - /* Free the parsed field information */ - if (self->fi) - { - int i; - - for (i = 0; i < self->nfld; i++) - free(self->fi[i]); - free(self->fi); - self->fi = NULL; - self->nfld = 0; - } - self->parse_status = STMT_PARSE_NONE; - - /* Free any cursors */ - if (self->result) - { - QR_Destructor(self->result); - self->result = NULL; - } - self->inaccurate_result = FALSE; - - /* - * Reset only parameters that have anything to do with results - */ - self->status = STMT_READY; - self->manual_result = FALSE; /* very important */ - - self->currTuple = -1; - self->rowset_start = -1; - self->current_col = -1; - self->bind_row = 0; - self->last_fetch_count = 0; - - if (self->errormsg_malloced && self->errormsg) - free(self->errormsg); - self->errormsg = NULL; - self->errornumber = 0; - self->errormsg_created = FALSE; - self->errormsg_malloced = FALSE; - - 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; -} - - -/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */ -void -SC_pre_execute(StatementClass *self) -{ - mylog("SC_pre_execute: status = %d\n", self->status); - - if (self->status == STMT_READY) - { - mylog(" preprocess: status = READY\n"); - - self->miscinfo = 0; - if (self->statement_type == STMT_TYPE_SELECT) - { - char old_pre_executing = self->pre_executing; - - self->pre_executing = TRUE; - self->inaccurate_result = FALSE; - - PGAPI_Execute(self); - - self->pre_executing = old_pre_executing; - - if (self->status == STMT_FINISHED) - { - mylog(" preprocess: after status = FINISHED, so set PREMATURE\n"); - self->status = STMT_PREMATURE; - } - } - if (!SC_is_pre_executable(self)) - { - self->result = QR_Constructor(); - QR_set_status(self->result, PGRES_TUPLES_OK); - self->inaccurate_result = TRUE; - self->status = STMT_PREMATURE; - } - } -} - - -/* This is only called from SQLFreeStmt(SQL_UNBIND) */ -char -SC_unbind_cols(StatementClass *self) -{ - Int2 lf; - - for (lf = 0; lf < self->bindings_allocated; lf++) - { - self->bindings[lf].data_left = -1; - self->bindings[lf].buflen = 0; - self->bindings[lf].buffer = NULL; - self->bindings[lf].used = NULL; - self->bindings[lf].returntype = SQL_C_CHAR; - } - - self->bookmark.buffer = NULL; - self->bookmark.used = NULL; - - return 1; -} - - -void -SC_clear_error(StatementClass *self) -{ - if (self->errormsg_malloced && self->errormsg) - free(self->errormsg); - self->errornumber = 0; - self->errormsg = NULL; - self->errormsg_created = FALSE; - self->errormsg_malloced = FALSE; -} - - -/* - * This function creates an error msg which is the concatenation - * of the result, statement, connection, and socket messages. - */ -char * -SC_create_errormsg(StatementClass *self) -{ - QResultClass *res = self->result; - ConnectionClass *conn = self->hdbc; - int pos; - static char msg[4096]; - - msg[0] = '\0'; - - if (res && res->message) - strcpy(msg, res->message); - - else if (self->errormsg) - strcpy(msg, self->errormsg); - - if (conn) - { - SocketClass *sock = conn->sock; - - if (conn->errormsg && conn->errormsg[0] != '\0') - { - pos = strlen(msg); - sprintf(&msg[pos], ";\n%s", conn->errormsg); - } - - if (sock && sock->errormsg && sock->errormsg[0] != '\0') - { - pos = strlen(msg); - sprintf(&msg[pos], ";\n%s", sock->errormsg); - } - } - if (!msg[0] && res && QR_get_notice(res)) - return QR_get_notice(res); - - return msg; -} - - -char -SC_get_error(StatementClass *self, int *number, char **message) -{ - char rv; - - /* Create a very informative errormsg if it hasn't been done yet. */ - if (!self->errormsg_created) - { - self->errormsg = SC_create_errormsg(self); - self->errormsg_created = TRUE; - } - - if (self->errornumber) - { - *number = self->errornumber; - *message = self->errormsg; - if (!self->errormsg_malloced) - self->errormsg = NULL; - } - - rv = (self->errornumber != 0); - self->errornumber = 0; - - 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) -{ - return (self->currTuple + 1); -} - - -RETCODE -SC_fetch(StatementClass *self) -{ - static char *func = "SC_fetch"; - QResultClass *res = self->result; - int retval, - result; - -#ifdef DRIVER_CURSOR_IMPLEMENT - int updret; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - Int2 num_cols, - lf; - Oid type; - char *value; - ColumnInfoClass *coli; - - /* TupleField *tupleField; */ - ConnInfo *ci = &(SC_get_conn(self)->connInfo); - - self->last_fetch_count = 0; - coli = QR_get_fields(res); /* the column info */ - - mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, ci->drivers.use_declarefetch); - - if (self->manual_result || !SC_is_fetchcursor(self)) - { - 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 - */ - self->currTuple = QR_get_num_tuples(res); - return SQL_NO_DATA_FOUND; - } - - mylog("**** SC_fetch: manual_result\n"); - (self->currTuple)++; - } - else - { - /* read from the cache or the physical next tuple */ - retval = QR_next_tuple(res); - if (retval < 0) - { - mylog("**** SC_fetch: end_tuples\n"); - return SQL_NO_DATA_FOUND; - } - else if (retval > 0) - (self->currTuple)++; /* all is well */ - else - { - mylog("SC_fetch: error\n"); - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "Error fetching next row"; - SC_log_error(func, "", self); - return SQL_ERROR; - } - } - - num_cols = QR_NumResultCols(res); - - result = SQL_SUCCESS; - self->last_fetch_count = 1; - - /* - * If the bookmark column was bound then return a bookmark. Since this - * is used with SQLExtendedFetch, and the rowset size may be greater - * than 1, and an application can use row or column wise binding, use - * the code in copy_and_convert_field() to handle that. - */ - if (self->bookmark.buffer) - { - char buf[32]; - - sprintf(buf, "%ld", SC_get_bookmark(self)); - result = copy_and_convert_field(self, 0, buf, - SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used); - } - -#ifdef DRIVER_CURSOR_IMPLEMENT - updret = 0; - if (self->options.scroll_concurrency != SQL_CONCUR_READ_ONLY) - { - if (!QR_get_value_backend_row(res, self->currTuple, num_cols - 1)) - updret = SQL_ROW_DELETED; - num_cols -= 2; - } -#endif /* DRIVER_CURSOR_IMPLEMENT */ - if (self->options.retrieve_data == SQL_RD_OFF) /* data isn't required */ -#ifdef DRIVER_CURSOR_IMPLEMENT - return updret ? updret + 10 : SQL_SUCCESS; -#else - return SQL_SUCCESS; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - 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 */ - self->bindings[lf].data_left = -1; - - if (self->bindings[lf].buffer != NULL) - { - /* this column has a binding */ - - /* type = QR_get_field_type(res, lf); */ - type = CI_get_oid(coli, lf); /* speed things up */ - - mylog("type = %d\n", type); - - if (self->manual_result) - { - value = QR_get_value_manual(res, self->currTuple, lf); - mylog("manual_result\n"); - } - else if (SC_is_fetchcursor(self)) - value = QR_get_value_backend(res, lf); - else - value = QR_get_value_backend_row(res, self->currTuple, lf); - - mylog("value = '%s'\n", (value == NULL) ? "" : value); - - retval = copy_and_convert_field_bindinfo(self, type, value, lf); - - mylog("copy_and_convert: retval = %d\n", retval); - - switch (retval) - { - case COPY_OK: - break; /* OK, do next bound column */ - - case COPY_UNSUPPORTED_TYPE: - self->errormsg = "Received an unsupported type from Postgres."; - self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR; - SC_log_error(func, "", self); - result = SQL_ERROR; - break; - - case COPY_UNSUPPORTED_CONVERSION: - self->errormsg = "Couldn't handle the necessary data type conversion."; - self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR; - SC_log_error(func, "", self); - result = SQL_ERROR; - break; - - case COPY_RESULT_TRUNCATED: - self->errornumber = STMT_TRUNCATED; - self->errormsg = "Fetched item was truncated."; - qlog("The %dth item was truncated\n", lf + 1); - qlog("The buffer size = %d", self->bindings[lf].buflen); - qlog(" and the value is '%s'\n", value); - 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; - - default: - self->errormsg = "Unrecognized return value from copy_and_convert_field."; - self->errornumber = STMT_INTERNAL_ERROR; - SC_log_error(func, "", self); - result = SQL_ERROR; - break; - } - } - } - -#ifdef DRIVER_CURSOR_IMPLEMENT - if (updret) - result = updret + 10; -#endif /* DRIVER_CURSOR_IMPLEMENT */ - return result; -} - - -RETCODE -SC_execute(StatementClass *self) -{ - static char *func = "SC_execute"; - ConnectionClass *conn; - QResultClass *res; - char ok, - was_ok, - was_nonfatal; - Int2 oldstatus, - numcols; - QueryInfo qi; - ConnInfo *ci; - - - conn = SC_get_conn(self); - ci = &(conn->connInfo); - - /* Begin a transaction if one is not already in progress */ - - /* - * Basically we don't have to begin a transaction in autocommit mode - * because Postgres backend runs in autocomit mode. We issue "BEGIN" - * in the following cases. 1) we use declare/fetch and the statement - * is SELECT (because declare/fetch must be called in a transaction). - * 2) we are in autocommit off state and the statement isn't of type - * OTHER. - */ - if (!self->internal && !CC_is_in_trans(conn) && - (SC_is_fetchcursor(self) || - (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER))) - { - mylog(" about to begin a transaction on statement = %u\n", self); - res = CC_send_query(conn, "BEGIN", NULL); - if (QR_aborted(res)) - { - self->errormsg = "Could not begin a transaction"; - self->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - ok = QR_command_successful(res); - - mylog("SC_exec: begin ok = %d, status = %d\n", ok, QR_get_status(res)); - - QR_Destructor(res); - - if (!ok) - { - self->errormsg = "Could not begin a transaction"; - self->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", self); - return SQL_ERROR; - } - else - 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. */ - - /* - * Note that the declare cursor has already been prepended to the - * statement - */ - /* 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 (SC_is_fetchcursor(self) && self->result != NULL && - QR_command_successful(self->result)) - { - QR_Destructor(self->result); - - /* - * That worked, so now send the fetch to start getting data - * back - */ - qi.result_in = NULL; - qi.cursor = self->cursor_name; - qi.row_size = ci->drivers.fetch_max; - - /* - * Most likely the rowset size will not be set by the - * application until after the statement is executed, so might - * as well use the cache size. The qr_next_tuple() function - * 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); - - /* - * We shouldn't send COMMIT. Postgres backend does the autocommit - * if neccessary. (Zoltan, 04/26/2000) - */ - - /* - * Above seems wrong. Even in case of autocommit, started - * transactions must be committed. (Hiroshi, 02/11/2001) - */ - if (!self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) - { - res = CC_send_query(conn, "COMMIT", NULL); - QR_Destructor(res); - CC_set_no_trans(conn); - } - } - - conn->status = oldstatus; - self->status = STMT_FINISHED; - - /* Check the status of the result */ - if (self->result) - { - was_ok = QR_command_successful(self->result); - was_nonfatal = QR_command_nonfatal(self->result); - - if (was_ok) - self->errornumber = STMT_OK; - 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; - - /* see if the query did return any result columns */ - numcols = QR_NumResultCols(self->result); - - /* now allocate the array to hold the binding info */ - if (numcols > 0) - { - extend_bindings(self, numcols); - if (self->bindings == NULL) - { - self->errornumber = STMT_NO_MEMORY_ERROR; - self->errormsg = "Could not get enough free memory to store the binding information"; - SC_log_error(func, "", self); - return SQL_ERROR; - } - } - /* issue "ABORT" when query aborted */ - if (QR_get_aborted(self->result) && !self->internal) - 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; - self->errormsg = "Error creating the table"; - - /* - * This would allow the table to already exists, thus - * appending rows to it. BUT, if the table didn't have the - * same attributes, it would fail. return - * SQL_SUCCESS_WITH_INFO; - */ - } - else - { - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "Error while executing the query"; - } - - if (!self->internal) - CC_abort(conn); - } - - if (self->statement_type == STMT_TYPE_PROCCALL && - (self->errornumber == STMT_OK || - self->errornumber == STMT_INFO_ONLY) && - self->parameters && - self->parameters[0].buffer && - self->parameters[0].paramType == SQL_PARAM_OUTPUT) - { /* get the return value of the procedure - * call */ - RETCODE ret; - HSTMT hstmt = (HSTMT) self; - - ret = SC_fetch(hstmt); - if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) - { - ret = PGAPI_GetData(hstmt, 1, self->parameters[0].CType, self->parameters[0].buffer, self->parameters[0].buflen, self->parameters[0].used); - if (ret != SQL_SUCCESS) - { - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "GetData to Procedure return failed."; - } - } - else - { - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "SC_fetch to get a Procedure return failed."; - } - } - if (self->errornumber == STMT_OK) - return SQL_SUCCESS; - else if (self->errornumber == STMT_INFO_ONLY) - return SQL_SUCCESS_WITH_INFO; - else - { - self->errormsg = "Error while executing the query"; - SC_log_error(func, "", self); - return SQL_ERROR; - } -} - - -void -SC_log_error(char *func, char *desc, StatementClass *self) -{ -#ifdef PRN_NULLCHECK -#define nullcheck(a) (a ? a : "(NULL)") -#endif - if (self) - { - qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); - mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); - qlog(" ------------------------------------------------------------\n"); - qlog(" hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, self->result); - qlog(" manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal); - qlog(" bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated); - qlog(" parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated); - qlog(" statement_type=%d, statement='%s'\n", self->statement_type, nullcheck(self->statement)); - qlog(" stmt_with_params='%s'\n", nullcheck(self->stmt_with_params)); - qlog(" data_at_exec=%d, current_exec_param=%d, put_data=%d\n", self->data_at_exec, self->current_exec_param, self->put_data); - qlog(" currTuple=%d, current_col=%d, lobj_fd=%d\n", self->currTuple, self->current_col, self->lobj_fd); - qlog(" maxRows=%d, rowset_size=%d, keyset_size=%d, cursor_type=%d, scroll_concurrency=%d\n", self->options.maxRows, self->options.rowset_size, self->options.keyset_size, self->options.cursor_type, self->options.scroll_concurrency); - qlog(" cursor_name='%s'\n", nullcheck(self->cursor_name)); - - qlog(" ----------------QResult Info -------------------------------\n"); - - if (self->result) - { - QResultClass *res = self->result; - - qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn); - qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor)); - qlog(" message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice)); - qlog(" status=%d, inTuples=%d\n", res->status, res->inTuples); - } - - /* Log the connection error if there is one */ - CC_log_error(func, desc, self->hdbc); - } - else - qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc); -#undef PRN_NULLCHECK -} diff --git a/src/interfaces/odbc/windev/statement.h b/src/interfaces/odbc/windev/statement.h deleted file mode 100644 index 9b52f25694..0000000000 --- a/src/interfaces/odbc/windev/statement.h +++ /dev/null @@ -1,254 +0,0 @@ -/* File: statement.h - * - * Description: See "statement.c" - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __STATEMENT_H__ -#define __STATEMENT_H__ - -#include "psqlodbc.h" - -#include "bind.h" - - -#ifndef FALSE -#define FALSE (BOOL)0 -#endif -#ifndef TRUE -#define TRUE (BOOL)1 -#endif - -typedef enum -{ - STMT_ALLOCATED, /* The statement handle is allocated, but - * not used so far */ - STMT_READY, /* the statement is waiting to be executed */ - STMT_PREMATURE, /* ODBC states that it is legal to call - * e.g. SQLDescribeCol before a call to - * SQLExecute, but after SQLPrepare. To - * get all the necessary information in - * such a case, we simply execute the - * query _before_ the actual call to - * SQLExecute, so that statement is - * considered to be "premature". */ - STMT_FINISHED, /* statement execution has finished */ - STMT_EXECUTING /* statement execution is still going on */ -} STMT_Status; - -#define STMT_ROW_VERSION_CHANGED (-4) -#define STMT_POS_BEFORE_RECORDSET (-3) -#define STMT_TRUNCATED (-2) -#define STMT_INFO_ONLY (-1) /* not an error message, - * just a notification - * to be returned by - * SQLError */ -#define STMT_OK 0 /* will be interpreted - * as "no error pending" */ -#define STMT_EXEC_ERROR 1 -#define STMT_STATUS_ERROR 2 -#define STMT_SEQUENCE_ERROR 3 -#define STMT_NO_MEMORY_ERROR 4 -#define STMT_COLNUM_ERROR 5 -#define STMT_NO_STMTSTRING 6 -#define STMT_ERROR_TAKEN_FROM_BACKEND 7 -#define STMT_INTERNAL_ERROR 8 -#define STMT_STILL_EXECUTING 9 -#define STMT_NOT_IMPLEMENTED_ERROR 10 -#define STMT_BAD_PARAMETER_NUMBER_ERROR 11 -#define STMT_OPTION_OUT_OF_RANGE_ERROR 12 -#define STMT_INVALID_COLUMN_NUMBER_ERROR 13 -#define STMT_RESTRICTED_DATA_TYPE_ERROR 14 -#define STMT_INVALID_CURSOR_STATE_ERROR 15 -#define STMT_OPTION_VALUE_CHANGED 16 -#define STMT_CREATE_TABLE_ERROR 17 -#define STMT_NO_CURSOR_NAME 18 -#define STMT_INVALID_CURSOR_NAME 19 -#define STMT_INVALID_ARGUMENT_NO 20 -#define STMT_ROW_OUT_OF_RANGE 21 -#define STMT_OPERATION_CANCELLED 22 -#define STMT_INVALID_CURSOR_POSITION 23 -#define STMT_VALUE_OUT_OF_RANGE 24 -#define STMT_OPERATION_INVALID 25 -#define STMT_PROGRAM_TYPE_OUT_OF_RANGE 26 -#define STMT_BAD_ERROR 27 -#define STMT_INVALID_OPTION_IDENTIFIER 28 - -/* statement types */ -enum -{ - STMT_TYPE_UNKNOWN = -2, - STMT_TYPE_OTHER = -1, - STMT_TYPE_SELECT = 0, - STMT_TYPE_INSERT, - STMT_TYPE_UPDATE, - STMT_TYPE_DELETE, - STMT_TYPE_CREATE, - STMT_TYPE_ALTER, - STMT_TYPE_DROP, - STMT_TYPE_GRANT, - STMT_TYPE_REVOKE, - STMT_TYPE_PROCCALL -}; - -#define STMT_UPDATE(stmt) (stmt->statement_type > STMT_TYPE_SELECT) - - -/* Parsing status */ -enum -{ - STMT_PARSE_NONE = 0, - STMT_PARSE_COMPLETE, - STMT_PARSE_INCOMPLETE, - STMT_PARSE_FATAL, -}; - -/* Result style */ -enum -{ - STMT_FETCH_NONE = 0, - STMT_FETCH_NORMAL, - STMT_FETCH_EXTENDED, -}; - -typedef struct -{ - COL_INFO *col_info; /* cached SQLColumns info for this table */ - char name[MAX_TABLE_LEN + 1]; - char alias[MAX_TABLE_LEN + 1]; -} TABLE_INFO; - -typedef struct -{ - TABLE_INFO *ti; /* resolve to explicit table names */ - int precision; - int scale; - int display_size; - int length; - int type; - char nullable; - char func; - char expr; - char quote; - char dquote; - char numeric; - char dot[MAX_TABLE_LEN + 1]; - char name[MAX_COLUMN_LEN + 1]; - char alias[MAX_COLUMN_LEN + 1]; -} FIELD_INFO; - - -/******** Statement Handle ***********/ -struct StatementClass_ -{ - ConnectionClass *hdbc; /* pointer to ConnectionClass this - * statement belongs to */ - QResultClass *result; /* result of the current statement */ - HSTMT FAR *phstmt; - StatementOptions options; - - STMT_Status status; - char *errormsg; - int errornumber; - - /* information on bindings */ - BindInfoClass *bindings; /* array to store the binding information */ - BindInfoClass bookmark; - int bindings_allocated; - - /* information on statement parameters */ - int parameters_allocated; - ParameterInfoClass *parameters; - - Int4 currTuple; /* current absolute row number (GetData, - * SetPos, SQLFetch) */ - int save_rowset_size; /* saved rowset size in case of - * change/FETCH_NEXT */ - int rowset_start; /* start of rowset (an absolute row - * number) */ - int bind_row; /* current offset for Multiple row/column - * binding */ - int last_fetch_count; /* number of rows retrieved in - * last fetch/extended fetch */ - int current_col; /* current column for GetData -- used to - * handle multiple calls */ - int lobj_fd; /* fd of the current large object */ - - char *statement; /* if non--null pointer to the SQL - * statement that has been executed */ - - TABLE_INFO **ti; - FIELD_INFO **fi; - int nfld; - int ntab; - - int parse_status; - - int statement_type; /* According to the defines above */ - int data_at_exec; /* Number of params needing SQLPutData */ - int current_exec_param; /* The current parameter for - * SQLPutData */ - - char put_data; /* Has SQLPutData been called yet? */ - - char errormsg_created; /* has an informative error msg - * been created? */ - char manual_result; /* Is the statement result manually built? */ - char prepare; /* is this statement a prepared statement - * or direct */ - - char internal; /* Is this statement being called - * internally? */ - - char cursor_name[MAX_CURSOR_LEN + 1]; - - char *stmt_with_params; /* statement after parameter - * substitution */ - int stmt_size_limit; - - char pre_executing; /* This statement is prematurely executing */ - char inaccurate_result; /* Current status is PREMATURE but - * result is inaccurate */ - char errormsg_malloced; /* Current error message is - * malloed (not in a static - * variable) ? */ - char miscinfo; -}; - -#define SC_get_conn(a) (a->hdbc) -#define SC_get_Result(a) (a->result); - -/* options for SC_free_params() */ -#define STMT_FREE_PARAMS_ALL 0 -#define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1 - -/* misc info */ -#define SC_set_pre_executable(a) (a->miscinfo |= 1L) -#define SC_no_pre_executable(a) (a->miscinfo &= ~1L) -#define SC_is_pre_executable(a) ((a->miscinfo & 1L) != 0) -#define SC_set_fetchcursor(a) (a->miscinfo |= 2L) -#define SC_no_fetchcursor(a) (a->miscinfo &= ~2L) -#define SC_is_fetchcursor(a) ((a->miscinfo & 2L) != 0) - -/* Statement prototypes */ -StatementClass *SC_Constructor(void); -void InitializeStatementOptions(StatementOptions *opt); -char SC_Destructor(StatementClass *self); -int statement_type(char *statement); -char parse_statement(StatementClass *stmt); -void SC_pre_execute(StatementClass *self); -char SC_unbind_cols(StatementClass *self); -char SC_recycle_statement(StatementClass *self); - -void SC_clear_error(StatementClass *self); -char SC_get_error(StatementClass *self, int *number, char **message); -char *SC_create_errormsg(StatementClass *self); -RETCODE SC_execute(StatementClass *self); -RETCODE SC_fetch(StatementClass *self); -void SC_free_params(StatementClass *self, char option); -void SC_log_error(char *func, char *desc, StatementClass *self); -unsigned long SC_get_bookmark(StatementClass *self); - -#endif diff --git a/src/interfaces/odbc/windev/tuple.c b/src/interfaces/odbc/windev/tuple.c deleted file mode 100644 index 512f36d2b2..0000000000 --- a/src/interfaces/odbc/windev/tuple.c +++ /dev/null @@ -1,66 +0,0 @@ -/*------- - * 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" - -#include -#include - - -void -set_tuplefield_null(TupleField *tuple_field) -{ - tuple_field->len = 0; - tuple_field->value = NULL; /* strdup(""); */ -} - - -void -set_tuplefield_string(TupleField *tuple_field, char *string) -{ - tuple_field->len = strlen(string); - tuple_field->value = malloc(strlen(string) + 1); - strcpy(tuple_field->value, string); -} - - -void -set_tuplefield_int2(TupleField *tuple_field, Int2 value) -{ - char buffer[10]; - - sprintf(buffer, "%d", value); - - tuple_field->len = strlen(buffer) + 1; - /* +1 ... is this correct (better be on the save side-...) */ - tuple_field->value = strdup(buffer); -} - - -void -set_tuplefield_int4(TupleField *tuple_field, Int4 value) -{ - char buffer[15]; - - sprintf(buffer, "%ld", value); - - tuple_field->len = strlen(buffer) + 1; - /* +1 ... is this correct (better be on the save side-...) */ - tuple_field->value = strdup(buffer); -} diff --git a/src/interfaces/odbc/windev/tuple.h b/src/interfaces/odbc/windev/tuple.h deleted file mode 100644 index fdc1a5f9ea..0000000000 --- a/src/interfaces/odbc/windev/tuple.h +++ /dev/null @@ -1,46 +0,0 @@ -/* File: tuple.h - * - * Description: See "tuple.c" - * - * Important NOTE: The TupleField structure is used both to hold backend data and - * manual result set data. The "set_" functions and the TupleNode - * structure are only used for manual result sets by info routines. - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __TUPLE_H__ -#define __TUPLE_H__ - -#include "psqlodbc.h" - -/* Used by backend data AND manual result sets */ -struct TupleField_ -{ - Int4 len; /* length of the current Tuple */ - void *value; /* an array representing the value */ -}; - -/* Used ONLY for manual result sets */ -struct TupleNode_ -{ - struct TupleNode_ *prev, - *next; - TupleField tuple[1]; -}; - -/* These macros are wrappers for the corresponding set_tuplefield functions - but these handle automatic NULL determination and call set_tuplefield_null() - if appropriate for the datatype (used by SQLGetTypeInfo). -*/ -#define set_nullfield_string(FLD, VAL) ((VAL) ? set_tuplefield_string(FLD, (VAL)) : set_tuplefield_null(FLD)) -#define set_nullfield_int2(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int2(FLD, (VAL)) : set_tuplefield_null(FLD)) -#define set_nullfield_int4(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int4(FLD, (VAL)) : set_tuplefield_null(FLD)) - -void set_tuplefield_null(TupleField *tuple_field); -void set_tuplefield_string(TupleField *tuple_field, char *string); -void set_tuplefield_int2(TupleField *tuple_field, Int2 value); -void set_tuplefield_int4(TupleField *tuple_field, Int4 value); - -#endif diff --git a/src/interfaces/odbc/windev/tuplelist.c b/src/interfaces/odbc/windev/tuplelist.c deleted file mode 100644 index 0ae2130bff..0000000000 --- a/src/interfaces/odbc/windev/tuplelist.c +++ /dev/null @@ -1,216 +0,0 @@ -/*-------- - * 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 "tuplelist.h" - -#include -#include "tuple.h" - - -TupleListClass * -TL_Constructor(UInt4 fieldcnt) -{ - TupleListClass *rv; - - mylog("in TL_Constructor\n"); - - rv = (TupleListClass *) malloc(sizeof(TupleListClass)); - if (rv) - { - rv->num_fields = fieldcnt; - rv->num_tuples = 0; - rv->list_start = NULL; - rv->list_end = NULL; - rv->lastref = NULL; - rv->last_indexed = -1; - } - - mylog("exit TL_Constructor\n"); - - return rv; -} - - -void -TL_Destructor(TupleListClass *self) -{ - int lf; - TupleNode *node, - *tp; - - mylog("TupleList: in DESTRUCTOR\n"); - - node = self->list_start; - while (node != NULL) - { - for (lf = 0; lf < self->num_fields; lf++) - if (node->tuple[lf].value != NULL) - free(node->tuple[lf].value); - tp = node->next; - free(node); - node = tp; - } - - free(self); - - mylog("TupleList: exit DESTRUCTOR\n"); -} - - -void * -TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno) -{ - Int4 lf; - Int4 delta, - from_end; - char end_is_closer, - start_is_closer; - TupleNode *rv; - - if (self->last_indexed == -1) - /* we have an empty tuple list */ - return NULL; - - /* some more sanity checks */ - if ((tupleno >= self->num_tuples) || (tupleno < 0)) - /* illegal tuple number range */ - return NULL; - - if ((fieldno >= self->num_fields) || (fieldno < 0)) - /* illegel field number range */ - return NULL; - - /* - * check if we are accessing the same tuple that was used in the last - * fetch (e.g: for fetching all the fields one after another. Do this - * to speed things up - */ - if (tupleno == self->last_indexed) - return self->lastref->tuple[fieldno].value; - - /* now for the tricky part... */ - - /* - * Since random access is quite inefficient for linked lists we use - * the lastref pointer that points to the last element referenced by a - * get_fieldval() call in conjunction with the its index number that - * is stored in last_indexed. (So we use some locality of reference - * principle to speed things up) - */ - - delta = tupleno - self->last_indexed; - /* if delta is positive, we have to go forward */ - - /* - * now check if we are closer to the start or the end of the list than - * to our last_indexed pointer - */ - from_end = (self->num_tuples - 1) - tupleno; - - start_is_closer = labs(delta) > tupleno; - - /* - * true if we are closer to the start of the list than to the - * last_indexed pointer - */ - - end_is_closer = labs(delta) > from_end; - /* true if we are closer at the end of the list */ - - if (end_is_closer) - { - /* scanning from the end is the shortest way. so we do that... */ - rv = self->list_end; - for (lf = 0; lf < from_end; lf++) - rv = rv->prev; - } - else if (start_is_closer) - { - /* - * the shortest way is to start the search from the head of the - * list - */ - rv = self->list_start; - for (lf = 0; lf < tupleno; lf++) - rv = rv->next; - } - else - { - /* the closest way is starting from our lastref - pointer */ - rv = self->lastref; - - /* - * at first determine whether we have to search forward or - * backwards - */ - if (delta < 0) - { - /* we have to search backwards */ - for (lf = 0; lf < (-1) * delta; lf++) - rv = rv->prev; - } - else - { - /* ok, we have to search forward... */ - for (lf = 0; lf < delta; lf++) - rv = rv->next; - } - } - - /* - * now we have got our return pointer, so update the lastref and the - * last_indexed values - */ - self->lastref = rv; - self->last_indexed = tupleno; - - return rv->tuple[fieldno].value; -} - - -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 - */ - - new_field->prev = NULL; - new_field->next = NULL; - - if (self->list_start == NULL) - { - /* the list is empty, we have to add the first tuple */ - self->list_start = new_field; - self->list_end = new_field; - self->lastref = new_field; - self->last_indexed = 0; - } - else - { - /* - * there is already an element in the list, so add the new one at - * the end of the list - */ - self->list_end->next = new_field; - new_field->prev = self->list_end; - self->list_end = new_field; - } - self->num_tuples++; - - /* this method of building a list cannot fail, so we return 1 */ - return 1; -} diff --git a/src/interfaces/odbc/windev/tuplelist.h b/src/interfaces/odbc/windev/tuplelist.h deleted file mode 100644 index 3dc98dd78f..0000000000 --- a/src/interfaces/odbc/windev/tuplelist.h +++ /dev/null @@ -1,35 +0,0 @@ -/* File: tuplelist.h - * - * Description: See "tuplelist.c" - * - * Important Note: This structure and its functions are ONLY used in building manual result - * sets for info functions (SQLTables, SQLColumns, etc.) - * - * Comments: See "notice.txt" for copyright and license information. - * - */ - -#ifndef __TUPLELIST_H__ -#define __TUPLELIST_H__ - -#include "psqlodbc.h" - -struct TupleListClass_ -{ - Int4 num_fields; - Int4 num_tuples; - TupleNode *list_start, - *list_end, - *lastref; - Int4 last_indexed; -}; - -#define TL_get_num_tuples(x) (x->num_tuples) - -/* Create a TupleList. Each tuple consits of fieldcnt columns */ -TupleListClass *TL_Constructor(UInt4 fieldcnt); -void TL_Destructor(TupleListClass *self); -void *TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno); -char TL_add_tuple(TupleListClass *self, TupleNode *new_field); - -#endif diff --git a/src/interfaces/odbc/windev/win32.mak b/src/interfaces/odbc/windev/win32.mak deleted file mode 100644 index 1d92eec1bb..0000000000 --- a/src/interfaces/odbc/windev/win32.mak +++ /dev/null @@ -1,507 +0,0 @@ - -# -# File: win32.mak -# -# Description: psqlodbc Makefile for Win32. -# -# Configurations: Debug, Release, MultibyteDebug, MultibyteRelease -# Build Types: ALL, CLEAN -# Usage: NMAKE /f win32.mak CFG=[Release | Debug | MultibyteRelease | MultiByteDebug] [ALL | CLEAN] -# -# Comments: Created by Dave Page, 2001-02-12 -# - -!MESSAGE Building the PostgreSQL ODBC Driver for Win32... -!MESSAGE -!IF "$(CFG)" == "" -CFG=Release -!MESSAGE No configuration specified. Defaulting to Release. -!MESSAGE -!ENDIF - -!IF "$(CFG)" != "Release" && "$(CFG)" != "Debug" && "$(CFG)" != "MultibyteRelease" && "$(CFG)" != "MultibyteDebug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f win32.mak CFG=[Release | Debug | MultibyteRelease | MultiByteDebug] [ALL | CLEAN] -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Release" (Win32 Release DLL) -!MESSAGE "Debug" (Win32 Debug DLL) -!MESSAGE "MultibyteRelease" (Win32 Release DLL with Multibyte support) -!MESSAGE "MultibyteDebug" (Win32 Release DLL with Multibyte support) -!MESSAGE -!ERROR An invalid configuration was specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -!IF "$(CFG)" == "Release" || "$(CFG)" == "MultibyteRelease" - -!IF "$(CFG)" == "MultibyteRelease" -OUTDIR=.\MultibyteRelease -INTDIR=.\MultibyteRelease -!ELSE -OUTDIR=.\Release -INTDIR=.\Release -!ENDIF - -ALL : "$(OUTDIR)\psqlodbc.dll" - - -CLEAN : - -@erase "$(INTDIR)\bind.obj" - -@erase "$(INTDIR)\columninfo.obj" - -@erase "$(INTDIR)\connection.obj" - -@erase "$(INTDIR)\convert.obj" - -@erase "$(INTDIR)\dlg_specific.obj" - -@erase "$(INTDIR)\drvconn.obj" - -@erase "$(INTDIR)\environ.obj" - -@erase "$(INTDIR)\execute.obj" - -@erase "$(INTDIR)\gpps.obj" - -@erase "$(INTDIR)\info.obj" - -@erase "$(INTDIR)\lobj.obj" - -@erase "$(INTDIR)\win_md5.obj" - -@erase "$(INTDIR)\misc.obj" -!IF "$(CFG)" == "MultibyteRelease" - -@erase "$(INTDIR)\multibyte.obj" -!ENDIF - -@erase "$(INTDIR)\options.obj" - -@erase "$(INTDIR)\parse.obj" - -@erase "$(INTDIR)\pgtypes.obj" - -@erase "$(INTDIR)\psqlodbc.obj" - -@erase "$(INTDIR)\psqlodbc.res" - -@erase "$(INTDIR)\qresult.obj" - -@erase "$(INTDIR)\results.obj" - -@erase "$(INTDIR)\setup.obj" - -@erase "$(INTDIR)\socket.obj" - -@erase "$(INTDIR)\statement.obj" - -@erase "$(INTDIR)\tuple.obj" - -@erase "$(INTDIR)\tuplelist.obj" - -@erase "$(INTDIR)\odbcapi.obj" - -@erase "$(INTDIR)\vc60.idb" - -@erase "$(OUTDIR)\psqlodbc.dll" - -@erase "$(OUTDIR)\psqlodbc.exp" - -@erase "$(OUTDIR)\psqlodbc.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -!IF "$(CFG)" == "MultibyteRelease" -CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "MULTIBYTE" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ELSE -CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c -!ENDIF - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" -DEF_FILE= "psqlodbc_win32.def" -LINK32_OBJS= \ - "$(INTDIR)\bind.obj" \ - "$(INTDIR)\columninfo.obj" \ - "$(INTDIR)\connection.obj" \ - "$(INTDIR)\convert.obj" \ - "$(INTDIR)\dlg_specific.obj" \ - "$(INTDIR)\drvconn.obj" \ - "$(INTDIR)\environ.obj" \ - "$(INTDIR)\execute.obj" \ - "$(INTDIR)\gpps.obj" \ - "$(INTDIR)\info.obj" \ - "$(INTDIR)\lobj.obj" \ - "$(INTDIR)\win_md5.obj" \ - "$(INTDIR)\misc.obj" \ -!IF "$(CFG)" == "MultibyteRelease" - "$(INTDIR)\multibyte.obj" \ -!ENDIF - "$(INTDIR)\options.obj" \ - "$(INTDIR)\parse.obj" \ - "$(INTDIR)\pgtypes.obj" \ - "$(INTDIR)\psqlodbc.obj" \ - "$(INTDIR)\qresult.obj" \ - "$(INTDIR)\results.obj" \ - "$(INTDIR)\setup.obj" \ - "$(INTDIR)\socket.obj" \ - "$(INTDIR)\statement.obj" \ - "$(INTDIR)\tuple.obj" \ - "$(INTDIR)\tuplelist.obj" \ - "$(INTDIR)\odbcapi.obj" \ - "$(INTDIR)\psqlodbc.res" - -"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Debug" || "$(CFG)" == "MultibyteDebug" - -!IF "$(CFG)" == "MultibyteDebug" -OUTDIR=.\MultibyteDebug -INTDIR=.\MultibyteDebug -!ELSE -OUTDIR=.\Debug -INTDIR=.\Debug -!ENDIF - -ALL : "$(OUTDIR)\psqlodbc.dll" - - -CLEAN : - -@erase "$(INTDIR)\bind.obj" - -@erase "$(INTDIR)\columninfo.obj" - -@erase "$(INTDIR)\connection.obj" - -@erase "$(INTDIR)\convert.obj" - -@erase "$(INTDIR)\dlg_specific.obj" - -@erase "$(INTDIR)\drvconn.obj" - -@erase "$(INTDIR)\environ.obj" - -@erase "$(INTDIR)\execute.obj" - -@erase "$(INTDIR)\gpps.obj" - -@erase "$(INTDIR)\info.obj" - -@erase "$(INTDIR)\lobj.obj" - -@erase "$(INTDIR)\win_md5.obj" - -@erase "$(INTDIR)\misc.obj" -!IF "$(CFG)" == "MultibyteDebug" - -@erase "$(INTDIR)\multibyte.obj" -!ENDIF - -@erase "$(INTDIR)\options.obj" - -@erase "$(INTDIR)\parse.obj" - -@erase "$(INTDIR)\pgtypes.obj" - -@erase "$(INTDIR)\psqlodbc.obj" - -@erase "$(INTDIR)\psqlodbc.res" - -@erase "$(INTDIR)\qresult.obj" - -@erase "$(INTDIR)\results.obj" - -@erase "$(INTDIR)\setup.obj" - -@erase "$(INTDIR)\socket.obj" - -@erase "$(INTDIR)\statement.obj" - -@erase "$(INTDIR)\tuple.obj" - -@erase "$(INTDIR)\tuplelist.obj" - -@erase "$(INTDIR)\odbcapi.obj" - -@erase "$(INTDIR)\vc60.idb" - -@erase "$(INTDIR)\vc60.pdb" - -@erase "$(OUTDIR)\psqlodbc.dll" - -@erase "$(OUTDIR)\psqlodbc.exp" - -@erase "$(OUTDIR)\psqlodbc.ilk" - -@erase "$(OUTDIR)\psqlodbc.lib" - -@erase "$(OUTDIR)\psqlodbc.pdb" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -!IF "$(CFG)" == "MultibyteDebug" -CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "MULTIBYTE" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c -!ELSE -CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c -!ENDIF - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.c{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cpp{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -.cxx{$(INTDIR)}.sbr:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -MTL=midl.exe -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC=rc.exe -RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" -BSC32=bscmake.exe -BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept -DEF_FILE= "psqlodbc_win32.def" -LINK32_OBJS= \ - "$(INTDIR)\bind.obj" \ - "$(INTDIR)\columninfo.obj" \ - "$(INTDIR)\connection.obj" \ - "$(INTDIR)\convert.obj" \ - "$(INTDIR)\dlg_specific.obj" \ - "$(INTDIR)\drvconn.obj" \ - "$(INTDIR)\environ.obj" \ - "$(INTDIR)\execute.obj" \ - "$(INTDIR)\gpps.obj" \ - "$(INTDIR)\info.obj" \ - "$(INTDIR)\lobj.obj" \ - "$(INTDIR)\win_md5.obj" - "$(INTDIR)\misc.obj" \ -!IF "$(CFG)" == "MultibyteDebug" - "$(INTDIR)\multibyte.obj" \ -!ENDIF - "$(INTDIR)\options.obj" \ - "$(INTDIR)\parse.obj" \ - "$(INTDIR)\pgtypes.obj" \ - "$(INTDIR)\psqlodbc.obj" \ - "$(INTDIR)\qresult.obj" \ - "$(INTDIR)\results.obj" \ - "$(INTDIR)\setup.obj" \ - "$(INTDIR)\socket.obj" \ - "$(INTDIR)\statement.obj" \ - "$(INTDIR)\tuple.obj" \ - "$(INTDIR)\tuplelist.obj" \ - "$(INTDIR)\odbcapi.obj" \ - "$(INTDIR)\psqlodbc.res" - -"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -!IF "$(CFG)" == "Release" || "$(CFG)" == "Debug" || "$(CFG)" == "MultibyteRelease" || "$(CFG)" == "MultibyteDebug" - -SOURCE=bind.c - -"$(INTDIR)\bind.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=columninfo.c - -"$(INTDIR)\columninfo.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=connection.c - -"$(INTDIR)\connection.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=convert.c - -"$(INTDIR)\convert.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=dlg_specific.c - -"$(INTDIR)\dlg_specific.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=drvconn.c - -"$(INTDIR)\drvconn.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=environ.c - -"$(INTDIR)\environ.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=execute.c - -"$(INTDIR)\execute.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=gpps.c - -"$(INTDIR)\gpps.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=info.c - -"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=lobj.c - -"$(INTDIR)\lobj.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=misc.c - -"$(INTDIR)\misc.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!IF "$(CFG)" == "MultibyteRelease" || "$(CFG)" == "MultibyteDebug" - -SOURCE=multibyte.c - -"$(INTDIR)\multibyte.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -!ENDIF - - -SOURCE=options.c - -"$(INTDIR)\options.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=parse.c - -"$(INTDIR)\parse.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=pgtypes.c - -"$(INTDIR)\pgtypes.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=psqlodbc.c - -"$(INTDIR)\psqlodbc.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=psqlodbc.rc - -!IF "$(CFG)" == "Release" -"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" $(SOURCE) -!ENDIF - -!IF "$(CFG)" == "MultibyteRelease" -"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE) -!ENDIF - -!IF "$(CFG)" == "Debug" -"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE) -!ENDIF - -!IF "$(CFG)" == "MultibyteDebug" -"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)" - $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" /d "MULTIBYTE" $(SOURCE) -!ENDIF - - -SOURCE=qresult.c - -"$(INTDIR)\qresult.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=results.c - -"$(INTDIR)\results.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=setup.c - -"$(INTDIR)\setup.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=socket.c - -"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=statement.c - -"$(INTDIR)\statement.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=tuple.c - -"$(INTDIR)\tuple.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=tuplelist.c - -"$(INTDIR)\tuplelist.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=win_md5.c - -"$(INTDIR)\win_md5.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -SOURCE=odbcapi.c - -"$(INTDIR)\odbcapi.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - - - -!ENDIF diff --git a/src/interfaces/odbc/windev/win_md5.c b/src/interfaces/odbc/windev/win_md5.c deleted file mode 100644 index 2a7c4014c7..0000000000 --- a/src/interfaces/odbc/windev/win_md5.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * win_md5.c - * Under Windows I don't love the following /D in makefiles. - inoue - */ -#define MD5_ODBC -#define FRONTEND - -/* - * md5.c is the exact copy of the src/backend/libpq/md5.c. - * - * psqlodbc driver stuff never refer(link) to other - * stuff directly. - * - */ -#include "md5.c"