summaryrefslogtreecommitdiff
path: root/src/interfaces
diff options
context:
space:
mode:
authorMarc G. Fournier2002-08-22 22:43:14 +0000
committerMarc G. Fournier2002-08-22 22:43:14 +0000
commit5a303f878ecd597c1524f7cb0b844d17cb9da266 (patch)
treeba28968f533df8a53f8759ee73b40efb9b44140a /src/interfaces
parent03a7625a3a1d7adb9a49295d7447a0e3d224845d (diff)
Remove all traces of the ODBC driver, which is now on GBorg as the psqlodbc
project ...
Diffstat (limited to 'src/interfaces')
-rw-r--r--src/interfaces/Makefile8
-rw-r--r--src/interfaces/odbc/GNUmakefile72
-rw-r--r--src/interfaces/odbc/bind.c638
-rw-r--r--src/interfaces/odbc/bind.h62
-rw-r--r--src/interfaces/odbc/columninfo.c191
-rw-r--r--src/interfaces/odbc/columninfo.h42
-rw-r--r--src/interfaces/odbc/connection.c2154
-rw-r--r--src/interfaces/odbc/connection.h359
-rw-r--r--src/interfaces/odbc/convert.c3578
-rw-r--r--src/interfaces/odbc/convert.h56
-rw-r--r--src/interfaces/odbc/descriptor.h104
-rw-r--r--src/interfaces/odbc/dlg_specific.c971
-rw-r--r--src/interfaces/odbc/dlg_specific.h200
-rw-r--r--src/interfaces/odbc/dlg_wingui.c523
-rw-r--r--src/interfaces/odbc/drvconn.c435
-rw-r--r--src/interfaces/odbc/environ.c661
-rw-r--r--src/interfaces/odbc/environ.h38
-rw-r--r--src/interfaces/odbc/execute.c1090
-rw-r--r--src/interfaces/odbc/gpps.c454
-rw-r--r--src/interfaces/odbc/gpps.h48
-rw-r--r--src/interfaces/odbc/info.c4509
-rw-r--r--src/interfaces/odbc/info30.c396
-rw-r--r--src/interfaces/odbc/iodbc.h68
-rw-r--r--src/interfaces/odbc/isql.h246
-rw-r--r--src/interfaces/odbc/isqlext.h1560
-rw-r--r--src/interfaces/odbc/license.txt962
-rw-r--r--src/interfaces/odbc/lobj.c186
-rw-r--r--src/interfaces/odbc/lobj.h47
-rw-r--r--src/interfaces/odbc/md5.c351
-rw-r--r--src/interfaces/odbc/md5.h49
-rw-r--r--src/interfaces/odbc/misc.c329
-rw-r--r--src/interfaces/odbc/misc.h107
-rw-r--r--src/interfaces/odbc/multibyte.c454
-rw-r--r--src/interfaces/odbc/multibyte.h90
-rw-r--r--src/interfaces/odbc/notice.txt38
-rw-r--r--src/interfaces/odbc/odbc.sql228
-rw-r--r--src/interfaces/odbc/odbcapi.c716
-rw-r--r--src/interfaces/odbc/odbcapi25w.c81
-rw-r--r--src/interfaces/odbc/odbcapi30.c550
-rw-r--r--src/interfaces/odbc/odbcapi30w.c282
-rwxr-xr-xsrc/interfaces/odbc/odbcapiw.c626
-rw-r--r--src/interfaces/odbc/odbcinst.ini3
-rw-r--r--src/interfaces/odbc/options.c728
-rw-r--r--src/interfaces/odbc/parse.c1229
-rw-r--r--src/interfaces/odbc/pgapi30.c1656
-rw-r--r--src/interfaces/odbc/pgapifunc.h294
-rw-r--r--src/interfaces/odbc/pgtypes.c1475
-rw-r--r--src/interfaces/odbc/pgtypes.h106
-rw-r--r--src/interfaces/odbc/psqlodbc.c132
-rw-r--r--src/interfaces/odbc/psqlodbc.h279
-rw-r--r--src/interfaces/odbc/psqlodbc.rc321
-rw-r--r--src/interfaces/odbc/psqlodbc.reg16
-rw-r--r--src/interfaces/odbc/psqlodbc30.reg16
-rw-r--r--src/interfaces/odbc/psqlodbc30w.reg16
-rwxr-xr-xsrc/interfaces/odbc/psqlodbc_api30.def82
-rw-r--r--src/interfaces/odbc/psqlodbc_api30w.def107
-rw-r--r--src/interfaces/odbc/psqlodbc_apiw.def84
-rw-r--r--src/interfaces/odbc/psqlodbc_win32.def60
-rw-r--r--src/interfaces/odbc/qresult.c846
-rw-r--r--src/interfaces/odbc/qresult.h146
-rw-r--r--src/interfaces/odbc/readme.txt84
-rw-r--r--src/interfaces/odbc/resource.h79
-rw-r--r--src/interfaces/odbc/results.c2999
-rw-r--r--src/interfaces/odbc/setup.c409
-rw-r--r--src/interfaces/odbc/setup.rul495
-rw-r--r--src/interfaces/odbc/socket.c354
-rw-r--r--src/interfaces/odbc/socket.h95
-rw-r--r--src/interfaces/odbc/statement.c1197
-rw-r--r--src/interfaces/odbc/statement.h248
-rw-r--r--src/interfaces/odbc/tuple.c66
-rw-r--r--src/interfaces/odbc/tuple.h72
-rw-r--r--src/interfaces/odbc/tuplelist.c216
-rw-r--r--src/interfaces/odbc/tuplelist.h35
-rw-r--r--src/interfaces/odbc/version.h16
-rw-r--r--src/interfaces/odbc/win32.mak511
-rwxr-xr-xsrc/interfaces/odbc/win32_30.mak537
-rw-r--r--src/interfaces/odbc/win32_30w.mak520
-rw-r--r--src/interfaces/odbc/win32w.mak478
-rw-r--r--src/interfaces/odbc/win_md5.c15
-rw-r--r--src/interfaces/odbc/win_setup.h27
-rw-r--r--src/interfaces/odbc/win_unicode.c149
81 files changed, 2 insertions, 39755 deletions
diff --git a/src/interfaces/Makefile b/src/interfaces/Makefile
index 8fa11e0aff9..113670bbebf 100644
--- a/src/interfaces/Makefile
+++ b/src/interfaces/Makefile
@@ -4,7 +4,7 @@
#
# Copyright (c) 1994, Regents of the University of California
#
-# $Header: /cvsroot/pgsql/src/interfaces/Makefile,v 1.46 2002/08/22 00:15:10 scrappy Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/Makefile,v 1.47 2002/08/22 22:43:11 scrappy Exp $
#
#-------------------------------------------------------------------------
@@ -14,11 +14,7 @@ include $(top_builddir)/src/Makefile.global
DIRS := libpq ecpg libpgeasy
-ALLDIRS := $(DIRS) odbc libpgtcl perl5 python jdbc
-
-ifeq ($(enable_odbc), yes)
-DIRS += odbc
-endif
+ALLDIRS := $(DIRS) libpgtcl perl5 python jdbc
ifeq ($(with_tcl), yes)
DIRS += libpgtcl
diff --git a/src/interfaces/odbc/GNUmakefile b/src/interfaces/odbc/GNUmakefile
deleted file mode 100644
index 8d62f9079a2..00000000000
--- a/src/interfaces/odbc/GNUmakefile
+++ /dev/null
@@ -1,72 +0,0 @@
-#-------------------------------------------------------------------------
-#
-# GNUMakefile for psqlodbc (Postgres ODBC driver)
-#
-# $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/GNUmakefile,v 1.23 2001/11/12 00:54:28 inoue Exp $
-#
-#-------------------------------------------------------------------------
-
-subdir = src/interfaces/odbc
-top_builddir = ../../..
-include $(top_builddir)/src/Makefile.global
-
-# Shared library parameters
-ifeq ($(with_unixodbc),yes)
-NAME = odbcpsql
-else
-NAME = psqlodbc
-endif
-SO_MAJOR_VERSION = 0
-SO_MINOR_VERSION = 27
-
-override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DMD5_ODBC
-
-
-OBJS = info.o bind.o columninfo.o connection.o convert.o drvconn.o \
- environ.o execute.o lobj.o md5.o misc.o options.o \
- pgtypes.o psqlodbc.o qresult.o results.o socket.o parse.o statement.o \
- tuple.o tuplelist.o dlg_specific.o odbcapi.o
-
-ifdef MULTIBYTE
-OBJS += multibyte.o
-endif
-
-SHLIB_LINK += $(filter -lm -lnsl -lsocket, $(LIBS))
-ifeq ($(with_unixodbc),yes)
-SHLIB_LINK += -lodbcinst
-endif
-ifeq ($(with_iodbc),yes)
-SHLIB_LINK += -liodbcinst
-endif
-ifeq ($(with_unixodbc)$(with_iodbc),nono)
-OBJS += gpps.o
-override CPPFLAGS += -DODBCINSTDIR='"$(odbcinst_ini_dir)"'
-endif
-
-all: all-lib odbc-drop.sql
-
-# Shared library stuff
-include $(top_srcdir)/src/Makefile.shlib
-
-# Symbols must be resolved to the version in the shared library because
-# the driver manager (e.g., iodbc) provides some symbols with the same
-# names and we don't want those. (This issue is probably ELF specific.)
-LINK.shared += $(shlib_symbolic)
-
-odbc-drop.sql: odbc.sql
- sed -n '/^CREATE OR REPLACE FUNCTION/s/CREATE OR REPLACE FUNCTION \([^ (][^ (]*([^)]*)\).*/DROP FUNCTION \1;/p' $< >$@
-
-install: all installdirs
- $(INSTALL_DATA) $(srcdir)/odbc.sql $(DESTDIR)$(datadir)/odbc.sql
- $(INSTALL_DATA) odbc-drop.sql $(DESTDIR)$(datadir)/odbc-drop.sql
- $(MAKE) install-lib
-
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(datadir)
-
-uninstall: uninstall-lib
- rm -f $(DESTDIR)$(datadir)/odbc.sql $(DESTDIR)$(datadir)/odbc-drop.sql
-
-clean distclean maintainer-clean: clean-lib
- rm -f $(OBJS)
- rm -f odbc-drop.sql
diff --git a/src/interfaces/odbc/bind.c b/src/interfaces/odbc/bind.c
deleted file mode 100644
index e6deedaa8b6..00000000000
--- a/src/interfaces/odbc/bind.c
+++ /dev/null
@@ -1,638 +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
- *
- * Comments: See "notice.txt" for copyright and license information.
- *-------
- */
-
-#include "bind.h"
-
-#include "environ.h"
-#include "statement.h"
-#include "descriptor.h"
-#include "qresult.h"
-#include "pgtypes.h"
-#include <stdlib.h>
-#include <string.h>
-
-#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";
- APDFields *opts;
-
- mylog("%s: entering...\n", func);
-
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
- SC_clear_error(stmt);
-
- opts = SC_get_APD(stmt);
- if (opts->allocated < ipar)
- extend_parameter_bindings(opts, ipar);
-
- /* use zero based column numbers for the below part */
- ipar--;
-
- /* store the given info */
- opts->parameters[ipar].buflen = cbValueMax;
- opts->parameters[ipar].buffer = rgbValue;
- opts->parameters[ipar].used = pcbValue;
- opts->parameters[ipar].paramType = fParamType;
- opts->parameters[ipar].CType = fCType;
- opts->parameters[ipar].SQLType = fSqlType;
- opts->parameters[ipar].column_size = cbColDef;
- opts->parameters[ipar].decimal_digits = ibScale;
- opts->parameters[ipar].precision = 0;
- opts->parameters[ipar].scale = 0;
-#if (ODBCVER >= 0x0300)
- switch (fCType)
- {
- case SQL_C_NUMERIC:
- if (cbColDef > 0)
- opts->parameters[ipar].precision = (UInt2) cbColDef;
- if (ibScale > 0)
- opts->parameters[ipar].scale = ibScale;
- break;
- case SQL_C_TYPE_TIMESTAMP:
- if (ibScale > 0)
- opts->parameters[ipar].precision = ibScale;
- break;
- }
-#endif /* ODBCVER */
-
- /*
- * If rebinding a parameter that had data-at-exec stuff in it, then
- * free that stuff
- */
- if (opts->parameters[ipar].EXEC_used)
- {
- free(opts->parameters[ipar].EXEC_used);
- opts->parameters[ipar].EXEC_used = NULL;
- }
-
- if (opts->parameters[ipar].EXEC_buffer)
- {
- if (opts->parameters[ipar].SQLType != SQL_LONGVARBINARY)
- free(opts->parameters[ipar].EXEC_buffer);
- opts->parameters[ipar].EXEC_buffer = NULL;
- }
-
- if (pcbValue && opts->param_offset_ptr)
- pcbValue += (*opts->param_offset_ptr >> 2);
- /* 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))
- opts->parameters[ipar].data_at_exec = TRUE;
- else
- opts->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, opts->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";
- ARDFields *opts;
-
- 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;
- }
-
-
-
- opts = SC_get_ARD(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;
- }
-
- SC_clear_error(stmt);
- /* If the bookmark column is being bound, then just save it */
- if (icol == 0)
- {
- if (rgbValue == NULL)
- {
- opts->bookmark->buffer = NULL;
- opts->bookmark->used = NULL;
- }
- else
- {
- /* Make sure it is the bookmark data type */
- if (fCType == SQL_C_BOOKMARK)
- switch (fCType)
- {
- case SQL_C_BOOKMARK:
-#if (ODBCVER >= 0x0300)
- case SQL_C_VARBOOKMARK:
-#endif /* ODBCVER */
- break;
- default:
- stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
-inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
- stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
-
- opts->bookmark->buffer = rgbValue;
- opts->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 > opts->allocated)
- extend_column_bindings(opts, icol);
-
- /* check to see if the bindings were allocated */
- if (!opts->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 */
- opts->bindings[icol].data_left = -1;
-
- if (rgbValue == NULL)
- {
- /* we have to unbind the column */
- opts->bindings[icol].buflen = 0;
- opts->bindings[icol].buffer = NULL;
- opts->bindings[icol].used = NULL;
- opts->bindings[icol].returntype = SQL_C_CHAR;
- if (opts->bindings[icol].ttlbuf)
- free(opts->bindings[icol].ttlbuf);
- opts->bindings[icol].ttlbuf = NULL;
- opts->bindings[icol].ttlbuflen = 0;
- opts->bindings[icol].precision = 0;
- opts->bindings[icol].scale = 0;
- }
- else
- {
- /* ok, bind that column */
- opts->bindings[icol].buflen = cbValueMax;
- opts->bindings[icol].buffer = rgbValue;
- opts->bindings[icol].used = pcbValue;
- opts->bindings[icol].returntype = fCType;
-#if (ODBCVER >= 0x0300)
- if (SQL_C_NUMERIC == fCType)
- opts->bindings[icol].precision = 32;
- else
-#endif /* ODBCVER */
- opts->bindings[icol].precision = 0;
- opts->bindings[icol].scale = 0;
-
- mylog(" bound buffer[%d] = %u\n", icol, opts->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";
- APDFields *opts;
-
- mylog("%s: entering...\n", func);
-
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
- SC_clear_error(stmt);
-
- opts = SC_get_APD(stmt);
- if ((ipar < 1) || (ipar > opts->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 = opts->parameters[ipar].SQLType;
-
- if (pcbColDef)
- *pcbColDef = opts->parameters[ipar].column_size;
-
- if (pibScale)
- *pibScale = opts->parameters[ipar].decimal_digits;
-
- if (pfNullable)
- *pfNullable = pgtype_nullable(stmt, opts->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;
- APDFields *opts;
-
- mylog("%s: entering... %d %x\n", func, crow, pirow);
-
- opts = SC_get_APD(stmt);
- opts->paramset_size = crow;
- SC_get_IPD(stmt)->param_processed_ptr = (UInt4 *) pirow;
- return SQL_SUCCESS;
-}
-
-
-/*
- * 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_parameter_bindings(APDFields *self, int num_params)
-{
- static char *func = "extend_parameter_bindings";
- ParameterInfoClass *new_bindings;
-
- mylog("%s: entering ... self=%u, parameters_allocated=%d, num_params=%d\n", func, self, self->allocated, num_params);
-
- /*
- * if we have too few, allocate room for more, and copy the old
- * entries into the new structure
- */
- if (self->allocated < num_params)
- {
- new_bindings = (ParameterInfoClass *) realloc(self->parameters, sizeof(ParameterInfoClass) * num_params);
- if (!new_bindings)
- {
- mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_params, self->allocated);
-
- self->parameters = NULL;
- self->allocated = 0;
- return;
- }
- memset(&new_bindings[self->allocated], 0,
- sizeof(ParameterInfoClass) * (num_params - self->allocated));
-
- self->parameters = new_bindings;
- self->allocated = num_params;
- }
-
- mylog("exit extend_parameter_bindings\n");
-}
-
-void
-reset_a_parameter_binding(APDFields *self, int ipar)
-{
- static char *func = "reset_a_parameter_binding";
-
- mylog("%s: entering ... self=%u, parameters_allocated=%d, ipar=%d\n", func, self, self->allocated, ipar);
-
- if (ipar < 1 || ipar > self->allocated)
- return;
-
- ipar--;
- self->parameters[ipar].buflen = 0;
- self->parameters[ipar].buffer = 0;
- self->parameters[ipar].used = 0;
- self->parameters[ipar].paramType = 0;
- self->parameters[ipar].CType = 0;
- if (self->parameters[ipar].EXEC_used)
- {
- free(self->parameters[ipar].EXEC_used);
- self->parameters[ipar].EXEC_used = NULL;
- }
-
- if (self->parameters[ipar].EXEC_buffer)
- {
- if (self->parameters[ipar].SQLType != SQL_LONGVARBINARY)
- free(self->parameters[ipar].EXEC_buffer);
- self->parameters[ipar].EXEC_buffer = NULL;
- }
- self->parameters[ipar].SQLType = 0;
- self->parameters[ipar].column_size = 0;
- self->parameters[ipar].decimal_digits = 0;
- self->parameters[ipar].precision = 0;
- self->parameters[ipar].scale = 0;
- self->parameters[ipar].data_at_exec = FALSE;
- self->parameters[ipar].lobj_oid = 0;
-}
-
-/*
- * Free parameters and free the memory.
- */
-void
-APD_free_params(APDFields *self, char option)
-{
- int i;
-
- mylog("APD_free_params: ENTER, self=%d\n", self);
-
- if (!self->parameters)
- return;
-
- for (i = 0; i < self->allocated; i++)
- {
- if (self->parameters[i].data_at_exec)
- {
- 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;
- }
- }
- }
-
- if (option == STMT_FREE_PARAMS_ALL)
- {
- if (self->parameters);
- free(self->parameters);
- self->parameters = NULL;
- self->allocated = 0;
- }
-
- mylog("APD_free_params: EXIT\n");
-}
-
-void
-extend_column_bindings(ARDFields *self, int num_columns)
-{
- static char *func = "extend_column_bindings";
- BindInfoClass *new_bindings;
- int i;
-
- mylog("%s: entering ... self=%u, bindings_allocated=%d, num_columns=%d\n", func, self, self->allocated, num_columns);
-
- /*
- * if we have too few, allocate room for more, and copy the old
- * entries into the new structure
- */
- if (self->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, self->allocated);
-
- if (self->bindings)
- {
- free(self->bindings);
- self->bindings = NULL;
- }
- self->allocated = 0;
- return;
- }
-
- if (self->bindings)
- {
- for (i = 0; i < self->allocated; i++)
- new_bindings[i] = self->bindings[i];
-
- free(self->bindings);
- }
-
- self->bindings = new_bindings;
- self->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_column_bindings\n");
-}
-
-void
-reset_a_column_binding(ARDFields *self, int icol)
-{
- static char *func = "reset_a_column_binding";
-
- mylog("%s: entering ... self=%u, bindings_allocated=%d, icol=%d\n", func, self, self->allocated, icol);
-
- if (icol > self->allocated)
- return;
-
- /* use zero based col numbers from here out */
- if (0 == icol)
- {
- self->bookmark->buffer = NULL;
- self->bookmark->used = NULL;
- }
- else
- {
- icol--;
-
- /* we have to unbind the column */
- self->bindings[icol].buflen = 0;
- self->bindings[icol].buffer = NULL;
- self->bindings[icol].used = NULL;
- self->bindings[icol].data_left = -1;
- self->bindings[icol].returntype = SQL_C_CHAR;
- if (self->bindings[icol].ttlbuf)
- free(self->bindings[icol].ttlbuf);
- self->bindings[icol].ttlbuf = NULL;
- self->bindings[icol].ttlbuflen = 0;
- }
-}
-
-void ARD_unbind_cols(ARDFields *self, BOOL freeall)
-{
- Int2 lf;
-
- for (lf = 1; lf <= self->allocated; lf++)
- reset_a_column_binding(self, lf);
- if (freeall)
- {
- if (self->bindings)
- free(self->bindings);
- self->bindings = NULL;
- self->allocated = 0;
- }
-}
diff --git a/src/interfaces/odbc/bind.h b/src/interfaces/odbc/bind.h
deleted file mode 100644
index f2467c7713a..00000000000
--- a/src/interfaces/odbc/bind.h
+++ /dev/null
@@ -1,62 +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...) */
- Int2 precision; /* the precision for numeric or timestamp type */
- Int2 scale; /* the scale for numeric type */
-};
-
-/*
- * ParameterInfoClass -- stores information about a bound parameter
- */
-struct ParameterInfoClass_
-{
- Int4 buflen;
- char *buffer;
- Int4 *used;
- Int2 paramType;
- Int2 CType;
- Int2 SQLType;
- Int2 decimal_digits;
- UInt4 column_size;
- 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 */
- Int2 precision; /* the precision for numeric or timestamp type */
- Int2 scale; /* the scale for numeric type */
- char data_at_exec;
-};
-
-BindInfoClass *create_empty_bindings(int num_columns);
-void extend_column_bindings(ARDFields *opts, int num_columns);
-void reset_a_column_binding(ARDFields *opts, int icol);
-void extend_parameter_bindings(APDFields *opts, int num_columns);
-void reset_a_parameter_binding(APDFields *opts, int ipar);
-
-#endif
diff --git a/src/interfaces/odbc/columninfo.c b/src/interfaces/odbc/columninfo.c
deleted file mode 100644
index 7fe72d3f6d1..00000000000
--- a/src/interfaces/odbc/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 <stdlib.h>
-#include <string.h>
-#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/columninfo.h b/src/interfaces/odbc/columninfo.h
deleted file mode 100644
index 41e9400dcea..00000000000
--- a/src/interfaces/odbc/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/connection.c b/src/interfaces/odbc/connection.c
deleted file mode 100644
index e3c0563ec2d..00000000000
--- a/src/interfaces/odbc/connection.c
+++ /dev/null
@@ -1,2154 +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 <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#ifndef WIN32
-#include <errno.h>
-#endif /* WIN32 */
-
-#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;
- }
-
- if (phdbc)
- *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 */
- memcpy(&ci->drivers, &globals, sizeof(globals));
- 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, AUTH_REQ_OK, NULL) <= 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;
-}
-
-
-void
-CC_conninfo_init(ConnInfo *conninfo)
-{
- memset(conninfo, 0, sizeof(ConnInfo));
- conninfo->disallow_premature = -1;
- conninfo->allow_keyset = -1;
- conninfo->lf_conversion = -1;
- conninfo->true_is_minus1 = -1;
- conninfo->int8_as = -101;
- memcpy(&(conninfo->drivers), &globals, sizeof(globals));
-}
-/*
- * 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 */
-
- CC_conninfo_init(&(rv->connInfo));
- 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;
- rv->unicode = 0;
- rv->result_uncommitted = 0;
- rv->schema_support = 0;
- rv->isolation = SQL_TXN_READ_COMMITTED;
-#ifdef MULTIBYTE
- rv->client_encoding = NULL;
- rv->server_encoding = NULL;
-#endif /* MULTIBYTE */
- rv->current_schema = NULL;
-
-
- /* Initialize statement options to defaults */
- /* Statements under this conn will inherit these options */
-
- InitializeStatementOptions(&rv->stmtOptions);
- InitializeARDFields(&rv->ardOptions);
- InitializeAPDFields(&rv->apdOptions);
- }
- 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");
-
- /* Free up statement holders */
- if (self->stmts)
- {
- free(self->stmts);
- self->stmts = NULL;
- }
- mylog("after free statement holders\n");
-
- 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 && SC_get_Result(stmt) && SC_get_Result(stmt)->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 begin a transaction.
- */
-char
-CC_begin(ConnectionClass *self)
-{
- char ret = TRUE;
- if (!CC_is_in_trans(self))
- {
- QResultClass *res = CC_send_query(self, "BEGIN", NULL, CLEAR_RESULT_ON_ABORT);
- mylog("CC_begin: sending BEGIN!\n");
-
- if (res != NULL)
- {
- ret = QR_command_maybe_successful(res);
- QR_Destructor(res);
- }
- else
- return FALSE;
- }
-
- return ret;
-}
-
-/*
- * Used to commit a transaction.
- * We are almost always in the middle of a transaction.
- */
-char
-CC_commit(ConnectionClass *self)
-{
- char ret = FALSE;
- if (CC_is_in_trans(self))
- {
- QResultClass *res = CC_send_query(self, "COMMIT", NULL, CLEAR_RESULT_ON_ABORT);
- mylog("CC_commit: sending COMMIT!\n");
- if (res != NULL)
- {
- ret = QR_command_maybe_successful(res);
- QR_Destructor(res);
- }
- else
- return FALSE;
- }
-
- return ret;
-}
-
-/*
- * Used to cancel a transaction.
- * We are almost always in the middle of a transaction.
- */
-char
-CC_abort(ConnectionClass *self)
-{
- if (CC_is_in_trans(self))
- {
- QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, CLEAR_RESULT_ON_ABORT);
- mylog("CC_abort: sending ABORT!\n");
- 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
-
- self->status = CONN_NOT_CONNECTED;
- self->transact_status = CONN_IN_AUTOCOMMIT;
- CC_conninfo_init(&(self->connInfo));
-#ifdef MULTIBYTE
- if (self->client_encoding)
- free(self->client_encoding);
- self->client_encoding = NULL;
- if (self->server_encoding)
- free(self->server_encoding);
- self->server_encoding = NULL;
-#endif /* MULTIBYTE */
- if (self->current_schema)
- free(self->current_schema);
- self->current_schema = NULL;
- /* 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);
-
- if (self->col_info[i]->schema)
- free(self->col_info[i]->schema);
- free(self->col_info[i]);
- }
- free(self->col_info);
- self->col_info = NULL;
- }
- self->ntables = 0;
- 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;
-
- 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 password_req, char *salt_para)
-{
- StartupPacket sp;
- StartupPacket6_2 sp62;
- QResultClass *res;
- SocketClass *sock;
- ConnInfo *ci = &(self->connInfo);
- int areq = -1;
- int beresp;
- static char msgbuffer[ERROR_MSG_LENGTH];
- char salt[5], notice[512];
- static char *func = "CC_connect";
-
-#ifdef MULTIBYTE
- char *encoding;
-#endif /* MULTIBYTE */
-
- mylog("%s: entering...\n", func);
-
- if (password_req != AUTH_REQ_OK)
-
- 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 NAMEDATALEN=%d\n",
- ci->drivers.text_as_longvarchar,
- ci->drivers.unknowns_as_longvarchar,
- ci->drivers.bools_as_char,
- MAX_TABLE_LEN);
-
-#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);
- }
- if (self->client_encoding)
- self->ccsc = pg_CS_code(self->client_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, USRNAMEDATALEN);
- 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 (password_req != AUTH_REQ_OK)
- 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 (password_req != AUTH_REQ_OK)
- {
- mylog("in 'R' password_req=%s\n", ci->password);
- areq = password_req;
- if (salt_para)
- memcpy(salt, salt_para, sizeof(salt));
- password_req = AUTH_REQ_OK;
- }
- else
- {
-
- areq = SOCK_get_int(sock, 4);
- if (areq == AUTH_REQ_MD5)
- SOCK_get_n_char(sock, salt, 4);
- else 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 -areq; /* 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.";
- if (salt_para)
- memcpy(salt_para, salt, sizeof(salt));
- return -areq; /* 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) */
- self->be_pid = SOCK_get_int(sock, 4); /* pid */
- self->be_key = SOCK_get_int(sock, 4); /* key */
-
- break;
- case 'Z': /* Backend is ready for new query (6.4) */
- ReadyForQuery = TRUE;
- break;
- case 'N': /* Notices may come */
- while (SOCK_get_string(sock, notice, sizeof(notice) - 1)) ;
- 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, CLEAR_RESULT_ON_ABORT);
- 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
- */
-
- /*
- * Get the version number first so we can check it before sending options
- * that are now obsolete. DJP 21/06/2002
- */
-
- CC_lookup_pg_version(self); /* Get PostgreSQL version for
- SQLGetInfo use */
- /*
- * 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 */
-
- /*
- * Multibyte handling is available ?
- */
-#ifdef MULTIBYTE
- if (PG_VERSION_GE(self, 6.4))
- {
- CC_lookup_characterset(self);
- if (self->errornumber != 0)
- return 0;
-#ifdef UNICODE_SUPPORT
- if (self->unicode)
- {
- if (!self->client_encoding ||
- stricmp(self->client_encoding, "UNICODE"))
- {
- QResultClass *res;
- if (PG_VERSION_LT(self, 7.1))
- {
- self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
- self->errormsg = "UTF-8 conversion isn't implemented before 7.1";
- return 0;
- }
- if (self->client_encoding)
- free(self->client_encoding);
- self->client_encoding = NULL;
- if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, CLEAR_RESULT_ON_ABORT), res)
- {
- self->client_encoding = strdup("UNICODE");
- self->ccsc = pg_CS_code(self->client_encoding);
- QR_Destructor(res);
-
- }
- }
- }
-#else
- {
- }
-#endif /* UNICODE_SUPPORT */
- }
-#ifdef UNICODE_SUPPORT
- else if (self->unicode)
- {
- self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
- self->errormsg = "Unicode isn't supported before 6.4";
- return 0;
- }
-#endif /* UNICODE_SUPPORT */
-#endif /* MULTIBYTE */
- ci->updatable_cursors = 0;
-#ifdef DRIVER_CURSOR_IMPLEMENT
- if (!ci->drivers.use_declarefetch &&
- PG_VERSION_GE(self, 7.0)) /* Tid scan since 7.0 */
- ci->updatable_cursors = ci->allow_keyset;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-
- 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;
-}
-
-
-void CC_on_commit(ConnectionClass *conn)
-{
- if (CC_is_in_trans(conn))
- {
-#ifdef DRIVER_CURSOR_IMPLEMENT
- if (conn->result_uncommitted)
- ProcessRollback(conn, FALSE);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- CC_set_no_trans(conn);
- }
- conn->result_uncommitted = 0;
-}
-void CC_on_abort(ConnectionClass *conn, UDWORD opt)
-{
- if (CC_is_in_trans(conn))
- {
-#ifdef DRIVER_CURSOR_IMPLEMENT
- if (conn->result_uncommitted)
- ProcessRollback(conn, TRUE);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- if (0 != (opt & NO_TRANS))
- CC_set_no_trans(conn);
- }
- if (0 != (opt & CONN_DEAD))
- conn->status = CONN_DOWN;
- conn->result_uncommitted = 0;
-}
-
-/*
- * 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, UDWORD flag)
-{
- QResultClass *cmdres = NULL,
- *retres = NULL,
- *res = NULL;
- BOOL clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
- create_keyset = ((flag & CREATE_KEYSET) != 0),
- issue_begin = ((flag & GO_INTO_TRANSACTION) != 0 && !CC_is_in_trans(self));
- char swallow, *wq, *ptr;
- int id;
- SocketClass *sock = self->sock;
- int maxlen,
- empty_reqs;
- BOOL msg_truncated,
- ReadyToReturn,
- query_completed = FALSE,
- before_64 = PG_VERSION_LT(self, 6.4),
- aborted = FALSE,
- used_passed_result_object = FALSE;
- UDWORD abort_opt;
-
- /* 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_on_abort(self, NO_TRANS | CONN_DEAD);
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
- return NULL;
- }
-
- if (issue_begin)
- SOCK_put_n_char(sock, "begin;", 6);
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
- 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;
- cmdres = qi ? qi->result_in : NULL;
- if (cmdres)
- used_passed_result_object = TRUE;
- else
- {
- cmdres = QR_Constructor();
- if (!cmdres)
- {
- self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
- self->errormsg = "Could not create result info in send_query.";
- return NULL;
- }
- }
- res = cmdres;
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
- ReadyToReturn = TRUE;
- retres = NULL;
- }
- else
- {
- mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
-
- if (query_completed) /* allow for "show" style notices */
- {
- res->next = QR_Constructor();
- res = res->next;
- }
-
- mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
-
- if (strnicmp(cmdbuffer, "BEGIN", 5) == 0)
- {
- CC_set_in_trans(self);
- if (issue_begin)
- {
- issue_begin = FALSE;
- continue;
- }
- }
- else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
- CC_on_commit(self);
- else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
- CC_on_abort(self, NO_TRANS);
- else if (strnicmp(cmdbuffer, "END", 3) == 0)
- CC_on_commit(self);
- else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
- CC_on_abort(self, NO_TRANS);
- else
- {
- trim(cmdbuffer); /* get rid of trailing space */
- ptr = strrchr(cmdbuffer, ' ');
- if (ptr)
- res->recent_processed_row_count = atoi(ptr + 1);
- else
- res->recent_processed_row_count = -1;
- }
-
- 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 (aborted || query_completed)
- retres = cmdres;
- else
- ReadyToReturn = FALSE;
- }
- break;
- case 'N': /* NOTICE: */
- msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
- 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 ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
- {
- self->errornumber = CONNECTION_BACKEND_CRAZY;
- QR_set_message(res, "Unexpected protocol character from backend (send_query - I)");
- QR_set_status(res, PGRES_FATAL_ERROR);
- ReadyToReturn = TRUE;
- retres = cmdres;
- 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';
-
-
- mylog("send_query: 'E' - %s\n", msgbuffer);
- qlog("ERROR from backend during send_query: '%s'\n", msgbuffer);
-
- /* We should report that an error occured. Zoltan */
- abort_opt = 0;
- if (!strncmp(msgbuffer, "FATAL", 5))
- {
- self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
- abort_opt = NO_TRANS | CONN_DEAD;
- }
- else
- self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
- CC_on_abort(self, abort_opt);
- QR_set_status(res, PGRES_FATAL_ERROR);
- QR_set_message(res, msgbuffer);
- QR_set_aborted(res, TRUE);
- aborted = 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 */
- if (query_completed)
- {
- res->next = QR_Constructor();
- if (!res->next)
- {
- self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
- self->errormsg = "Could not create result info in send_query.";
- ReadyToReturn = TRUE;
- retres = NULL;
- break;
- }
- if (create_keyset)
- QR_set_haskeyset(res->next);
- mylog("send_query: 'T' no result_in: res = %u\n", res->next);
- res = res->next;
-
- if (qi)
- QR_set_cache_size(res, qi->row_size);
- }
- if (!used_passed_result_object)
- {
- if (create_keyset)
- QR_set_haskeyset(res);
- if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
- {
- self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
- self->errormsg = QR_get_message(res);
- ReadyToReturn = TRUE;
- if (PGRES_FATAL_ERROR == QR_get_status(res))
- retres = cmdres;
- else
- retres = NULL;
- break;
- }
- query_completed = TRUE;
- }
- else
- { /* next fetch, so reuse an existing result */
-
- /*
- * called from QR_next_tuple and must return
- * immediately.
- */
- ReadyToReturn = TRUE;
- if (!QR_fetch_tuples(res, NULL, NULL))
- {
- self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
- self->errormsg = QR_get_message(res);
- retres = NULL;
- break;
- }
- retres = cmdres;
- }
- break;
- case 'D': /* Copy in command began successfully */
- if (query_completed)
- {
- res->next = QR_Constructor();
- res = res->next;
- }
- QR_set_status(res, PGRES_COPY_IN);
- ReadyToReturn = TRUE;
- retres = cmdres;
- break;
- case 'B': /* Copy out command began successfully */
- if (query_completed)
- {
- res->next = QR_Constructor();
- res = res->next;
- }
- QR_set_status(res, PGRES_COPY_OUT);
- ReadyToReturn = TRUE;
- retres = cmdres;
- break;
- default:
- self->errornumber = CONNECTION_BACKEND_CRAZY;
- self->errormsg = "Unexpected protocol character from backend (send_query)";
- CC_on_abort(self, NO_TRANS | CONN_DEAD);
-
- 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)
- break;
- }
- }
-
- /*
- * Break before being ready to return.
- */
- if (!ReadyToReturn)
- retres = cmdres;
-
- /*
- * Cleanup garbage results before returning.
- */
- if (cmdres && retres != cmdres && !used_passed_result_object)
- QR_Destructor(cmdres);
- /*
- * Cleanup the aborted result if specified
- */
- if (retres)
- {
- if (aborted)
- {
- if (clear_result_on_abort)
- {
- if (!used_passed_result_object)
- {
- QR_Destructor(retres);
- retres = NULL;
- }
- }
- if (retres)
- {
- /*
- * discard results other than errors.
- */
- QResultClass *qres;
- for (qres = retres; qres->next; qres = retres)
- {
- if (QR_get_aborted(qres))
- break;
- retres = qres->next;
- qres->next = NULL;
- QR_Destructor(qres);
- }
- /*
- * If error message isn't set
- */
- if (retres && (!self->errormsg || !self->errormsg[0]))
- self->errormsg = QR_get_message(retres);
- }
- }
- }
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
- 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;
- CC_on_abort(self, 0);
-
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
-
- 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;
- CC_on_abort(self, 0);
- 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_on_abort(self, NO_TRANS | CONN_DEAD);
-
- 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 (not applicable to 7.1+ - DJP 21/06/2002) */
- if (ci->drivers.ksqo && PG_VERSION_LT(self, 7.1))
- {
- 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);
- if (PG_VERSION_GE(self, 7.3))
- self->schema_support = 1;
-
- 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(const char *func, const char *desc, const 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);
- mylog("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;
-}
-
-/*
- * This deosn't really return the CURRENT SCHEMA
- * but there's no alternative.
- */
-const char *
-CC_get_current_schema(ConnectionClass *conn)
-{
- if (!conn->current_schema && conn->schema_support)
- {
- QResultClass *res;
-
- if (res = CC_send_query(conn, "select current_schema()", NULL, CLEAR_RESULT_ON_ABORT), res)
- {
- if (QR_get_num_total_tuples(res) == 1)
- conn->current_schema = strdup(QR_get_value_backend_row(res, 0, 0));
- QR_Destructor(res);
- }
- }
- return (const char *) conn->current_schema;
-}
-
-int
-CC_send_cancel_request(const ConnectionClass *conn)
-{
-#ifdef WIN32
- int save_errno = (WSAGetLastError());
-#else
- int save_errno = errno;
-#endif
- int tmpsock = -1;
- struct
- {
- uint32 packetlen;
- CancelRequestPacket cp;
- } crp;
-
- /* Check we have an open connection */
- if (!conn)
- return FALSE;
-
- if (conn->sock == NULL )
- {
- return FALSE;
- }
-
- /*
- * We need to open a temporary connection to the postmaster. Use the
- * information saved by connectDB to do this with only kernel calls.
- */
- if ((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- {
- return FALSE;
- }
- if (connect(tmpsock, (struct sockaddr *)&(conn->sock->sadr),
- sizeof(conn->sock->sadr)) < 0)
- {
- return FALSE;
- }
-
- /*
- * We needn't set nonblocking I/O or NODELAY options here.
- */
- crp.packetlen = htonl((uint32) sizeof(crp));
- crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
- crp.cp.backendPID = htonl(conn->be_pid);
- crp.cp.cancelAuthCode = htonl(conn->be_key);
-
- if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
- {
- return FALSE;
- }
-
- /* Sent it, done */
- closesocket(tmpsock);
-#ifdef WIN32
- WSASetLastError(save_errno);
-#else
- errno = save_errno;
-#endif
- return TRUE;
-}
diff --git a/src/interfaces/odbc/connection.h b/src/interfaces/odbc/connection.h
deleted file mode 100644
index 133b4920c00..00000000000
--- a/src/interfaces/odbc/connection.h
+++ /dev/null
@@ -1,359 +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 <stdlib.h>
-#include <string.h>
-#include "descriptor.h"
-
-
-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 USRNAMEDATALEN 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[USRNAMEDATALEN];
- char options[ARGV_SIZE];
- char execfile[ARGV_SIZE];
- char tty[PATH_SIZE];
-} StartupPacket6_2;
-
-/* Transferred from pqcomm.h: */
-
-
-typedef ProtocolVersion MsgType;
-
-#define PG_PROTOCOL(m,n) (((m) << 16) | (n))
-#define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
-
-typedef struct CancelRequestPacket
-{
- /* Note that each field is stored in network byte order! */
- MsgType cancelRequestCode; /* code to identify a cancel request */
- unsigned int backendPID; /* PID of client's backend */
- unsigned int cancelAuthCode; /* secret key to authorize cancel */
-} CancelRequestPacket;
-
-/* 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 allow_keyset;
- char updatable_cursors;
- char lf_conversion;
- char true_is_minus1;
- char int8_as;
- 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 *schema;
- 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;
- ARDFields ardOptions;
- APDFields apdOptions;
- 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;
- char unicode;
- char result_uncommitted;
- char schema_support;
-#ifdef MULTIBYTE
- char *client_encoding;
- char *server_encoding;
-#endif /* MULTIBYTE */
- int ccsc;
- int be_pid; /* pid returned by backend */
- int be_key; /* auth code needed to send cancel */
- UInt4 isolation;
- char *current_schema;
-};
-
-
-/* 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);
-void CC_conninfo_init(ConnInfo *conninfo);
-char CC_Destructor(ConnectionClass *self);
-int CC_cursor_count(ConnectionClass *self);
-char CC_cleanup(ConnectionClass *self);
-char CC_begin(ConnectionClass *self);
-char CC_commit(ConnectionClass *self);
-char CC_abort(ConnectionClass *self);
-int CC_set_translation(ConnectionClass *self);
-char CC_connect(ConnectionClass *self, char password_req, char *salt);
-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, UDWORD flag);
-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(const char *func, const char *desc, const ConnectionClass *self);
-int CC_get_max_query_len(const ConnectionClass *self);
-int CC_send_cancel_request(const ConnectionClass *conn);
-void CC_on_commit(ConnectionClass *conn);
-void CC_on_abort(ConnectionClass *conn, UDWORD opt);
-void ProcessRollback(ConnectionClass *conn, BOOL undo);
-const char *CC_get_current_schema(ConnectionClass *conn);
-
-/* CC_send_query options */
-#define CLEAR_RESULT_ON_ABORT 1L
-#define CREATE_KEYSET (1L << 1) /* create keyset for updatable curosrs */
-#define GO_INTO_TRANSACTION (1L << 2) /* issue begin in advance */
-/* CC_on_abort options */
-#define NO_TRANS 1L
-#define CONN_DEAD (1L << 1) /* connection is no longer valid */
-
-#endif /* __CONNECTION_H__ */
diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c
deleted file mode 100644
index 2b586192320..00000000000
--- a/src/interfaces/odbc/convert.c
+++ /dev/null
@@ -1,3578 +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 <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef MULTIBYTE
-#include "multibyte.h"
-#endif
-
-#include <time.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-#include <math.h>
-#include <stdlib.h>
-#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" }, built_in */
- {"CHAR", "chr($*)" },
- {"CONCAT", "textcat($*)" },
-/* { "DIFFERENCE", "difference" }, how to ? */
- {"INSERT", "substring($1 from 1 for $2 - 1) || $4 || substring($1 from $2 + $3)" },
- {"LCASE", "lower($*)" },
- {"LEFT", "ltrunc($*)" },
- {"%2LOCATE", "strpos($2, $1)" }, /* 2 parameters */
- {"%3LOCATE", "strpos(substring($2 from $3), $1) + $3 - 1" }, /* 3 parameters */
- {"LENGTH", "char_length($*)"},
-/* { "LTRIM", "ltrim" }, built_in */
- {"RIGHT", "rtrunc($*)" },
- {"SPACE", "repeat('' '', $1)" },
-/* { "REPEAT", "repeat" }, built_in */
-/* { "REPLACE", "replace" }, ??? */
-/* { "RTRIM", "rtrim" }, built_in */
-/* { "SOUNDEX", "soundex" }, how to ? */
- {"SUBSTRING", "substr($*)" },
- {"UCASE", "upper($*)" },
-
-/* { "ABS", "abs" }, built_in */
-/* { "ACOS", "acos" }, built_in */
-/* { "ASIN", "asin" }, built_in */
-/* { "ATAN", "atan" }, built_in */
-/* { "ATAN2", "atan2" }, bui;t_in */
- {"CEILING", "ceil($*)" },
-/* { "COS", "cos" }, built_in */
-/* { "COT", "cot" }, built_in */
-/* { "DEGREES", "degrees" }, built_in */
-/* { "EXP", "exp" }, built_in */
-/* { "FLOOR", "floor" }, built_in */
- {"LOG", "ln($*)" },
- {"LOG10", "log($*)" },
-/* { "MOD", "mod" }, built_in */
-/* { "PI", "pi" }, built_in */
- {"POWER", "pow($*)" },
-/* { "RADIANS", "radians" }, built_in */
- {"%0RAND", "random()" }, /* 0 parameters */
- {"%1RAND", "(setseed($1) * .0 + random())" }, /* 1 parameters */
-/* { "ROUND", "round" }, built_in */
-/* { "SIGN", "sign" }, built_in */
-/* { "SIN", "sin" }, built_in */
-/* { "SQRT", "sqrt" }, built_in */
-/* { "TAN", "tan" }, built_in */
- {"TRUNCATE", "trunc($*)" },
-
- {"CURRENT_DATE", "current_date" },
- {"CURRENT_TIME", "current_time" },
- {"CURRENT_TIMESTAMP", "current_timestamp" },
- {"LOCALTIME", "localtime" },
- {"LOCALTIMESTAMP", "localtimestamp" },
- {"CURRENT_USER", "cast(current_user as text)" },
- {"SESSION_USER", "cast(session_user as text)" },
- {"CURDATE", "current_date" },
- {"CURTIME", "current_time" },
- {"DAYNAME", "to_char($1, 'Day')" },
- {"DAYOFMONTH", "cast(extract(day from $1) as integer)" },
- {"DAYOFWEEK", "(cast(extract(dow from $1) as integer) + 1)" },
- {"DAYOFYEAR", "cast(extract(doy from $1) as integer)" },
- {"HOUR", "cast(extract(hour from $1) as integer)" },
- {"MINUTE", "cast(extract(minute from $1) as integer)" },
- {"MONTH", "cast(extract(month from $1) as integer)" },
- {"MONTHNAME", " to_char($1, 'Month')" },
-/* { "NOW", "now" }, built_in */
- {"QUARTER", "cast(extract(quarter from $1) as integer)" },
- {"SECOND", "cast(extract(second from $1) as integer)" },
- {"WEEK", "cast(extract(week from $1) as integer)" },
- {"YEAR", "cast(extract(year from $1) as integer)" },
-
-/* { "DATABASE", "database" }, */
- {"IFNULL", "coalesce($*)" },
- {"USER", "cast(current_user as text)" },
- {0, 0}
-};
-
-static const char *mapFunction(const char *func, int param_count);
-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;
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
- long timediff;
-#endif
- BOOL withZone = *bZone;
-
- *bZone = FALSE;
- *zone = 0;
- st->fr = 0;
- st->infinity = 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 (st->infinity > 0)
- {
- strcpy(str, "Infinity");
- return TRUE;
- }
- else if (st->infinity < 0)
- {
- strcpy(str, "-Infinity");
- return TRUE;
- }
- 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)
-{
- ARDFields *opts = SC_get_ARD(stmt);
- BindInfoClass *bic = &(opts->bindings[col]);
- UInt4 offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
-
- return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) (bic->buffer + offset),
- (SDWORD) bic->buflen, (SDWORD *) (bic->used + (offset >> 2)));
-}
-
-
-/* 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)
-{
- static char *func = "copy_and_convert_field";
- ARDFields *opts = SC_get_ARD(stmt);
- 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 = opts->bind_size;
- int result = COPY_OK;
-#ifdef HAVE_LOCALE_H
- char saved_locale[256];
-#endif /* HAVE_LOCALE_H */
- BOOL changed, true_is_minus1 = FALSE;
- const char *neut_str = value;
- char midtemp[2][32];
- int mtemp_cnt = 0;
- static BindInfoClass sbic;
- BindInfoClass *pbic;
-#ifdef UNICODE_SUPPORT
- BOOL wchanged = FALSE;
-#endif /* UNICODE_SUPPORT */
-
- if (stmt->current_col >= 0)
- {
- pbic = &opts->bindings[stmt->current_col];
- if (pbic->data_left == -2)
- pbic->data_left = (cbValueMax > 0) ? 0 : -1; /* This seems to be *
- * needed by 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) ? "<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;
- }
- else
- {
- stmt->errornumber = STMT_RETURN_NULL_WITHOUT_INDICATOR;
- stmt->errormsg = "StrLen_or_IndPtr was a null pointer and NULL data was retrieved";
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- }
-
- 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_NO_TMZONE:
- case PG_TYPE_TIMESTAMP:
- st.fr = 0;
- st.infinity = 0;
- if (strnicmp(value, "infinity", 8) == 0)
- {
- st.infinity = 1;
- st.m = 12;
- st.d = 31;
- st.y = 9999;
- st.hh = 23;
- st.mm = 59;
- st.ss = 59;
- }
- if (strnicmp(value, "-infinity", 9) == 0)
- {
- st.infinity = -1;
- st.m = 0;
- st.d = 0;
- st.y = 0;
- st.hh = 0;
- st.mm = 0;
- st.ss = 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];
- switch (((char *)value)[0])
- {
- case 'f':
- case 'F':
- case 'n':
- case 'N':
- case '0':
- strcpy(s, "0");
- break;
- default:
- if (true_is_minus1)
- strcpy(s, "-1");
- else
- strcpy(s, "1");
- }
- 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;
-
-#ifdef UNICODE_SUPPORT
- if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
-#else
- if (fCType == SQL_C_CHAR)
-#endif /* UNICODE_SUPPORT */
- {
- /* 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_NO_TMZONE:
- 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 = strlen(neut_str);
- 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 = &opts->bindings[stmt->current_col];
- if (pbic->data_left < 0)
- {
- BOOL lf_conv = SC_get_conn(stmt)->connInfo.lf_conversion;
-#ifdef UNICODE_SUPPORT
- if (fCType == SQL_C_WCHAR)
- {
- len = utf8_to_ucs2_lf(neut_str, -1, lf_conv, NULL, 0);
- len *= 2;
- wchanged = changed = TRUE;
- }
- else
-#endif /* UNICODE_SUPPORT */
- /* convert linefeeds to carriage-return/linefeed */
- len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &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;
- }
-#ifdef UNICODE_SUPPORT
- if (fCType == SQL_C_WCHAR)
- {
- utf8_to_ucs2_lf(neut_str, -1, lf_conv, (SQLWCHAR *) pbic->ttlbuf, len / 2);
- }
- else
-#endif /* UNICODE_SUPPORT */
- convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, lf_conv, &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;
-
-#ifdef HAVE_LOCALE_H
- switch (field_type)
- {
- case PG_TYPE_FLOAT4:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_NUMERIC:
- {
- struct lconv *lc;
- char *new_string;
- int i, j;
-
- new_string = malloc( cbValueMax );
- lc = localeconv();
- for (i = 0, j = 0; ptr[i]; i++)
- if (ptr[i] == '.')
- {
- strncpy(&new_string[j], lc->decimal_point, strlen(lc->decimal_point));
- j += strlen(lc->decimal_point);
- }
- else
- new_string[j++] = ptr[i];
- new_string[j] = '\0';
- strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
- free(new_string);
- break;
- }
- default:
- /* Copy the data */
- strncpy_null(rgbValueBindRow, ptr, copy_len + 1);
- }
-#else /* HAVE_LOCALE_H */
- /* Copy the data */
- memcpy(rgbValueBindRow, ptr, copy_len);
- rgbValueBindRow[copy_len] = '\0';
-#endif /* HAVE_LOCALE_H */
-
- /* 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;
- }
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == fCType && ! wchanged)
- {
- if (cbValueMax > 2 * len)
- {
- char *str = strdup(rgbValueBindRow);
- UInt4 ucount = utf8_to_ucs2(str, len, (SQLWCHAR *) rgbValueBindRow, cbValueMax / 2);
- if (cbValueMax < 2 * (SDWORD) ucount)
- result = COPY_RESULT_TRUNCATED;
- len = ucount * 2;
- free(str);
- }
- else
- {
- len *= 2;
- result = COPY_RESULT_TRUNCATED;
- }
- }
-#endif /* UNICODE_SUPPORT */
-
- }
- 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:
-#ifdef HAVE_LOCALE_H
- strcpy(saved_locale, setlocale(LC_ALL, NULL));
- setlocale(LC_ALL, "C");
-#endif /* HAVE_LOCALE_H */
- 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);
-#ifdef HAVE_LOCALE_H
- setlocale(LC_ALL, saved_locale);
-#endif /* HAVE_LOCALE_H */
- break;
-
- case SQL_C_DOUBLE:
-#ifdef HAVE_LOCALE_H
- strcpy(saved_locale, setlocale(LC_ALL, NULL));
- setlocale(LC_ALL, "C");
-#endif /* HAVE_LOCALE_H */
- len = 8;
- if (bind_size > 0)
- *(SDOUBLE *) ((char *) rgbValue + (bind_row * bind_size)) = atof(neut_str);
- else
- *((SDOUBLE *) rgbValue + bind_row) = atof(neut_str);
-#ifdef HAVE_LOCALE_H
- setlocale(LC_ALL, saved_locale);
-#endif /* HAVE_LOCALE_H */
- break;
-
-#if (ODBCVER >= 0x0300)
- case SQL_C_NUMERIC:
-#ifdef HAVE_LOCALE_H
- /* strcpy(saved_locale, setlocale(LC_ALL, NULL));
- setlocale(LC_ALL, "C"); not needed currently */
-#endif /* HAVE_LOCALE_H */
- {
- SQL_NUMERIC_STRUCT *ns;
- int i, nlen, bit, hval, tv, dig, sta, olen;
- char calv[SQL_MAX_NUMERIC_LEN * 3], *wv;
- BOOL dot_exist;
-
- len = sizeof(SQL_NUMERIC_STRUCT);
- if (bind_size > 0)
- ns = (SQL_NUMERIC_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
- else
- ns = (SQL_NUMERIC_STRUCT *) rgbValue + bind_row;
- for (wv = neut_str; *wv && isspace(*wv); wv++)
- ;
- ns->sign = 1;
- if (*wv == '-')
- {
- ns->sign = 0;
- wv++;
- }
- else if (*wv == '+')
- wv++;
- while (*wv == '0') wv++;
- ns->precision = 0;
- ns->scale = 0;
- for (nlen = 0, dot_exist = FALSE;; wv++)
- {
- if (*wv == '.')
- {
- if (dot_exist)
- break;
- dot_exist = TRUE;
- }
- else if (!isdigit(*wv))
- break;
- else
- {
- if (dot_exist)
- ns->scale++;
- else
- ns->precision++;
- calv[nlen++] = *wv;
- }
- }
- memset(ns->val, 0, sizeof(ns->val));
- for (hval = 0, bit = 1L, sta = 0, olen = 0; sta < nlen;)
- {
- for (dig = 0, i = sta; i < nlen; i++)
- {
- tv = dig * 10 + calv[i] - '0';
- dig = tv % 2;
- calv[i] = tv / 2 + '0';
- if (i == sta && tv < 2)
- sta++;
- }
- if (dig > 0)
- hval |= bit;
- bit <<= 1;
- if (bit >= (1L << 8))
- {
- ns->val[olen++] = hval;
- hval = 0;
- bit = 1L;
- if (olen >= SQL_MAX_NUMERIC_LEN - 1)
- {
- ns->scale = sta - ns->precision;
- break;
- }
- }
- }
- if (hval && olen < SQL_MAX_NUMERIC_LEN - 1)
- ns->val[olen++] = hval;
- }
-#ifdef HAVE_LOCALE_H
- /* setlocale(LC_ALL, saved_locale); */
-#endif /* HAVE_LOCALE_H */
- break;
-#endif /* ODBCVER */
-
- 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;
-
-#if (ODBCVER >= 0x0300) && defined(ODBCINT64)
-#ifdef WIN32
- case SQL_C_SBIGINT:
- len = 8;
- if (bind_size > 0)
- *(SQLBIGINT *) ((char *) rgbValue + (bind_row * bind_size)) = _atoi64(neut_str);
- else
- *((SQLBIGINT *) rgbValue + bind_row) = _atoi64(neut_str);
- break;
-
- case SQL_C_UBIGINT:
- len = 8;
- if (bind_size > 0)
- *(SQLUBIGINT *) ((char *) rgbValue + (bind_row * bind_size)) = _atoi64(neut_str);
- else
- *((SQLUBIGINT *) rgbValue + bind_row) = _atoi64(neut_str);
- break;
-
-#endif /* WIN32 */
-#endif /* ODBCINT64 */
- 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 = &opts->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)
- opts->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 FLGP_PREPARE_DUMMY_CURSOR 1L
-#define FLGP_CURSOR_CHECK_OK (1L << 1)
-#define FLGP_SELECT_INTO (1L << 2)
-#define FLGP_SELECT_FOR_UPDATE (1L << 3)
-typedef struct _QueryParse {
- const char *statement;
- int statement_type;
- UInt4 opos;
- int from_pos;
- int where_pos;
- UInt4 stmt_len;
- BOOL in_quote, in_dquote, in_escape;
- char token_save[64];
- int token_len;
- BOOL prev_token_end;
- BOOL proc_no_param;
- unsigned int declare_pos;
- UInt4 flags;
-#ifdef MULTIBYTE
- encoded_str encstr;
-#endif /* MULTIBYTE */
-} QueryParse;
-
-static int
-QP_initialize(QueryParse *q, const StatementClass *stmt)
-{
- q->statement = stmt->statement;
- q->statement_type = stmt->statement_type;
- q->opos = 0;
- q->from_pos = -1;
- q->where_pos = -1;
- q->stmt_len = (q->statement) ? strlen(q->statement) : -1;
- q->in_quote = q->in_dquote = q->in_escape = FALSE;
- q->token_save[0] = '\0';
- q->token_len = 0;
- q->prev_token_end = TRUE;
- q->proc_no_param = TRUE;
- q->declare_pos = 0;
- q->flags = 0;
-#ifdef MULTIBYTE
- make_encoded_str(&q->encstr, SC_get_conn(stmt), q->statement);
-#endif /* MULTIBYTE */
-
- return q->stmt_len;
-}
-
-#define FLGB_PRE_EXECUTING 1L
-#define FLGB_INACCURATE_RESULT (1L << 1)
-#define FLGB_CREATE_KEYSET (1L << 2)
-#define FLGB_KEYSET_DRIVEN (1L << 3)
-typedef struct _QueryBuild {
- char *query_statement;
- UInt4 str_size_limit;
- UInt4 str_alsize;
- UInt4 npos;
- int current_row;
- int param_number;
- APDFields *apdopts;
- UInt4 load_stmt_len;
- UInt4 flags;
- BOOL lf_conv;
- int ccsc;
- int errornumber;
- const char *errormsg;
-
- ConnectionClass *conn; /* mainly needed for LO handling */
- StatementClass *stmt; /* needed to set error info in ENLARGE_.. */
-} QueryBuild;
-
-#define INIT_MIN_ALLOC 4096
-static int
-QB_initialize(QueryBuild *qb, UInt4 size, StatementClass *stmt, ConnectionClass *conn)
-{
- UInt4 newsize = 0;
-
- qb->flags = 0;
- qb->load_stmt_len = 0;
- qb->stmt = stmt;
- qb->apdopts = NULL;
- if (conn)
- qb->conn = conn;
- else if (stmt)
- {
- qb->apdopts = SC_get_APD(stmt);
- qb->conn = SC_get_conn(stmt);
- if (stmt->pre_executing)
- qb->flags |= FLGB_PRE_EXECUTING;
- }
- else
- {
- qb->conn = NULL;
- return -1;
- }
- qb->lf_conv = qb->conn->connInfo.lf_conversion;
- qb->ccsc = qb->conn->ccsc;
-
- if (stmt)
- qb->str_size_limit = stmt->stmt_size_limit;
- else
- qb->str_size_limit = -1;
- if (qb->str_size_limit > 0)
- {
- if (size > qb->str_size_limit)
- return -1;
- newsize = qb->str_size_limit;
- }
- else
- {
- newsize = INIT_MIN_ALLOC;
- while (newsize <= size)
- newsize *= 2;
- }
- if ((qb->query_statement = malloc(newsize)) == NULL)
- {
- qb->str_alsize = 0;
- return -1;
- }
- qb->query_statement[0] = '\0';
- qb->str_alsize = newsize;
- qb->npos = 0;
- qb->current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
- qb->param_number = -1;
- qb->errornumber = 0;
- qb->errormsg = NULL;
-
- return newsize;
-}
-
-static int
-QB_initialize_copy(QueryBuild *qb_to, const QueryBuild *qb_from, UInt4 size)
-{
- memcpy(qb_to, qb_from, sizeof(QueryBuild));
-
- if (qb_to->str_size_limit > 0)
- {
- if (size > qb_to->str_size_limit)
- return -1;
- }
- if ((qb_to->query_statement = malloc(size)) == NULL)
- {
- qb_to->str_alsize = 0;
- return -1;
- }
- qb_to->query_statement[0] = '\0';
- qb_to->str_alsize = size;
- qb_to->npos = 0;
-
- return size;
-}
-
-static void
-QB_Destructor(QueryBuild *qb)
-{
- if (qb->query_statement)
- {
- free(qb->query_statement);
- qb->query_statement = NULL;
- qb->str_alsize = 0;
- }
-}
-
-/*
- * New macros (Aceto)
- *--------------------
- */
-
-#define F_OldChar(qp) \
-qp->statement[qp->opos]
-
-#define F_OldPtr(qp) \
-(qp->statement + qp->opos)
-
-#define F_OldNext(qp) \
-(++qp->opos)
-
-#define F_OldPrior(qp) \
-(--qp->opos)
-
-#define F_OldPos(qp) \
-qp->opos
-
-#define F_ExtractOldTo(qp, buf, ch, maxsize) \
-do { \
- unsigned int c = 0; \
- while (qp->statement[qp->opos] != '\0' && qp->statement[qp->opos] != ch) \
- { \
- buf[c++] = qp->statement[qp->opos++]; \
- if (c >= maxsize) \
- break; \
- } \
- if (qp->statement[qp->opos] == '\0') \
- return SQL_ERROR; \
- buf[c] = '\0'; \
-} while (0)
-
-#define F_NewChar(qb) \
-qb->query_statement[qb->npos]
-
-#define F_NewPtr(qb) \
-(qb->query_statement + qb->npos)
-
-#define F_NewNext(qb) \
-(++qb->npos)
-
-#define F_NewPos(qb) \
-(qb->npos)
-
-
-static int
-convert_escape(QueryParse *qp, QueryBuild *qb);
-static int
-inner_process_tokens(QueryParse *qp, QueryBuild *qb);
-static int
-ResolveOneParam(QueryBuild *qb);
-static int
-processParameters(QueryParse *qp, QueryBuild *qb,
-UInt4 *output_count, Int4 param_pos[][2]);
-
-static int
-enlarge_query_statement(QueryBuild *qb, unsigned int newsize)
-{
- unsigned int newalsize = INIT_MIN_ALLOC;
- static char *func = "enlarge_statement";
-
- if (qb->str_size_limit > 0 && qb->str_size_limit < (int) newsize)
- {
- free(qb->query_statement);
- qb->query_statement = NULL;
- qb->str_alsize = 0;
- if (qb->stmt)
- {
- qb->stmt->errormsg = "Query buffer overflow in copy_statement_with_parameters";
- qb->stmt->errornumber = STMT_EXEC_ERROR;
- SC_log_error(func, "", qb->stmt);
- }
- else
- {
- qb->errormsg = "Query buffer overflow in copy_statement_with_parameters";
- qb->errornumber = STMT_EXEC_ERROR;
- }
- return -1;
- }
- while (newalsize <= newsize)
- newalsize *= 2;
- if (!(qb->query_statement = realloc(qb->query_statement, newalsize)))
- {
- qb->str_alsize = 0;
- if (qb->stmt)
- {
- qb->stmt->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
- qb->stmt->errornumber = STMT_EXEC_ERROR;
- }
- else
- {
- qb->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
- qb->errornumber = STMT_EXEC_ERROR;
- }
- return 0;
- }
- qb->str_alsize = newalsize;
- return newalsize;
-}
-
-/*----------
- * Enlarge stmt_with_params if necessary.
- *----------
- */
-#define ENLARGE_NEWSTATEMENT(qb, newpos) \
- if (newpos >= qb->str_alsize) \
- { \
- if (enlarge_query_statement(qb, newpos) <= 0) \
- return SQL_ERROR; \
- }
-
-/*----------
- * Terminate the stmt_with_params string with NULL.
- *----------
- */
-#define CVT_TERMINATE(qb) \
-do { \
- qb->query_statement[qb->npos] = '\0'; \
-} while (0)
-
-/*----------
- * Append a data.
- *----------
- */
-#define CVT_APPEND_DATA(qb, s, len) \
-do { \
- unsigned int newpos = qb->npos + len; \
- ENLARGE_NEWSTATEMENT(qb, newpos) \
- memcpy(&qb->query_statement[qb->npos], s, len); \
- qb->npos = newpos; \
- qb->query_statement[newpos] = '\0'; \
-} while (0)
-
-/*----------
- * Append a string.
- *----------
- */
-#define CVT_APPEND_STR(qb, s) \
-do { \
- unsigned int len = strlen(s); \
- CVT_APPEND_DATA(qb, s, len); \
-} while (0)
-
-/*----------
- * Append a char.
- *----------
- */
-#define CVT_APPEND_CHAR(qb, c) \
-do { \
- ENLARGE_NEWSTATEMENT(qb, qb->npos + 1); \
- qb->query_statement[qb->npos++] = c; \
-} while (0)
-
-/*----------
- * Append a binary data.
- * Newly reqeuired size may be overestimated currently.
- *----------
- */
-#define CVT_APPEND_BINARY(qb, buf, used) \
-do { \
- unsigned int newlimit = qb->npos + 5 * used; \
- ENLARGE_NEWSTATEMENT(qb, newlimit); \
- qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used); \
-} while (0)
-
-/*----------
- *
- *----------
- */
-#define CVT_SPECIAL_CHARS(qb, buf, used) \
-do { \
- int cnvlen = convert_special_chars(buf, NULL, used, qb->lf_conv, qb->ccsc); \
- unsigned int newlimit = qb->npos + cnvlen; \
-\
- ENLARGE_NEWSTATEMENT(qb, newlimit); \
- convert_special_chars(buf, &qb->query_statement[qb->npos], used, qb->lf_conv, qb->ccsc); \
- qb->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]);
-}
-
-/*----------
- * Check if the statement is
- * INSERT INTO ... () VALUES ()
- * This isn't really a strict check but ...
- *----------
- */
-static BOOL
-insert_without_target(const char *stmt, int *endpos)
-{
- const char *wstmt = stmt;
-
- while (isspace((unsigned char) *(++wstmt)));
- if (!*wstmt)
- return FALSE;
- if (strnicmp(wstmt, "VALUES", 6))
- return FALSE;
- wstmt += 6;
- if (!wstmt[0] || !isspace((unsigned char) wstmt[0]))
- return FALSE;
- while (isspace((unsigned char) *(++wstmt)));
- if (*wstmt != '(' || *(++wstmt) != ')')
- return FALSE;
- wstmt++;
- *endpos = wstmt - stmt;
- return !wstmt[0] || isspace((unsigned char) wstmt[0])
- || ';' == wstmt[0];
-}
-
-#ifdef MULTIBYTE
-#define my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
-#else
-#define my_strchr(conn, s1,c1) strchr(s1,c1)
-#endif
-/*
- * 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";
- RETCODE retval;
- QueryParse query_org, *qp;
- QueryBuild query_crt, *qb;
-
- char *new_statement;
-
- BOOL begin_first = FALSE, prepare_dummy_cursor = FALSE;
- ConnectionClass *conn = SC_get_conn(stmt);
- ConnInfo *ci = &(conn->connInfo);
- int current_row;
-
- if (!stmt->statement)
- {
- SC_log_error(func, "No statement string", stmt);
- return SQL_ERROR;
- }
-
- current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
- qp = &query_org;
- QP_initialize(qp, stmt);
-
- if (ci->disallow_premature)
- prepare_dummy_cursor = stmt->pre_executing;
- if (prepare_dummy_cursor);
- qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
-
-
-#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_FATAL)
- {
- stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
- return SQL_ERROR;
- }
- else if (!stmt->updatable)
- {
- stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
- stmt->options.cursor_type = SQL_CURSOR_STATIC;
- }
- else
- {
- qp->from_pos = stmt->from_pos;
- qp->where_pos = stmt->where_pos;
- }
- }
-#else
- stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
- if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
- stmt->options.cursor_type = SQL_CURSOR_STATIC;
-#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);
- if (stmt->stmt_with_params)
- {
- free(stmt->stmt_with_params);
- stmt->stmt_with_params = NULL;
- }
- qb = &query_crt;
- if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
- return SQL_ERROR;
- new_statement = qb->query_statement;
-
- stmt->miscinfo = 0;
- /* For selects, prepend a declare cursor to the statement */
- if (stmt->statement_type == STMT_TYPE_SELECT)
- {
- SC_set_pre_executable(stmt);
- if (prepare_dummy_cursor || ci->drivers.use_declarefetch)
- {
- if (prepare_dummy_cursor)
- {
- if (!CC_is_in_trans(conn) && 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);
- qb->npos = strlen(new_statement);
- qp->flags |= FLGP_CURSOR_CHECK_OK;
- qp->declare_pos = qb->npos;
- }
- else if (SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
- {
- qb->flags |= FLGB_CREATE_KEYSET;
- if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type)
- qb->flags |= FLGB_KEYSET_DRIVEN;
- }
- }
-
- for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
- {
- retval = inner_process_tokens(qp, qb);
- if (SQL_ERROR == retval)
- {
- if (0 == stmt->errornumber)
- {
- stmt->errornumber = qb->errornumber;
- stmt->errormsg = qb->errormsg;
- }
- SC_log_error(func, "", stmt);
- QB_Destructor(qb);
- return retval;
- }
- }
- /* make sure new_statement is always null-terminated */
- CVT_TERMINATE(qb);
-
- new_statement = qb->query_statement;
- stmt->statement_type = qp->statement_type;
- stmt->inaccurate_result = (0 != (qb->flags & FLGB_INACCURATE_RESULT));
- if (0 != (qp->flags & FLGP_SELECT_INTO))
- {
- SC_no_pre_executable(stmt);
- SC_no_fetchcursor(stmt);
- stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
- }
- if (0 != (qp->flags & FLGP_SELECT_FOR_UPDATE))
- {
- SC_no_fetchcursor(stmt);
- stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
- }
-
- 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 (!stmt->load_statement && qp->from_pos >= 0)
- {
- UInt4 npos = qb->load_stmt_len;
-
- if (0 == npos)
- {
- npos = qb->npos;
- for (; npos > 0; npos--)
- {
- if (isspace(new_statement[npos - 1]))
- continue;
- if (';' != new_statement[npos - 1])
- break;
- }
- if (0 != (qb->flags & FLGB_KEYSET_DRIVEN))
- {
- qb->npos = npos;
- /* ----------
- * 1st query is for field information
- * 2nd query is keyset gathering
- */
- CVT_APPEND_STR(qb, " where ctid = '(,)';select ctid, oid from ");
- CVT_APPEND_DATA(qb, qp->statement + qp->from_pos + 5, npos - qp->from_pos - 5);
- }
- }
- stmt->load_statement = malloc(npos + 1);
- memcpy(stmt->load_statement, qb->query_statement, npos);
- stmt->load_statement[npos] = '\0';
- }
-#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(qb, fetchstr);
- stmt->inaccurate_result = TRUE;
- }
-
- stmt->stmt_with_params = qb->query_statement;
- return SQL_SUCCESS;
-}
-
-static int
-inner_process_tokens(QueryParse *qp, QueryBuild *qb)
-{
- static char *func = "inner_process_tokens";
- BOOL lf_conv = qb->lf_conv;
-
- RETCODE retval;
- char oldchar;
-
- if (qp->from_pos == (Int4) qp->opos)
- {
- CVT_APPEND_STR(qb, ", CTID, OID ");
- }
- else if (qp->where_pos == (Int4) qp->opos)
- {
- qb->load_stmt_len = qb->npos;
- if (0 != (qb->flags & FLGB_KEYSET_DRIVEN))
- {
- CVT_APPEND_STR(qb, "where ctid = '(,)';select CTID, OID from ");
- CVT_APPEND_DATA(qb, qp->statement + qp->from_pos + 5, qp->where_pos - qp->from_pos - 5);
- }
- }
-#ifdef MULTIBYTE
- oldchar = encoded_byte_check(&qp->encstr, qp->opos);
- if (ENCODE_STATUS(qp->encstr) != 0)
- {
- CVT_APPEND_CHAR(qb, oldchar);
- return SQL_SUCCESS;
- }
-
- /*
- * From here we are guaranteed to handle a 1-byte character.
- */
-#else
- oldchar = qp->statement[qp->opos];
-#endif
-
- if (qp->in_escape) /* escape check */
- {
- qp->in_escape = FALSE;
- CVT_APPEND_CHAR(qb, oldchar);
- return SQL_SUCCESS;
- }
- else if (qp->in_quote || qp->in_dquote) /* quote/double quote check */
- {
- if (oldchar == '\\')
- qp->in_escape = TRUE;
- else if (oldchar == '\'' && qp->in_quote)
- qp->in_quote = FALSE;
- else if (oldchar == '\"' && qp->in_dquote)
- qp->in_dquote = FALSE;
- CVT_APPEND_CHAR(qb, oldchar);
- return SQL_SUCCESS;
- }
-
- /*
- * 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 (lf_conv && oldchar == '\r' && qp->opos + 1 < qp->stmt_len &&
- qp->statement[qp->opos + 1] == '\n')
- return SQL_SUCCESS;
-
- /*
- * Handle literals (date, time, timestamp) and ODBC scalar
- * functions
- */
- else if (oldchar == '{')
- {
- if (SQL_ERROR == convert_escape(qp, qb))
- {
- if (0 == qb->errornumber)
- {
- qb->errornumber = STMT_EXEC_ERROR;
- qb->errormsg = "ODBC escape convert error";
- }
- mylog("%s convert_escape error\n", func);
- return SQL_ERROR;
- }
- if (isalnum(F_OldPtr(qp)[1]))
- CVT_APPEND_CHAR(qb, ' ');
- return SQL_SUCCESS;
- }
- /* End of an escape sequence */
- else if (oldchar == '}')
- {
- if (qp->statement_type == STMT_TYPE_PROCCALL)
- {
- if (qp->proc_no_param)
- CVT_APPEND_STR(qb, "()");
- }
- else if (!isspace(F_OldPtr(qp)[1]))
- CVT_APPEND_CHAR(qb, ' ');
- return SQL_SUCCESS;
- }
-
- /*
- * 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 != '?')
- {
- if (oldchar == '\'')
- qp->in_quote = TRUE;
- else if (oldchar == '\\')
- qp->in_escape = TRUE;
- else if (oldchar == '\"')
- qp->in_dquote = TRUE;
- else
- {
- if (isspace((unsigned char) oldchar))
- {
- if (!qp->prev_token_end)
- {
- qp->prev_token_end = TRUE;
- qp->token_save[qp->token_len] = '\0';
- if (qp->token_len == 4)
- {
- if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&
- into_table_from(&qp->statement[qp->opos - qp->token_len]))
- {
- qp->flags |= FLGP_SELECT_INTO;
- qp->flags &= ~FLGP_CURSOR_CHECK_OK;
- qb->flags &= ~FLGB_KEYSET_DRIVEN;
- qp->statement_type = STMT_TYPE_CREATE;
- memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);
- qb->npos -= qp->declare_pos;
- }
- }
- else if (qp->token_len == 3)
- {
- int endpos;
-
- if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&
- strnicmp(qp->token_save, "for", 3) == 0 &&
- table_for_update(&qp->statement[qp->opos], &endpos))
- {
- qp->flags |= FLGP_SELECT_FOR_UPDATE;
- qp->flags &= ~FLGP_CURSOR_CHECK_OK;
- if (qp->flags & FLGP_PREPARE_DUMMY_CURSOR)
- {
- qb->npos -= 4;
- qp->opos += endpos;
- }
- else
- {
- memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);
- qb->npos -= qp->declare_pos;
- }
- }
- }
- else if (qp->token_len == 2)
- {
- int endpos;
-
- if (STMT_TYPE_INSERT == qp->statement_type &&
- strnicmp(qp->token_save, "()", 2) == 0 &&
- insert_without_target(&qp->statement[qp->opos], &endpos))
- {
- qb->npos -= 2;
- CVT_APPEND_STR(qb, "DEFAULT VALUES");
- qp->opos += endpos;
- return SQL_SUCCESS;
- }
- }
- }
- }
- else if (qp->prev_token_end)
- {
- qp->prev_token_end = FALSE;
- qp->token_save[0] = oldchar;
- qp->token_len = 1;
- }
- else if (qp->token_len + 1 < sizeof(qp->token_save))
- qp->token_save[qp->token_len++] = oldchar;
- }
- CVT_APPEND_CHAR(qb, oldchar);
- return SQL_SUCCESS;
- }
-
- /*
- * Its a '?' parameter alright
- */
- if (retval = ResolveOneParam(qb), retval < 0)
- return retval;
-
- return SQL_SUCCESS;
-}
-
-#if (ODBCVER >= 0x0300)
-static BOOL
-ResolveNumericParam(const SQL_NUMERIC_STRUCT *ns, char *chrform)
-{
- static int prec[] = {1, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 29, 32, 34, 37, 39};
- Int4 i, j, k, ival, vlen, len, newlen;
- unsigned char calv[40];
- const unsigned char *val = (const unsigned char *) ns->val;
- BOOL next_figure;
-
- if (0 == ns->precision)
- {
- strcpy(chrform, "0");
- return TRUE;
- }
- else if (ns->precision < prec[sizeof(Int4)])
- {
- for (i = 0, ival = 0; i < sizeof(Int4) && prec[i] <= ns->precision; i++)
- {
- ival += (val[i] << (8 * i)); /* ns->val is little endian */
- }
- if (0 == ns->scale)
- {
- if (0 == ns->sign)
- ival *= -1;
- sprintf(chrform, "%d", ival);
- }
- else if (ns->scale > 0)
- {
- Int4 i, div, o1val, o2val;
-
- for (i = 0, div = 1; i < ns->scale; i++)
- div *= 10;
- o1val = ival / div;
- o2val = ival % div;
- if (0 == ns->sign)
- o1val *= -1;
- sprintf(chrform, "%d.%0.*d", o1val, ns->scale, o2val);
- }
- return TRUE;
- }
-
- for (i = 0; i < SQL_MAX_NUMERIC_LEN && prec[i] <= ns->precision; i++)
- ;
- vlen = i;
- len = 0;
- memset(calv, 0, sizeof(calv));
- for (i = vlen - 1; i >= 0; i--)
- {
- for (j = len - 1; j >= 0; j--)
- {
- if (!calv[j])
- continue;
- ival = (((Int4)calv[j]) << 8);
- calv[j] = (ival % 10);
- ival /= 10;
- calv[j + 1] += (ival % 10);
- ival /= 10;
- calv[j + 2] += (ival % 10);
- ival /= 10;
- calv[j + 3] += ival;
- for (k = j;; k++)
- {
- next_figure = FALSE;
- if (calv[k] > 0)
- {
- if (k >= len)
- len = k + 1;
- while (calv[k] > 9)
- {
- calv[k + 1]++;
- calv[k] -= 10;
- next_figure = TRUE;
- }
- }
- if (k >= j + 3 && !next_figure)
- break;
- }
- }
- ival = val[i];
- if (!ival)
- continue;
- calv[0] += (ival % 10);
- ival /= 10;
- calv[1] += (ival % 10);
- ival /= 10;
- calv[2] += ival;
- for (j = 0;; j++)
- {
- next_figure = FALSE;
- if (calv[j] > 0)
- {
- if (j >= len)
- len = j + 1;
- while (calv[j] > 9)
- {
- calv[j + 1]++;
- calv[j] -= 10;
- next_figure = TRUE;
- }
- }
- if (j >= 2 && !next_figure)
- break;
- }
- }
- newlen = 0;
- if (0 == ns->sign)
- chrform[newlen++] = '-';
- for (i = len - 1; i >= ns->scale; i--)
- chrform[newlen++] = calv[i] + '0';
- if (ns->scale > 0)
- {
- chrform[newlen++] = '.';
- for (; i >= 0; i--)
- chrform[newlen++] = calv[i] + '0';
- }
- chrform[newlen] = '\0';
- return TRUE;
-}
-#endif /* ODBCVER */
-
-/*
- *
- */
-static int
-ResolveOneParam(QueryBuild *qb)
-{
- const char *func = "ResolveOneParam";
-
- ConnectionClass *conn = qb->conn;
- ConnInfo *ci = &(conn->connInfo);
- APDFields *opts = qb->apdopts;
-
- int param_number;
- char param_string[128], tmp[256],
- cbuf[PG_NUMERIC_MAX_PRECISION * 2]; /* seems big enough to handle the data in this function */
- Int2 param_ctype, param_sqltype;
- SIMPLE_TIME st;
- time_t t;
- struct tm *tim;
- SDWORD used;
- char *buffer, *buf, *allocbuf;
- Oid lobj_oid;
- int lobj_fd, retval;
- UInt4 offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
- UInt4 current_row = qb->current_row;
-
- /*
- * Its a '?' parameter alright
- */
- param_number = ++qb->param_number;
-
- if (param_number >= opts->allocated)
- {
- if (0 != (qb->flags & FLGB_PRE_EXECUTING))
- {
- CVT_APPEND_STR(qb, "NULL");
- qb->flags |= FLGB_INACCURATE_RESULT;
- return SQL_SUCCESS;
- }
- else
- {
- CVT_APPEND_CHAR(qb, '?');
- return SQL_SUCCESS;
- }
- }
-
- /* Assign correct buffers based on data at exec param or not */
- if (opts->parameters[param_number].data_at_exec)
- {
- used = opts->parameters[param_number].EXEC_used ? *opts->parameters[param_number].EXEC_used : SQL_NTS;
- buffer = opts->parameters[param_number].EXEC_buffer;
- }
- else
- {
- UInt4 bind_size = opts->param_bind_type;
- UInt4 ctypelen;
-
- buffer = opts->parameters[param_number].buffer + offset;
- if (current_row > 0)
- {
- if (bind_size > 0)
- buffer += (bind_size * current_row);
- else if (ctypelen = ctype_length(opts->parameters[param_number].CType), ctypelen > 0)
- buffer += current_row * ctypelen;
- else
- buffer += current_row * opts->parameters[param_number].buflen;
- }
- if (opts->parameters[param_number].used)
- {
- UInt4 p_offset = offset;
- if (bind_size > 0)
- p_offset = offset + bind_size * current_row;
- else
- p_offset = offset + sizeof(SDWORD) * current_row;
- used = *(SDWORD *)((char *)opts->parameters[param_number].used + p_offset);
- }
- else
- used = SQL_NTS;
- }
-
- /* Handle NULL parameter data */
- if (used == SQL_NULL_DATA)
- {
- CVT_APPEND_STR(qb, "NULL");
- return SQL_SUCCESS;
- }
-
- /*
- * If no buffer, and it's not null, then what the hell is it? Just
- * leave it alone then.
- */
- if (!buffer)
- {
- if (0 != (qb->flags & FLGB_PRE_EXECUTING))
- {
- CVT_APPEND_STR(qb, "NULL");
- qb->flags |= FLGB_INACCURATE_RESULT;
- return SQL_SUCCESS;
- }
- else
- {
- CVT_APPEND_CHAR(qb, '?');
- return SQL_SUCCESS;
- }
- }
-
- param_ctype = opts->parameters[param_number].CType;
- param_sqltype = opts->parameters[param_number].SQLType;
-
- mylog("%s: from(fcType)=%d, to(fSqlType)=%d\n", func,
- 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);
-
- allocbuf = buf = NULL;
- param_string[0] = '\0';
- cbuf[0] = '\0';
- memset(&st, 0, sizeof(st));
- t = time(NULL);
- tim = localtime(&t);
- st.m = tim->tm_mon + 1;
- st.d = tim->tm_mday;
- st.y = tim->tm_year + 1900;
-
- /* Convert input C type to a neutral format */
- switch (param_ctype)
- {
- case SQL_C_BINARY:
- case SQL_C_CHAR:
- buf = buffer;
- break;
-
-#ifdef UNICODE_SUPPORT
- case SQL_C_WCHAR:
- buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / 2, &used);
- used *= 2;
- break;
-#endif /* UNICODE_SUPPORT */
-
- 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;
-
-#if (ODBCVER >= 0x0300) && defined(ODBCINT64)
-#ifdef WIN32
- case SQL_C_SBIGINT:
- sprintf(param_string, "%I64d",
- *((SQLBIGINT *) buffer));
- break;
-
- case SQL_C_UBIGINT:
- sprintf(param_string, "%I64u",
- *((SQLUBIGINT *) buffer));
- break;
-
-#endif /* WIN32 */
-#endif /* ODBCINT64 */
- 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;
-
- }
-#if (ODBCVER >= 0x0300)
- case SQL_C_NUMERIC:
- if (ResolveNumericParam((SQL_NUMERIC_STRUCT *) buffer, param_string))
- break;
-#endif
- default:
- /* error */
- qb->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";
- qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
- CVT_TERMINATE(qb); /* just in case */
- 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:
-#ifdef UNICODE_SUPPORT
- case SQL_WCHAR:
- case SQL_WVARCHAR:
- case SQL_WLONGVARCHAR:
-#endif /* UNICODE_SUPPORT */
-
- CVT_APPEND_CHAR(qb, '\''); /* Open Quote */
-
- /* it was a SQL_C_CHAR */
- if (buf)
- CVT_SPECIAL_CHARS(qb, buf, used);
-
- /* it was a numeric type */
- else if (param_string[0] != '\0')
- CVT_APPEND_STR(qb, 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(qb, tmp);
- }
-
- CVT_APPEND_CHAR(qb, '\''); /* 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'::date", st.y, st.m, st.d);
-
- CVT_APPEND_STR(qb, 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'::time", st.hh, st.mm, st.ss);
-
- CVT_APPEND_STR(qb, 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, USE_ZONE, PG_VERSION_GE(conn, 7.2));
- strcat(tmp, "'::timestamp");
-
- CVT_APPEND_STR(qb, tmp);
-
- break;
-
- case SQL_BINARY:
- case SQL_VARBINARY:/* non-ascii characters should be
- * converted to octal */
- CVT_APPEND_CHAR(qb, '\''); /* Open Quote */
-
- mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
-
- CVT_APPEND_BINARY(qb, buf, used);
-
- CVT_APPEND_CHAR(qb, '\''); /* Close Quote */
-
- break;
-
- case SQL_LONGVARBINARY:
-
- if (opts->parameters[param_number].data_at_exec)
- lobj_oid = opts->parameters[param_number].lobj_oid;
- else
- {
- /* begin transaction if needed */
- if (!CC_is_in_trans(conn))
- {
- if (!CC_begin(conn))
- {
- qb->errormsg = "Could not begin (in-line) a transaction";
- qb->errornumber = STMT_EXEC_ERROR;
- return SQL_ERROR;
- }
- }
-
- /* store the oid */
- lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
- if (lobj_oid == 0)
- {
- qb->errornumber = STMT_EXEC_ERROR;
- qb->errormsg = "Couldnt create (in-line) large object.";
- return SQL_ERROR;
- }
-
- /* store the fd */
- lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);
- if (lobj_fd < 0)
- {
- qb->errornumber = STMT_EXEC_ERROR;
- qb->errormsg = "Couldnt open (in-line) large object for writing.";
- 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))
- {
- if (!CC_commit(conn))
- {
- qb->errormsg = "Could not commit (in-line) a transaction";
- qb->errornumber = STMT_EXEC_ERROR;
- return SQL_ERROR;
- }
- }
- }
-
- /*
- * 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(qb, 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(qb, 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(qb, tmp);
- break;
- case SQL_NUMERIC:
- if (buf)
- {
- cbuf[0] = '\'';
- my_strcpy(cbuf + 1, sizeof(cbuf) - 3, buf, used); /* 3 = 1('\'') +
- * strlen("'")
- * + 1('\0') */
- strcat(cbuf, "'");
- }
- else
- sprintf(cbuf, "'%s'", param_string);
- CVT_APPEND_STR(qb, cbuf);
- break;
- default: /* a numeric type or SQL_BIT */
- if (param_sqltype == SQL_BIT)
- CVT_APPEND_CHAR(qb, '\''); /* Open Quote */
-
- if (buf)
- {
- switch (used)
- {
- case SQL_NULL_DATA:
- break;
- case SQL_NTS:
- CVT_APPEND_STR(qb, buf);
- break;
- default:
- CVT_APPEND_DATA(qb, buf, used);
- }
- }
- else
- CVT_APPEND_STR(qb, param_string);
-
- if (param_sqltype == SQL_BIT)
- CVT_APPEND_CHAR(qb, '\''); /* Close Quote */
-
- break;
- }
-#ifdef UNICODE_SUPPORT
- if (allocbuf)
- free(allocbuf);
-#endif /* UNICODE_SUPPORT */
- return SQL_SUCCESS;
-}
-
-
-static const char *
-mapFunction(const char *func, int param_count)
-{
- int i;
-
- for (i = 0; mapFuncs[i][0]; i++)
- {
- if (mapFuncs[i][0][0] == '%')
- {
- if (mapFuncs[i][0][1] - '0' == param_count &&
- !stricmp(mapFuncs[i][0] + 2, func))
- return mapFuncs[i][1];
- }
- else if (!stricmp(mapFuncs[i][0], func))
- return mapFuncs[i][1];
- }
-
- return NULL;
-}
-
-/*
- * processParameters()
- * Process function parameters and work with embedded escapes sequences.
- */
-static int
-processParameters(QueryParse *qp, QueryBuild *qb,
- UInt4 *output_count, Int4 param_pos[][2])
-{
- static const char *func = "processParameters";
- int retval, innerParenthesis, param_count;
- BOOL stop;
-
- /* begin with outer '(' */
- innerParenthesis = 0;
- param_count = 0;
- stop = FALSE;
- for (; F_OldPos(qp) < qp->stmt_len; F_OldNext(qp))
- {
- retval = inner_process_tokens(qp, qb);
- if (retval == SQL_ERROR)
- return retval;
-#ifdef MULTIBYTE
- if (ENCODE_STATUS(qp->encstr) != 0)
- continue;
-#endif
- if (qp->in_dquote || qp->in_quote || qp->in_escape)
- continue;
-
- switch (F_OldChar(qp))
- {
- case ',':
- if (1 == innerParenthesis)
- {
- param_pos[param_count][1] = F_NewPos(qb) - 2;
- param_count++;
- param_pos[param_count][0] = F_NewPos(qb);
- param_pos[param_count][1] = -1;
- }
- break;
- case '(':
- if (0 == innerParenthesis)
- {
- param_pos[param_count][0] = F_NewPos(qb);
- param_pos[param_count][1] = -1;
- }
- innerParenthesis++;
- break;
-
- case ')':
- innerParenthesis--;
- if (0 == innerParenthesis)
- {
- param_pos[param_count][1] = F_NewPos(qb) - 2;
- param_count++;
- param_pos[param_count][0] =
- param_pos[param_count][1] = -1;
- }
- if (output_count)
- *output_count = F_NewPos(qb);
- break;
-
- case '}':
- stop = (0 == innerParenthesis);
- break;
-
- }
- if (stop) /* returns with the last } position */
- break;
- }
- if (param_pos[param_count][0] >= 0)
- {
- mylog("%s closing ) not found %d\n", func, innerParenthesis);
- qb->errornumber = STMT_EXEC_ERROR;
- qb->errormsg = "processParameters closing ) not found";
- return SQL_ERROR;
- }
- else if (1 == param_count) /* the 1 parameter is really valid ? */
- {
- BOOL param_exist = FALSE;
- int i;
-
- for (i = param_pos[0][0]; i <= param_pos[0][1]; i++)
- {
- if (!isspace(qb->query_statement[i]))
- {
- param_exist = TRUE;
- break;
- }
- }
- if (!param_exist)
- {
- param_pos[0][0] = param_pos[0][1] = -1;
- }
- }
-
- return SQL_SUCCESS;
-}
-
-/*
- * convert_escape()
- * This function doesn't return a pointer to static memory any longer !
- */
-static int
-convert_escape(QueryParse *qp, QueryBuild *qb)
-{
- static const char *func = "convert_escape";
- RETCODE retval = SQL_SUCCESS;
- char buf[1024], key[65];
- unsigned char ucv;
- UInt4 prtlen;
-
- if (F_OldChar(qp) == '{') /* skip the first { */
- F_OldNext(qp);
- /* Separate off the key, skipping leading and trailing whitespace */
- while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
- F_OldNext(qp);
- /*
- * procedure calls
- */
- if (qp->statement_type == STMT_TYPE_PROCCALL)
- {
- int lit_call_len = 4;
- ConnectionClass *conn = qb->conn;
-
- /* '?=' to accept return values exists ? */
- if (F_OldChar(qp) == '?')
- {
- qb->param_number++;
- while (isspace((unsigned char) qp->statement[++qp->opos]));
- if (F_OldChar(qp) != '=')
- {
- F_OldPrior(qp);
- return SQL_SUCCESS;
- }
- while (isspace((unsigned char) qp->statement[++qp->opos]));
- }
- if (strnicmp(F_OldPtr(qp), "call", lit_call_len) ||
- !isspace((unsigned char) F_OldPtr(qp)[lit_call_len]))
- {
- F_OldPrior(qp);
- return SQL_SUCCESS;
- }
- qp->opos += lit_call_len;
- CVT_APPEND_STR(qb, "SELECT ");
- if (my_strchr(conn, F_OldPtr(qp), '('))
- qp->proc_no_param = FALSE;
- return SQL_SUCCESS;
- }
-
- sscanf(F_OldPtr(qp), "%32s", key);
- while ((ucv = F_OldChar(qp)) != '\0' && (!isspace(ucv)))
- F_OldNext(qp);
- while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
- F_OldNext(qp);
-
- /* Avoid the concatenation of the function name with the previous word. Aceto */
-
- if (F_NewPos(qb) > 0 && isalnum(F_NewPtr(qb)[-1]))
- CVT_APPEND_CHAR(qb, ' ');
-
- if (strcmp(key, "d") == 0)
- {
- /* Literal; return the escape part adding type cast */
- F_ExtractOldTo(qp, buf, '}', sizeof(buf));
- prtlen = snprintf(buf, sizeof(buf), "%s::date ", buf);
- CVT_APPEND_DATA(qb, buf, prtlen);
- }
- else if (strcmp(key, "t") == 0)
- {
- /* Literal; return the escape part adding type cast */
- F_ExtractOldTo(qp, buf, '}', sizeof(buf));
- prtlen = snprintf(buf, sizeof(buf), "%s::time", buf);
- CVT_APPEND_DATA(qb, buf, prtlen);
- }
- else if (strcmp(key, "ts") == 0)
- {
- /* Literal; return the escape part adding type cast */
- F_ExtractOldTo(qp, buf, '}', sizeof(buf));
- if (PG_VERSION_LT(qb->conn, 7.1))
- prtlen = snprintf(buf, sizeof(buf), "%s::datetime", buf);
- else
- prtlen = snprintf(buf, sizeof(buf), "%s::timestamp", buf);
- CVT_APPEND_DATA(qb, buf, prtlen);
- }
- else if (strcmp(key, "oj") == 0) /* {oj syntax support for 7.1 * servers */
- {
- F_OldPrior(qp);
- return SQL_SUCCESS; /* Continue at inner_process_tokens loop */
- }
- else if (strcmp(key, "fn") == 0)
- {
- QueryBuild nqb;
- const char *mapExpr;
- int i, param_count;
- UInt4 param_consumed;
- Int4 param_pos[16][2];
-
- /* Separate off the func name, skipping leading and trailing whitespace */
- i = 0;
- while ((ucv = F_OldChar(qp)) != '\0' && ucv != '(' &&
- (!isspace(ucv)))
- {
- if (i < sizeof(key)-1)
- key[i++] = ucv;
- F_OldNext(qp);
- }
- key[i] = '\0';
- while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
- F_OldNext(qp);
-
- /*
- * We expect left parenthesis here, else return fn body as-is
- * since it is one of those "function constants".
- */
- if (F_OldChar(qp) != '(')
- {
- CVT_APPEND_STR(qb, key);
- return SQL_SUCCESS;
- }
-
- /*
- * Process parameter list and inner escape
- * sequences
- * Aceto 2002-01-29
- */
-
- QB_initialize_copy(&nqb, qb, 1024);
- if (retval = processParameters(qp, &nqb, &param_consumed, param_pos), retval == SQL_ERROR)
- {
- qb->errornumber = nqb.errornumber;
- qb->errormsg = nqb.errormsg;
- QB_Destructor(&nqb);
- return retval;
- }
-
- for (param_count = 0;; param_count++)
- {
- if (param_pos[param_count][0] < 0)
- break;
- }
- if (param_count == 1 &&
- param_pos[0][1] < param_pos[0][0])
- param_count = 0;
-
- mapExpr = mapFunction(key, param_count);
- if (mapExpr == NULL)
- {
- CVT_APPEND_STR(qb, key);
- CVT_APPEND_DATA(qb, nqb.query_statement, nqb.npos);
- }
- else
- {
- const char *mapptr;
- int from, to, pidx, paramlen;
-
- for (prtlen = 0, mapptr = mapExpr; *mapptr; mapptr++)
- {
- if (*mapptr != '$')
- {
- CVT_APPEND_CHAR(qb, *mapptr);
- continue;
- }
- mapptr++;
- if (*mapptr == '*')
- {
- from = 1;
- to = param_consumed - 2;
- }
- else if (isdigit(*mapptr))
- {
- pidx = *mapptr - '0' - 1;
- if (pidx < 0 ||
- param_pos[pidx][0] < 0)
- {
- qb->errornumber = STMT_EXEC_ERROR;
- qb->errormsg = "param not found";
- qlog("%s %dth param not found for the expression %s\n", pidx + 1, mapExpr);
- retval = SQL_ERROR;
- break;
- }
- from = param_pos[pidx][0];
- to = param_pos[pidx][1];
- }
- else
- {
- qb->errornumber = STMT_EXEC_ERROR;
- qb->errormsg = "internal expression error";
- qlog("%s internal expression error %s\n", func, mapExpr);
- retval = SQL_ERROR;
- break;
- }
- paramlen = to - from + 1;
- if (paramlen > 0)
- CVT_APPEND_DATA(qb, nqb.query_statement+ from, paramlen);
- }
- }
- if (0 == qb->errornumber)
- {
- qb->errornumber = nqb.errornumber;
- qb->errormsg = nqb.errormsg;
- }
- if (SQL_ERROR != retval)
- {
- qb->param_number = nqb.param_number;
- qb->flags = nqb.flags;
- }
- QB_Destructor(&nqb);
- }
- else
- {
- /* Bogus key, leave untranslated */
- return SQL_ERROR;
- }
-
- return retval;
-}
-
-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(const char *buf, SIMPLE_TIME *st)
-{
- int y,
- m,
- d,
- hh,
- mm,
- ss;
- int nf;
-
- y = m = d = hh = mm = ss = 0;
- st->fr = 0;
- st->infinity = 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 convlf, 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 (convlf && 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, BOOL convlf, int ccsc)
-{
- size_t i = 0,
- out = 0,
- max;
- char *p = NULL;
-#ifdef MULTIBYTE
- encoded_str encstr;
-#endif
-
-
- if (used == SQL_NTS)
- max = strlen(si);
- else
- max = used;
- if (dst)
- {
- p = dst;
- p[0] = '\0';
- }
-#ifdef MULTIBYTE
- encoded_str_constr(&encstr, ccsc, si);
-#endif
-
- for (i = 0; i < max && si[i]; i++)
- {
-#ifdef MULTIBYTE
- encoded_nextchar(&encstr);
- if (ENCODE_STATUS(encstr) != 0)
- {
- if (p)
- p[out] = si[i];
- out++;
- continue;
- }
-#endif
- if (convlf && 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] - '0') << (3 * (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 << (4 * (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) + '0';
- 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);
- ARDFields *opts = SC_get_ARD(stmt);
- int factor = (fCType == SQL_C_CHAR ? 2 : 1);
-
- /* If using SQLGetData, then current_col will be set */
- if (stmt->current_col >= 0)
- {
- bindInfo = &opts->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))
- {
- if (!CC_begin(conn))
- {
- stmt->errormsg = "Could not begin (in-line) a transaction";
- stmt->errornumber = STMT_EXEC_ERROR;
- return COPY_GENERAL_ERROR;
- }
- }
-
- 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))
- {
- if (!CC_commit(conn))
- {
- stmt->errormsg = "Could not commit (in-line) a transaction";
- stmt->errornumber = STMT_EXEC_ERROR;
- return COPY_GENERAL_ERROR;
- }
- }
-
- 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))
- {
- if (!CC_commit(conn))
- {
- stmt->errormsg = "Could not commit (in-line) a transaction";
- stmt->errornumber = STMT_EXEC_ERROR;
- return COPY_GENERAL_ERROR;
- }
- }
-
- stmt->lobj_fd = -1; /* prevent further reading */
- }
-
- return result;
-}
diff --git a/src/interfaces/odbc/convert.h b/src/interfaces/odbc/convert.h
deleted file mode 100644
index 8f65472e1f2..00000000000
--- a/src/interfaces/odbc/convert.h
+++ /dev/null
@@ -1,56 +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
-/* convert_escape results */
-#define CONVERT_ESCAPE_OK 0
-#define CONVERT_ESCAPE_OVERFLOW 1
-#define CONVERT_ESCAPE_ERROR -1
-
-typedef struct
-{
- int infinity;
- 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);
-BOOL convert_money(const char *s, char *sout, size_t soutmax);
-char parse_datetime(const char *buf, SIMPLE_TIME *st);
-int convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
-int convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
-
-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/descriptor.h b/src/interfaces/odbc/descriptor.h
deleted file mode 100644
index c3f016a7dca..00000000000
--- a/src/interfaces/odbc/descriptor.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* File: descriptor.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: descriptor.h,v 1.6 2002/06/06 04:50:47 inoue Exp $
- *
- */
-
-#ifndef __DESCRIPTOR_H__
-#define __DESCRIPTOR_H__
-
-#include "psqlodbc.h"
-
-typedef struct
-{
- COL_INFO *col_info; /* cached SQLColumns info for this table */
- char schema[MAX_SCHEMA_LEN + 1];
- char name[MAX_TABLE_LEN + 1];
- char alias[MAX_TABLE_LEN + 1];
- char updatable;
-} TABLE_INFO;
-
-typedef struct
-{
- TABLE_INFO *ti; /* resolve to explicit table names */
- int column_size; /* precision in 2.x */
- int decimal_digits; /* scale in 2.x */
- int display_size;
- int length;
- int type;
- char nullable;
- char func;
- char expr;
- char quote;
- char dquote;
- char numeric;
- char updatable;
- char dot[MAX_TABLE_LEN + 1];
- char name[MAX_COLUMN_LEN + 1];
- char alias[MAX_COLUMN_LEN + 1];
- char *schema;
-} FIELD_INFO;
-Int4 FI_precision(const FIELD_INFO *);
-Int4 FI_scale(const FIELD_INFO *);
-
-struct ARDFields_
-{
- StatementClass *stmt;
- int rowset_size;
- int bind_size; /* size of each structure if using Row
- * Binding */
- UInt2 *row_operation_ptr;
- UInt4 *row_offset_ptr;
- BindInfoClass *bookmark;
- BindInfoClass *bindings;
- int allocated;
-};
-
-struct APDFields_
-{
- StatementClass *stmt;
- int paramset_size;
- int param_bind_type; /* size of each structure if using Param
- * Binding */
- UInt2 *param_operation_ptr;
- UInt4 *param_offset_ptr;
- ParameterInfoClass *parameters;
- int allocated;
-};
-
-struct IRDFields_
-{
- StatementClass *stmt;
- UInt4 *rowsFetched;
- UInt2 *rowStatusArray;
- UInt4 nfields;
- FIELD_INFO **fi;
-};
-
-struct IPDFields_
-{
- StatementClass *stmt;
- UInt4 *param_processed_ptr;
- UInt2 *param_status_ptr;
-};
-
-void InitializeARDFields(ARDFields *self);
-void InitializeAPDFields(APDFields *self);
-/* void InitializeIRDFields(IRDFields *self);
-void InitializeIPDFiedls(IPDFields *self); */
-void ARDFields_free(ARDFields *self);
-void APDFields_free(APDFields *self);
-void IRDFields_free(IRDFields *self);
-void IPDFields_free(IPDFields *self);
-void ARD_unbind_cols(ARDFields *self, BOOL freeall);
-void APD_free_params(APDFields *self, char option);
-#if (ODBCVER >= 0x0300)
-void Desc_set_error(SQLHDESC hdesc, int errornumber, const char * errormsg);
-#endif /* ODBCVER */
-
-#endif
diff --git a/src/interfaces/odbc/dlg_specific.c b/src/interfaces/odbc/dlg_specific.c
deleted file mode 100644
index 4f96a6f7c56..00000000000
--- a/src/interfaces/odbc/dlg_specific.c
+++ /dev/null
@@ -1,971 +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;
-
-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],
- ";%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d",
- INI_READONLY,
- ci->onlyread,
- INI_PROTOCOL,
- ci->protocol,
- INI_FAKEOIDINDEX,
- ci->fake_oid_index,
- INI_SHOWOIDCOLUMN,
- ci->show_oid_column,
- INI_ROWVERSIONING,
- ci->row_versioning,
- INI_SHOWSYSTEMTABLES,
- ci->show_system_tables,
- INI_CONNSETTINGS,
- encoded_conn_settings,
- INI_FETCH,
- ci->drivers.fetch_max,
- INI_SOCKET,
- ci->drivers.socket_buffersize,
- INI_UNKNOWNSIZES,
- ci->drivers.unknown_sizes,
- INI_MAXVARCHARSIZE,
- ci->drivers.max_varchar_size,
- INI_MAXLONGVARCHARSIZE,
- ci->drivers.max_longvarchar_size,
- INI_DEBUG,
- ci->drivers.debug,
- INI_COMMLOG,
- ci->drivers.commlog,
- INI_OPTIMIZER,
- ci->drivers.disable_optimizer,
- INI_KSQO,
- ci->drivers.ksqo,
- INI_USEDECLAREFETCH,
- ci->drivers.use_declarefetch,
- INI_TEXTASLONGVARCHAR,
- ci->drivers.text_as_longvarchar,
- INI_UNKNOWNSASLONGVARCHAR,
- ci->drivers.unknowns_as_longvarchar,
- INI_BOOLSASCHAR,
- ci->drivers.bools_as_char,
- INI_PARSE,
- ci->drivers.parse,
- INI_CANCELASFREESTMT,
- ci->drivers.cancel_as_freestmt,
- INI_EXTRASYSTABLEPREFIXES,
- ci->drivers.extra_systable_prefixes,
- INI_LFCONVERSION,
- ci->lf_conversion,
- INI_UPDATABLECURSORS,
- ci->allow_keyset,
- INI_DISALLOWPREMATURE,
- ci->disallow_premature,
- INI_TRUEISMINUS1,
- ci->true_is_minus1,
- INI_INT8AS,
- ci->true_is_minus1);
- /* Abbrebiation is needed ? */
- if (abbrev || strlen(connect_string) >= len)
- {
- unsigned long flag = 0;
- if (ci->disallow_premature)
- flag |= BIT_DISALLOWPREMATURE;
- if (ci->allow_keyset)
- flag |= BIT_UPDATABLECURSORS;
- if (ci->lf_conversion)
- flag |= BIT_LFCONVERSION;
- if (ci->drivers.unique_index)
- flag |= BIT_UNIQUEINDEX;
- if (strncmp(ci->protocol, PG64, strlen(PG64)) == 0)
- flag |= BIT_PROTOCOL_64;
- else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
- flag |= BIT_PROTOCOL_63;
- switch (ci->drivers.unknown_sizes)
- {
- case UNKNOWNS_AS_DONTKNOW:
- flag |= BIT_UNKNOWN_DONTKNOW;
- break;
- case UNKNOWNS_AS_MAX:
- flag |= BIT_UNKNOWN_ASMAX;
- break;
- }
- if (ci->drivers.disable_optimizer)
- flag |= BIT_OPTIMIZER;
- if (ci->drivers.ksqo)
- flag |= BIT_KSQO;
- if (ci->drivers.commlog)
- flag |= BIT_COMMLOG;
- if (ci->drivers.debug)
- flag |= BIT_DEBUG;
- if (ci->drivers.parse)
- flag |= BIT_PARSE;
- if (ci->drivers.cancel_as_freestmt)
- flag |= BIT_CANCELASFREESTMT;
- if (ci->drivers.use_declarefetch)
- flag |= BIT_USEDECLAREFETCH;
- if (ci->onlyread[0] == '1')
- flag |= BIT_READONLY;
- if (ci->drivers.text_as_longvarchar)
- flag |= BIT_TEXTASLONGVARCHAR;
- if (ci->drivers.unknowns_as_longvarchar)
- flag |= BIT_UNKNOWNSASLONGVARCHAR;
- if (ci->drivers.bools_as_char)
- flag |= BIT_BOOLSASCHAR;
- if (ci->row_versioning[0] == '1')
- flag |= BIT_ROWVERSIONING;
- if (ci->show_system_tables[0] == '1')
- flag |= BIT_SHOWSYSTEMTABLES;
- if (ci->show_oid_column[0] == '1')
- flag |= BIT_SHOWOIDCOLUMN;
- if (ci->fake_oid_index[0] == '1')
- flag |= BIT_FAKEOIDINDEX;
- if (ci->true_is_minus1)
- flag |= BIT_TRUEISMINUS1;
-
- sprintf(&connect_string[hlen],
- ";A6=%s;A7=%d;A8=%d;B0=%d;B1=%d;%s=%d;C2=%s;CX=%02x%lx",
- encoded_conn_settings,
- ci->drivers.fetch_max,
- ci->drivers.socket_buffersize,
- ci->drivers.max_varchar_size,
- ci->drivers.max_longvarchar_size,
- INI_INT8AS,
- ci->int8_as,
- ci->drivers.extra_systable_prefixes,
- EFFECTIVE_BIT_COUNT,
- flag);
- }
-}
-
-static void
-unfoldCXAttribute(ConnInfo *ci, const char *value)
-{
- int count;
- unsigned long flag;
-
- if (strlen(value) < 2)
- {
- count = 3;
- sscanf(value, "%lx", &flag);
- }
- else
- {
- char cnt[8];
- memcpy(cnt, value, 2);
- cnt[2] = '\0';
- sscanf(cnt, "%x", &count);
- sscanf(value + 2, "%lx", &flag);
- }
- ci->disallow_premature = (char)((flag & BIT_DISALLOWPREMATURE) != 0);
- ci->allow_keyset = (char)((flag & BIT_UPDATABLECURSORS) != 0);
- ci->lf_conversion = (char)((flag & BIT_LFCONVERSION) != 0);
- if (count < 4)
- return;
- ci->drivers.unique_index = (char)((flag & BIT_UNIQUEINDEX) != 0);
- if ((flag & BIT_PROTOCOL_64) != 0)
- strcpy(ci->protocol, PG64);
- else if ((flag & BIT_PROTOCOL_63) != 0)
- strcpy(ci->protocol, PG63);
- else
- strcpy(ci->protocol, PG62);
- if ((flag & BIT_UNKNOWN_DONTKNOW) != 0)
- ci->drivers.unknown_sizes = UNKNOWNS_AS_DONTKNOW;
- else if ((flag & BIT_UNKNOWN_ASMAX) != 0)
- ci->drivers.unknown_sizes = UNKNOWNS_AS_MAX;
- else
- ci->drivers.unknown_sizes = UNKNOWNS_AS_LONGEST;
- ci->drivers.disable_optimizer = (char)((flag & BIT_OPTIMIZER) != 0);
- ci->drivers.ksqo = (char)((flag & BIT_KSQO) != 0);
- ci->drivers.commlog = (char)((flag & BIT_COMMLOG) != 0);
- ci->drivers.debug = (char)((flag & BIT_DEBUG) != 0);
- ci->drivers.parse = (char)((flag & BIT_PARSE) != 0);
- ci->drivers.cancel_as_freestmt = (char)((flag & BIT_CANCELASFREESTMT) != 0);
- ci->drivers.use_declarefetch = (char)((flag & BIT_USEDECLAREFETCH) != 0);
- sprintf(ci->onlyread, "%d", (char)((flag & BIT_READONLY) != 0));
- ci->drivers.text_as_longvarchar = (char)((flag & BIT_TEXTASLONGVARCHAR) !=0);
- ci->drivers.unknowns_as_longvarchar = (char)((flag & BIT_UNKNOWNSASLONGVARCHAR) !=0);
- ci->drivers.bools_as_char = (char)((flag & BIT_BOOLSASCHAR) != 0);
- sprintf(ci->row_versioning, "%d", (char)((flag & BIT_ROWVERSIONING) != 0));
- sprintf(ci->show_system_tables, "%d", (char)((flag & BIT_SHOWSYSTEMTABLES) != 0));
- sprintf(ci->show_oid_column, "%d", (char)((flag & BIT_SHOWOIDCOLUMN) != 0));
- sprintf(ci->fake_oid_index, "%d", (char)((flag & BIT_FAKEOIDINDEX) != 0));
- ci->true_is_minus1 = (char)((flag & BIT_TRUEISMINUS1) != 0);
-}
-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->allow_keyset = atoi(value);
- else if (stricmp(attribute, INI_LFCONVERSION) == 0)
- ci->lf_conversion = atoi(value);
- else if (stricmp(attribute, INI_TRUEISMINUS1) == 0)
- ci->true_is_minus1 = atoi(value);
- else if (stricmp(attribute, INI_INT8AS) == 0)
- ci->int8_as = atoi(value);
- else if (stricmp(attribute, "CX") == 0)
- unfoldCXAttribute(ci, 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);
-
- if (ci->disallow_premature < 0)
- ci->disallow_premature = DEFAULT_DISALLOWPREMATURE;
- if (ci->allow_keyset < 0)
- ci->allow_keyset = DEFAULT_UPDATABLECURSORS;
- if (ci->lf_conversion < 0)
- ci->lf_conversion = DEFAULT_LFCONVERSION;
- if (ci->true_is_minus1 < 0)
- ci->true_is_minus1 = DEFAULT_TRUEISMINUS1;
- if (ci->int8_as < -100)
- ci->int8_as = DEFAULT_INT8AS;
-}
-
-
-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.
- */
- 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);
- if (temp[0])
- ci->disallow_premature = atoi(temp);
- }
-
- if (ci->allow_keyset < 0 || overwrite)
- {
- SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI);
- if (temp[0])
- ci->allow_keyset = atoi(temp);
- }
-
- if (ci->lf_conversion < 0 || overwrite)
- {
- SQLGetPrivateProfileString(DSN, INI_LFCONVERSION, "", temp, sizeof(temp), ODBC_INI);
- if (temp[0])
- ci->lf_conversion = atoi(temp);
- }
-
- if (ci->true_is_minus1 < 0 || overwrite)
- {
- SQLGetPrivateProfileString(DSN, INI_TRUEISMINUS1, "", temp, sizeof(temp), ODBC_INI);
- if (temp[0])
- ci->true_is_minus1 = atoi(temp);
- }
-
- if (ci->int8_as < -100 || overwrite)
- {
- SQLGetPrivateProfileString(DSN, INI_INT8AS, "", temp, sizeof(temp), ODBC_INI);
- if (temp[0])
- ci->int8_as = 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 function writes any global parameters (that can be manipulated)
- * to the ODBCINST.INI portion of the registry
- */
-void
-writeDriverCommoninfo(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);
-
- sprintf(tmp, "%d", comval->unique_index);
- SQLWritePrivateProfileString(sectionName, INI_UNIQUEINDEX, tmp, fileName);
- /*
- * Never update the onlyread from this module.
- */
- if (!ci)
- {
- 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);
- */
-}
-
-/* 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->allow_keyset);
- SQLWritePrivateProfileString(DSN,
- INI_UPDATABLECURSORS,
- temp,
- ODBC_INI);
- sprintf(temp, "%d", ci->lf_conversion);
- SQLWritePrivateProfileString(DSN,
- INI_LFCONVERSION,
- temp,
- ODBC_INI);
- sprintf(temp, "%d", ci->true_is_minus1);
- SQLWritePrivateProfileString(DSN,
- INI_TRUEISMINUS1,
- temp,
- ODBC_INI);
- sprintf(temp, "%d", ci->int8_as);
- SQLWritePrivateProfileString(DSN,
- INI_INT8AS,
- 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/dlg_specific.h b/src/interfaces/odbc/dlg_specific.h
deleted file mode 100644
index 99005d3a338..00000000000
--- a/src/interfaces/odbc/dlg_specific.h
+++ /dev/null
@@ -1,200 +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 <windowsx.h>
-#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"
-#define INI_LFCONVERSION "LFConversion"
-#define INI_TRUEISMINUS1 "TrueIsMinus1"
-#define INI_INT8AS "BI"
-/* Bit representaion for abbreviated connection strings */
-#define BIT_LFCONVERSION (1L)
-#define BIT_UPDATABLECURSORS (1L<<1)
-#define BIT_DISALLOWPREMATURE (1L<<2)
-#define BIT_UNIQUEINDEX (1L<<3)
-#define BIT_PROTOCOL_63 (1L<<4)
-#define BIT_PROTOCOL_64 (1L<<5)
-#define BIT_UNKNOWN_DONTKNOW (1L<<6)
-#define BIT_UNKNOWN_ASMAX (1L<<7)
-#define BIT_OPTIMIZER (1L<<8)
-#define BIT_KSQO (1L<<9)
-#define BIT_COMMLOG (1L<<10)
-#define BIT_DEBUG (1L<<11)
-#define BIT_PARSE (1L<<12)
-#define BIT_CANCELASFREESTMT (1L<<13)
-#define BIT_USEDECLAREFETCH (1L<<14)
-#define BIT_READONLY (1L<<15)
-#define BIT_TEXTASLONGVARCHAR (1L<<16)
-#define BIT_UNKNOWNSASLONGVARCHAR (1L<<17)
-#define BIT_BOOLSASCHAR (1L<<18)
-#define BIT_ROWVERSIONING (1L<<19)
-#define BIT_SHOWSYSTEMTABLES (1L<<20)
-#define BIT_SHOWOIDCOLUMN (1L<<21)
-#define BIT_FAKEOIDINDEX (1L<<22)
-#define BIT_TRUEISMINUS1 (1L<<23)
-
-#define EFFECTIVE_BIT_COUNT 24
-
-
-/* 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_;"
-
-#define DEFAULT_DISALLOWPREMATURE 0
-#define DEFAULT_TRUEISMINUS1 0
-#ifdef DRIVER_CURSOR_IMPLEMENT
-#define DEFAULT_UPDATABLECURSORS 1
-#else
-#define DEFAULT_UPDATABLECURSORS 0
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-#ifdef WIN32
-#define DEFAULT_LFCONVERSION 1
-#else
-#define DEFAULT_LFCONVERSION 0
-#endif /* WIN32 */
-#define DEFAULT_INT8AS 0
-
-/* 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,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam);
-int CALLBACK global_optionsProc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam);
-int CALLBACK ds_options1Proc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam);
-int CALLBACK ds_options2Proc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam);
-#endif /* WIN32 */
-
-void updateGlobals(void);
-void writeDriverCommoninfo(const ConnInfo *ci);
-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/dlg_wingui.c b/src/interfaces/odbc/dlg_wingui.c
deleted file mode 100644
index 88c2e9f4c45..00000000000
--- a/src/interfaces/odbc/dlg_wingui.c
+++ /dev/null
@@ -1,523 +0,0 @@
-#ifdef WIN32
-/*-------
- * Module: dlg_wingui.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;
-
-extern HINSTANCE NEAR s_hModule;
-static int driver_optionsDraw(HWND, const ConnInfo *, int src, BOOL enable);
-static int driver_options_update(HWND hdlg, ConnInfo *ci, BOOL);
-
-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;
- }
-
- ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL2), enable ? SW_SHOW : SW_HIDE);
- CheckDlgButton(hdlg, DRV_COMMLOG, comval->commlog);
-#ifndef Q_LOG
- EnableWindow(GetDlgItem(hdlg, DRV_COMMLOG), FALSE);
-#endif /* Q_LOG */
- 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);
-#ifndef MY_LOG
- EnableWindow(GetDlgItem(hdlg, DRV_DEBUG), FALSE);
-#endif /* MY_LOG */
- 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);
- ShowWindow(GetDlgItem(hdlg, IDPREVPAGE), enable ? SW_HIDE : SW_SHOW);
- ShowWindow(GetDlgItem(hdlg, IDNEXTPAGE), enable ? SW_HIDE : SW_SHOW);
- 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);
- comval->unique_index = IsDlgButtonChecked(hdlg, DRV_UNIQUEINDEX);
- if (!ci)
- {
- 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)
- writeDriverCommoninfo(ci);
-
- /* fall through */
- return 0;
-}
-
-int CALLBACK
-driver_optionsProc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- ConnInfo *ci;
-
- switch (wMsg)
- {
- case WM_INITDIALOG:
- SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK etc */
- ci = (ConnInfo *) lParam;
- SetWindowText(hdlg, "Advanced Options (Default)");
- SetWindowText(GetDlgItem(hdlg, IDOK), "Save");
- ShowWindow(GetDlgItem(hdlg, IDAPPLY), SW_HIDE);
- driver_optionsDraw(hdlg, ci, 0, TRUE);
- break;
-
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam))
- {
- case IDOK:
- ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
- driver_options_update(hdlg, NULL,
- ci && ci->dsn && ci->dsn[0]);
-
- case IDCANCEL:
- EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
- return TRUE;
-
- case IDDEFAULTS:
- driver_optionsDraw(hdlg, NULL, 2, TRUE);
- break;
- }
- }
-
- return FALSE;
-}
-
-int CALLBACK
-global_optionsProc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
-
- switch (wMsg)
- {
- case WM_INITDIALOG:
- CheckDlgButton(hdlg, DRV_COMMLOG, globals.commlog);
-#ifndef Q_LOG
- EnableWindow(GetDlgItem(hdlg, DRV_COMMLOG), FALSE);
-#endif /* Q_LOG */
- CheckDlgButton(hdlg, DRV_DEBUG, globals.debug);
-#ifndef MY_LOG
- EnableWindow(GetDlgItem(hdlg, DRV_DEBUG), FALSE);
-#endif /* MY_LOG */
- break;
-
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam))
- {
- case IDOK:
- globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
- globals.debug = IsDlgButtonChecked(hdlg, DRV_DEBUG);
- driver_options_update(hdlg, NULL, TRUE);
-
- case IDCANCEL:
- EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-int CALLBACK
-ds_options1Proc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- ConnInfo *ci;
-
- switch (wMsg)
- {
- case WM_INITDIALOG:
- SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK etc */
- ci = (ConnInfo *) lParam;
- if (ci && ci->dsn && ci->dsn[0])
- SetWindowText(hdlg, "Advanced Options (DSN 1/2)");
- else
- {
- SetWindowText(hdlg, "Advanced Options (Connection 1/2)");
- ShowWindow(GetDlgItem(hdlg, IDAPPLY), SW_HIDE);
- }
- driver_optionsDraw(hdlg, ci, 1, FALSE);
- break;
-
- case WM_COMMAND:
- ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
- switch (GET_WM_COMMAND_ID(wParam, lParam))
- {
- case IDOK:
- driver_options_update(hdlg, ci, FALSE);
-
- case IDCANCEL:
- EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
- return TRUE;
-
- case IDAPPLY:
- driver_options_update(hdlg, ci, FALSE);
- SendMessage(GetWindow(hdlg, GW_OWNER), WM_COMMAND, wParam, lParam);
- break;
-
- case IDDEFAULTS:
- driver_optionsDraw(hdlg, ci, 0, FALSE);
- break;
-
- case IDNEXTPAGE:
- driver_options_update(hdlg, ci, FALSE);
-
- EndDialog(hdlg, FALSE);
- DialogBoxParam(s_hModule,
- MAKEINTRESOURCE(DLG_OPTIONS_DS),
- hdlg, ds_options2Proc, (LPARAM)
-ci);
- break;
- }
- }
-
- return FALSE;
-}
-
-
-int CALLBACK
-ds_options2Proc(HWND hdlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- ConnInfo *ci;
- char buf[128];
- DWORD cmd;
-
- 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 2/2)");
- ShowWindow(GetDlgItem(hdlg, IDAPPLY), SW_HIDE); }
- else
- {
- sprintf(buf, "Advanced Options (%s) 2/2", 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);
-
- /* Int8 As */
- switch (ci->int8_as)
- {
- case SQL_BIGINT:
- CheckDlgButton(hdlg, DS_INT8_AS_BIGINT, 1);
- break;
- case SQL_NUMERIC:
- CheckDlgButton(hdlg, DS_INT8_AS_NUMERIC, 1);
- break;
- case SQL_VARCHAR:
- CheckDlgButton(hdlg, DS_INT8_AS_VARCHAR, 1);
- break;
- case SQL_DOUBLE:
- CheckDlgButton(hdlg, DS_INT8_AS_DOUBLE, 1);
- break;
- case SQL_INTEGER:
- CheckDlgButton(hdlg, DS_INT8_AS_INT4, 1);
- break;
- default:
- CheckDlgButton(hdlg, DS_INT8_AS_DEFAULT, 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);
- CheckDlgButton(hdlg, DS_LFCONVERSION, ci->lf_conversion);
- CheckDlgButton(hdlg, DS_TRUEISMINUS1, ci->true_is_minus1);
- CheckDlgButton(hdlg, DS_UPDATABLECURSORS, ci->allow_keyset);
-#ifndef DRIVER_CURSOR_IMPLEMENT
- EnableWindow(GetDlgItem(hdlg, DS_UPDATABLECURSORS), FALSE);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-
- 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 (cmd = 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:
- case IDAPPLY:
- case IDPREVPAGE:
- 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);
-
- /* Int8 As */
- if (IsDlgButtonChecked(hdlg, DS_INT8_AS_DEFAULT))
- ci->int8_as = 0;
- else if (IsDlgButtonChecked(hdlg, DS_INT8_AS_BIGINT))
- ci->int8_as = SQL_BIGINT;
- else if (IsDlgButtonChecked(hdlg, DS_INT8_AS_NUMERIC))
- ci->int8_as = SQL_NUMERIC;
- else if (IsDlgButtonChecked(hdlg, DS_INT8_AS_DOUBLE))
- ci->int8_as = SQL_DOUBLE;
- else if (IsDlgButtonChecked(hdlg, DS_INT8_AS_INT4))
- ci->int8_as = SQL_INTEGER;
- else
- ci->int8_as = SQL_VARCHAR;
-
- 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);
- ci->lf_conversion = IsDlgButtonChecked(hdlg, DS_LFCONVERSION);
- ci->true_is_minus1 = IsDlgButtonChecked(hdlg, DS_TRUEISMINUS1);
-#ifdef DRIVER_CURSOR_IMPLEMENT
- ci->allow_keyset = IsDlgButtonChecked(hdlg, DS_UPDATABLECURSORS);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-
- /* 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));
- if (IDAPPLY == cmd)
- {
- SendMessage(GetWindow(hdlg, GW_OWNER), WM_COMMAND, wParam, lParam);
- break;
- }
-
- EndDialog(hdlg, cmd == IDOK);
- if (IDOK == cmd)
- return TRUE;
- DialogBoxParam(s_hModule,
- MAKEINTRESOURCE(DLG_OPTIONS_DRV),
- hdlg, ds_options1Proc, (LPARAM) ci);
- break;
-
- case IDCANCEL:
- EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-#endif /* WIN32 */
diff --git a/src/interfaces/odbc/drvconn.c b/src/interfaces/odbc/drvconn.c
deleted file mode 100644
index 6c08376ac4b..00000000000
--- a/src/interfaces/odbc/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 <stdio.h>
-#include <stdlib.h>
-
-#include "connection.h"
-
-#ifndef WIN32
-#include <sys/types.h>
-#include <sys/socket.h>
-#define NEAR
-#else
-#include <winsock.h>
-#endif
-
-#include <string.h>
-
-#ifdef WIN32
-#include <windowsx.h>
-#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 salt[5];
- char password_required = AUTH_REQ_OK;
- 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);
- salt[0] = '\0';
-
-#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, salt);
- 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 = -retval;
- 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);
- ShowWindow(GetDlgItem(hdlg, IDC_DRIVER), 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_DATASOURCE:
- ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
- DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
- hdlg, ds_options1Proc, (LPARAM) ci);
- break;
-
- case IDC_DRIVER:
- ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
- DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
- hdlg, driver_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;
-
- CC_conninfo_init(ci);
-
- 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/environ.c b/src/interfaces/odbc/environ.c
deleted file mode 100644
index 9ac8f8eb6cf..00000000000
--- a/src/interfaces/odbc/environ.c
+++ /dev/null
@@ -1,661 +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 <stdlib.h>
-#include <string.h>
-#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;
-}
-
-
-static void
-pg_sqlstate_set(const EnvironmentClass *env, UCHAR *szSqlState, const UCHAR *ver3str, const UCHAR *ver2str)
-{
- strcpy(szSqlState, EN_is_odbc3(env) ? ver3str : ver2str);
-}
-
-#define DRVMNGRDIV 511
-/* Returns the next SQL error information. */
-RETCODE SQL_API
-PGAPI_StmtError( HSTMT hstmt,
- SWORD RecNumber,
- UCHAR FAR * szSqlState,
- SDWORD FAR * pfNativeError,
- UCHAR FAR * szErrorMsg,
- SWORD cbErrorMsgMax,
- SWORD FAR * pcbErrorMsg,
- UWORD flag)
-{
- /* CC: return an error of a hstmt */
- StatementClass *stmt = (StatementClass *) hstmt;
- EnvironmentClass *env = (EnvironmentClass *) SC_get_conn(stmt)->henv;
- char *msg;
- int status;
- BOOL partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),
- clear_str = ((flag & PODBC_ERROR_CLEAR) != 0);
- SWORD msglen, stapos, wrtlen, pcblen;
-
- mylog("**** PGAPI_StmtError: hstmt=%u <%d>\n", hstmt, cbErrorMsgMax);
-
- if (cbErrorMsgMax < 0)
- return SQL_ERROR;
-
- if (!SC_get_error(stmt, &status, &msg) || NULL == msg || !msg[0])
- {
- mylog("SC_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;
- }
- mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
- msglen = (SWORD) strlen(msg);
- /*
- * Even though an application specifies a larger error message
- * buffer, the driver manager changes it silently.
- * Therefore we divide the error message into ...
- */
- if (stmt->error_recsize < 0)
- {
- if (cbErrorMsgMax > 0)
- stmt->error_recsize = cbErrorMsgMax - 1; /* apply the first request */
- else
- stmt->error_recsize = DRVMNGRDIV;
- }
- if (RecNumber < 0)
- {
- if (0 == stmt->errorpos)
- RecNumber = 1;
- else
- RecNumber = 2 + (stmt->errorpos - 1) / stmt->error_recsize;
- }
- stapos = (RecNumber - 1) * stmt->error_recsize;
- if (stapos > msglen)
- return SQL_NO_DATA_FOUND;
- pcblen = wrtlen = msglen - stapos;
- if (pcblen > stmt->error_recsize)
- pcblen = stmt->error_recsize;
- if (0 == cbErrorMsgMax)
- wrtlen = 0;
- else if (wrtlen >= cbErrorMsgMax)
- {
- if (partial_ok)
- wrtlen = cbErrorMsgMax - 1;
- else if (cbErrorMsgMax <= stmt->error_recsize)
- wrtlen = 0;
- else
- wrtlen = stmt->error_recsize;
- }
- if (wrtlen > pcblen)
- wrtlen = pcblen;
- if (NULL != pcbErrorMsg)
- *pcbErrorMsg = pcblen;
-
- if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
- {
- memcpy(szErrorMsg, msg + stapos, wrtlen);
- szErrorMsg[wrtlen] = '\0';
- }
-
- if (NULL != pfNativeError)
- *pfNativeError = status;
-
- if (NULL != szSqlState)
-
- switch (status)
- {
- /* now determine the SQLSTATE to be returned */
- case STMT_ROW_VERSION_CHANGED:
- pg_sqlstate_set(env, szSqlState, "01001", "01001");
- /* data truncated */
- break;
- case STMT_TRUNCATED:
- pg_sqlstate_set(env, szSqlState, "01004", "01004");
- /* data truncated */
- break;
- case STMT_INFO_ONLY:
- pg_sqlstate_set(env, szSqlState, "00000", "0000");
- /* just information that is returned, no error */
- break;
- case STMT_BAD_ERROR:
- pg_sqlstate_set(env, szSqlState, "08S01", "08S01");
- /* communication link failure */
- break;
- case STMT_CREATE_TABLE_ERROR:
- pg_sqlstate_set(env, szSqlState, "42S01", "S0001");
- /* table already exists */
- break;
- case STMT_STATUS_ERROR:
- case STMT_SEQUENCE_ERROR:
- pg_sqlstate_set(env, szSqlState, "HY010", "S1010");
- /* Function sequence error */
- break;
- case STMT_NO_MEMORY_ERROR:
- pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
- /* memory allocation failure */
- break;
- case STMT_COLNUM_ERROR:
- pg_sqlstate_set(env, szSqlState, "07009", "S1002");
- /* invalid column number */
- break;
- case STMT_NO_STMTSTRING:
- pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
- /* having no stmtstring is also a malloc problem */
- break;
- case STMT_ERROR_TAKEN_FROM_BACKEND:
- pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
- /* general error */
- break;
- case STMT_INTERNAL_ERROR:
- pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
- /* general error */
- break;
- case STMT_FETCH_OUT_OF_RANGE:
- pg_sqlstate_set(env, szSqlState, "HY106", "S1106");
- break;
-
- case STMT_ROW_OUT_OF_RANGE:
- pg_sqlstate_set(env, szSqlState, "HY107", "S1107");
- break;
-
- case STMT_OPERATION_CANCELLED:
- pg_sqlstate_set(env, szSqlState, "HY008", "S1008");
- break;
-
- case STMT_NOT_IMPLEMENTED_ERROR:
- pg_sqlstate_set(env, szSqlState, "HYC00", "S1C00"); /* == 'driver not
- * capable' */
- break;
- case STMT_OPTION_OUT_OF_RANGE_ERROR:
- pg_sqlstate_set(env, szSqlState, "HY092", "S1092");
- break;
- case STMT_BAD_PARAMETER_NUMBER_ERROR:
- pg_sqlstate_set(env, szSqlState, "07009", "S1093");
- break;
- case STMT_INVALID_COLUMN_NUMBER_ERROR:
- pg_sqlstate_set(env, szSqlState, "07009", "S1002");
- break;
- case STMT_RESTRICTED_DATA_TYPE_ERROR:
- pg_sqlstate_set(env, szSqlState, "07006", "07006");
- break;
- case STMT_INVALID_CURSOR_STATE_ERROR:
- pg_sqlstate_set(env, szSqlState, "07005", "24000");
- break;
- case STMT_ERROR_IN_ROW:
- pg_sqlstate_set(env, szSqlState, "01S01", "01S01");
- break;
- case STMT_OPTION_VALUE_CHANGED:
- pg_sqlstate_set(env, szSqlState, "01S02", "01S02");
- break;
- case STMT_POS_BEFORE_RECORDSET:
- pg_sqlstate_set(env, szSqlState, "01S06", "01S06");
- break;
- case STMT_INVALID_CURSOR_NAME:
- pg_sqlstate_set(env, szSqlState, "34000", "34000");
- break;
- case STMT_NO_CURSOR_NAME:
- pg_sqlstate_set(env, szSqlState, "S1015", "S1015");
- break;
- case STMT_INVALID_ARGUMENT_NO:
- pg_sqlstate_set(env, szSqlState, "HY024", "S1009");
- /* invalid argument value */
- break;
- case STMT_INVALID_CURSOR_POSITION:
- pg_sqlstate_set(env, szSqlState, "HY109", "S1109");
- break;
- case STMT_RETURN_NULL_WITHOUT_INDICATOR:
- pg_sqlstate_set(env, szSqlState, "22002", "22002");
- break;
- case STMT_VALUE_OUT_OF_RANGE:
- pg_sqlstate_set(env, szSqlState, "HY019", "22003");
- break;
- case STMT_OPERATION_INVALID:
- pg_sqlstate_set(env, szSqlState, "HY011", "S1011");
- break;
- case STMT_INVALID_DESCRIPTOR_IDENTIFIER:
- pg_sqlstate_set(env, szSqlState, "HY091", "HY091");
- break;
- case STMT_INVALID_OPTION_IDENTIFIER:
- pg_sqlstate_set(env, szSqlState, "HY092", "HY092");
- break;
- case STMT_OPTION_NOT_FOR_THE_DRIVER:
- pg_sqlstate_set(env, szSqlState, "HYC00", "HYC00");
- break;
- case STMT_EXEC_ERROR:
- default:
- pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
- /* also a general error */
- break;
- }
- mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);
- if (clear_str)
- {
- stmt->errorpos = stapos + wrtlen;
- if (stmt->errorpos >= msglen)
- SC_clear_error(stmt);
- }
- if (wrtlen == 0)
- return SQL_SUCCESS_WITH_INFO;
- else
- return SQL_SUCCESS;
-}
-
-RETCODE SQL_API
-PGAPI_ConnectError( HDBC hdbc,
- SWORD RecNumber,
- UCHAR FAR * szSqlState,
- SDWORD FAR * pfNativeError,
- UCHAR FAR * szErrorMsg,
- SWORD cbErrorMsgMax,
- SWORD FAR * pcbErrorMsg,
- UWORD flag)
-{
- ConnectionClass *conn = (ConnectionClass *) hdbc;
- EnvironmentClass *env = (EnvironmentClass *) conn->henv;
- char *msg;
- int status;
- BOOL once_again = FALSE;
- SWORD msglen;
-
- mylog("**** PGAPI_ConnectError: hdbc=%u <%d>\n", hdbc, cbErrorMsgMax);
- if (RecNumber != 1 && RecNumber != -1)
- return SQL_NO_DATA_FOUND;
- if (cbErrorMsgMax < 0)
- return SQL_ERROR;
- if (!CC_get_error(conn, &status, &msg) || NULL == msg)
- {
- 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;
- }
- mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
-
- 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:
- pg_sqlstate_set(env, szSqlState, "01S02", "01S02");
- break;
- case STMT_TRUNCATED:
- case CONN_TRUNCATED:
- pg_sqlstate_set(env, szSqlState, "01004", "01004");
- /* data truncated */
- break;
- case CONN_INIREAD_ERROR:
- pg_sqlstate_set(env, szSqlState, "IM002", "IM002");
- /* data source not found */
- break;
- case CONNECTION_SERVER_NOT_REACHED:
- case CONN_OPENDB_ERROR:
- pg_sqlstate_set(env, szSqlState, "08001", "08001");
- /* unable to connect to data source */
- break;
- case CONN_INVALID_AUTHENTICATION:
- case CONN_AUTH_TYPE_UNSUPPORTED:
- pg_sqlstate_set(env, szSqlState, "28000", "28000");
- break;
- case CONN_STMT_ALLOC_ERROR:
- pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
- /* memory allocation failure */
- break;
- case CONN_IN_USE:
- pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
- /* general error */
- break;
- case CONN_UNSUPPORTED_OPTION:
- pg_sqlstate_set(env, szSqlState, "IM001", "IM001");
- /* driver does not support this function */
- case CONN_INVALID_ARGUMENT_NO:
- pg_sqlstate_set(env, szSqlState, "HY009", "S1009");
- /* invalid argument value */
- break;
- case CONN_TRANSACT_IN_PROGRES:
- pg_sqlstate_set(env, szSqlState, "HY010", "S1010");
-
- /*
- * when the user tries to switch commit mode in a
- * transaction
- */
- /* -> function sequence error */
- break;
- case CONN_NO_MEMORY_ERROR:
- pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
- break;
- case CONN_NOT_IMPLEMENTED_ERROR:
- case STMT_NOT_IMPLEMENTED_ERROR:
- pg_sqlstate_set(env, szSqlState, "HYC00", "S1C00");
- break;
- case STMT_RETURN_NULL_WITHOUT_INDICATOR:
- pg_sqlstate_set(env, szSqlState, "22002", "22002");
- break;
- case CONN_VALUE_OUT_OF_RANGE:
- case STMT_VALUE_OUT_OF_RANGE:
- pg_sqlstate_set(env, szSqlState, "HY019", "22003");
- break;
- default:
- pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
- /* general error */
- break;
- }
-
- mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, msglen, szErrorMsg);
- if (once_again)
- {
- conn->errornumber = status;
- return SQL_SUCCESS_WITH_INFO;
- }
- else
- return SQL_SUCCESS;
-}
-
-RETCODE SQL_API
-PGAPI_EnvError( HENV henv,
- SWORD RecNumber,
- UCHAR FAR * szSqlState,
- SDWORD FAR * pfNativeError,
- UCHAR FAR * szErrorMsg,
- SWORD cbErrorMsgMax,
- SWORD FAR * pcbErrorMsg,
- UWORD flag)
-{
- EnvironmentClass *env = (EnvironmentClass *) henv;
- char *msg;
- int status;
-
- mylog("**** PGAPI_EnvError: henv=%u <%d>\n", henv, cbErrorMsgMax);
- if (RecNumber != 1 && RecNumber != -1)
- return SQL_NO_DATA_FOUND;
- if (cbErrorMsgMax < 0)
- return SQL_ERROR;
- if (!EN_get_error(env, &status, &msg) || NULL == msg)
- {
- mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
-
- if (NULL != szSqlState)
- pg_sqlstate_set(env, szSqlState, "00000", "00000");
- if (NULL != pcbErrorMsg)
- *pcbErrorMsg = 0;
- if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
- szErrorMsg[0] = '\0';
-
- return SQL_NO_DATA_FOUND;
- }
- mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
-
- 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 */
- pg_sqlstate_set(env, szSqlState, "HY001", "S1001");
- break;
- default:
- pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
- /* general error */
- break;
- }
- }
-
- return SQL_SUCCESS;
-}
-
-
-/* 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)
-{
- RETCODE ret;
- UWORD flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR;
-
- mylog("**** PGAPI_Error: henv=%u, hdbc=%u hstmt=%d\n", henv, hdbc, hstmt);
-
- if (cbErrorMsgMax < 0)
- return SQL_ERROR;
- if (SQL_NULL_HSTMT != hstmt)
- ret = PGAPI_StmtError(hstmt, -1, szSqlState, pfNativeError,
- szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
- else if (SQL_NULL_HDBC != hdbc)
- ret = PGAPI_ConnectError(hdbc, -1, szSqlState, pfNativeError,
- szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
- else if (SQL_NULL_HENV != hdbc)
- ret = PGAPI_EnvError(henv, -1, szSqlState, pfNativeError,
- szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
- else
- {
- if (NULL != szSqlState)
- strcpy(szSqlState, "00000");
- if (NULL != pcbErrorMsg)
- *pcbErrorMsg = 0;
- if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
- szErrorMsg[0] = '\0';
-
- ret = SQL_NO_DATA_FOUND;
- }
- mylog("**** PGAPI_Error exit code=%d\n", ret);
- return ret;
-}
-
-/*
- * EnvironmentClass implementation
- */
-EnvironmentClass *
-EN_Constructor(void)
-{
- EnvironmentClass *rv;
-
- rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass));
- if (rv)
- {
- rv->errormsg = 0;
- rv->errornumber = 0;
- rv->flag = 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_check();
-#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/environ.h b/src/interfaces/odbc/environ.h
deleted file mode 100644
index 24b456d4899..00000000000
--- a/src/interfaces/odbc/environ.h
+++ /dev/null
@@ -1,38 +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;
- Int4 flag;
-};
-
-/* 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);
-
-#define EN_OV_ODBC2 1L
-#define EN_is_odbc2(env) ((env->flag & EN_OV_ODBC2) != 0)
-#define EN_is_odbc3(env) ((env->flag & EN_OV_ODBC2) == 0)
-#define EN_set_odbc2(env) (env->flag |= EN_OV_ODBC2)
-#define EN_set_odbc3(env) (env->flag &= EN_OV_ODBC2)
-
-#endif
diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c
deleted file mode 100644
index 598c2a2f61a..00000000000
--- a/src/interfaces/odbc/execute.c
+++ /dev/null
@@ -1,1090 +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 <stdio.h>
-#include <string.h>
-
-#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);
- if (self->stmt_with_params)
- free(self->stmt_with_params);
- self->stmt_with_params = NULL;
- if (self->load_statement)
- free(self->load_statement);
- self->load_statement = NULL;
-
- 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);
- if (stmt->stmt_with_params)
- free(stmt->stmt_with_params);
- stmt->stmt_with_params = NULL;
- if (stmt->load_statement)
- free(stmt->load_statement);
- stmt->load_statement = NULL;
-
- /*
- * 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;
- APDFields *opts;
- IPDFields *ipdopts;
- ConnectionClass *conn;
- int i,
- retval, start_row, end_row;
- int cursor_type, scroll_concurrency;
- QResultClass *res;
-
- 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;
- }
-
- opts = SC_get_APD(stmt);
- cursor_type = stmt->options.cursor_type;
- scroll_concurrency = stmt->options.scroll_concurrency;
- /*
- * 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)
- {
- stmt->exec_current_row = -1;
- 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);
-/******** Is this really NEEDED ? ******/
- 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;
- }
-
- if (start_row = stmt->exec_start_row, start_row < 0)
- start_row = 0;
- if (end_row = stmt->exec_end_row, end_row < 0)
- end_row = opts->paramset_size - 1;
- if (stmt->exec_current_row < 0)
- stmt->exec_current_row = start_row;
- ipdopts = SC_get_IPD(stmt);
- if (stmt->exec_current_row == start_row)
- {
- if (ipdopts->param_processed_ptr)
- *ipdopts->param_processed_ptr = 0;
- SC_recycle_statement(stmt);
- }
-
-next_param_row:
-#if (ODBCVER >= 0x0300)
- if (opts->param_operation_ptr)
- {
- while (opts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
- {
- if (ipdopts->param_status_ptr)
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_UNUSED;
- if (stmt->exec_current_row >= end_row)
- {
- stmt->exec_current_row = -1;
- return SQL_SUCCESS;
- }
- ++stmt->exec_current_row;
- }
- }
-#endif /* ODBCVER */
- /*
- * 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.
- */
- UInt4 offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
- Int4 bind_size = opts->param_bind_type;
- Int4 current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
-
- stmt->data_at_exec = -1;
- for (i = 0; i < opts->allocated; i++)
- {
- Int4 *pcVal = opts->parameters[i].used;
-
- opts->parameters[i].data_at_exec = FALSE;
- if (pcVal)
- {
- if (bind_size > 0)
- pcVal = (Int4 *)((char *)pcVal + offset + bind_size * current_row);
- else
- pcVal = (Int4 *)((char *)pcVal + offset + sizeof(SDWORD) * current_row);
- if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
- opts->parameters[i].data_at_exec = TRUE;
- }
- /* Check for data at execution parameters */
- if (opts->parameters[i].data_at_exec)
- {
- 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);
-
- if (!stmt->inaccurate_result || !conn->connInfo.disallow_premature)
- {
- retval = SC_execute(stmt);
- if (retval != SQL_ERROR)
- {
- if (ipdopts->param_processed_ptr)
- (*ipdopts->param_processed_ptr)++;
- /* special handling of result for keyset driven cursors */
- if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
- SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
- {
- QResultClass *kres;
-
- res = SC_get_Result(stmt);
- if (kres = res->next, kres)
- {
- kres->fields = res->fields;
- res->fields = NULL;
- kres->num_fields = res->num_fields;
- res->next = NULL;
- QR_Destructor(res);
- SC_set_Result(stmt, kres);
- }
- }
- }
-#if (ODBCVER >= 0x0300)
- if (ipdopts->param_status_ptr)
- {
- switch (retval)
- {
- case SQL_SUCCESS:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
- break;
- case SQL_SUCCESS_WITH_INFO:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
- break;
- default:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
- break;
- }
- }
-#endif /* ODBCVER */
- if (retval == SQL_ERROR ||
- stmt->inaccurate_result ||
- stmt->exec_current_row >= end_row)
- {
- stmt->exec_current_row = -1;
- return retval;
- }
- stmt->exec_current_row++;
- goto next_param_row;
- }
- /*
- * Get the field info for the prepared query using dummy backward
- * fetch.
- */
- if (SC_is_pre_executable(stmt))
- {
- BOOL in_trans = CC_is_in_trans(conn);
- BOOL issued_begin = FALSE,
- begin_included = FALSE;
- QResultClass *curres;
-
- if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
- begin_included = TRUE;
- else if (!in_trans)
- {
- if (issued_begin = CC_begin(conn), !issued_begin)
- {
- stmt->errornumber = STMT_EXEC_ERROR;
- stmt->errormsg = "Handle prepare error";
- return SQL_ERROR;
- }
- }
- /* we are now in a transaction */
- res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
- if (!res)
- {
- CC_abort(conn);
- stmt->errornumber = STMT_EXEC_ERROR;
- stmt->errormsg = "Handle prepare error";
- return SQL_ERROR;
- }
- SC_set_Result(stmt, res);
- for (curres = res; !curres->num_fields; curres = curres->next)
- ;
- SC_set_Curres(stmt, curres);
- if (CC_is_in_autocommit(conn))
- {
- if (issued_begin)
- CC_commit(conn);
- }
- stmt->status = STMT_FINISHED;
- return SQL_SUCCESS;
- }
- if (res = SC_get_Curres(stmt), res)
- stmt->diag_row_count = res->recent_processed_row_count;
- if (stmt->options.cursor_type != cursor_type ||
- stmt->options.scroll_concurrency != scroll_concurrency)
- {
- stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
- stmt->errormsg = "cursor updatability changed";
- return SQL_SUCCESS_WITH_INFO;
- }
- else
- return SQL_SUCCESS;
-}
-
-
-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, CLEAR_RESULT_ON_ABORT);
- if (!res)
- {
- /* error msg will be in the connection */
- CC_on_abort(conn, NO_TRANS);
- CC_log_error(func, "", conn);
- return SQL_ERROR;
- }
-
- ok = QR_command_maybe_successful(res);
- QR_Destructor(res);
-
- if (!ok)
- {
- CC_on_abort(conn, NO_TRANS);
- 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;
- ConnectionClass *conn;
- 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;
- }
- conn = SC_get_conn(stmt);
- ci = &(conn->connInfo);
-
- /*
- * Not in the middle of SQLParamData/SQLPutData so cancel like a
- * close.
- */
- if (stmt->data_at_exec < 0)
- {
- /*
- * Tell the Backend that we're cancelling this request
- */
- if (stmt->status == STMT_EXECUTING)
- CC_send_cancel_request(conn);
- /*
- * 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;
- APDFields *opts;
- IPDFields *ipdopts;
- 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);
- opts = SC_get_APD(stmt);
-
- mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, opts->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 > opts->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))
- {
- if (!CC_commit(stmt->hdbc))
- {
- 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 */
- ipdopts = SC_get_IPD(stmt);
- if (stmt->data_at_exec == 0)
- {
- int end_row;
-
- retval = copy_statement_with_parameters(stmt);
- if (retval != SQL_SUCCESS)
- return retval;
-
- stmt->current_exec_param = -1;
-
- retval = SC_execute(stmt);
- if (retval != SQL_ERROR)
- {
- if (ipdopts->param_processed_ptr)
- (*ipdopts->param_processed_ptr)++;
- }
-#if (ODBCVER >= 0x0300)
- if (ipdopts->param_status_ptr)
- {
- switch (retval)
- {
- case SQL_SUCCESS:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
- break;
- case SQL_SUCCESS_WITH_INFO:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
- break;
- default:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
- break;
- }
- }
-#endif /* ODBCVER */
- end_row = stmt->exec_end_row;
- if (end_row < 0)
- end_row = opts->paramset_size - 1;
- if (retval == SQL_ERROR ||
- stmt->exec_current_row >= end_row)
- {
- stmt->exec_current_row = -1;
- return retval;
- }
- stmt->exec_current_row++;
- return PGAPI_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 < opts->allocated; i++)
- {
- if (opts->parameters[i].data_at_exec)
- {
- stmt->data_at_exec--;
- stmt->current_exec_param = i;
- stmt->put_data = FALSE;
- *prgbValue = opts->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;
- APDFields *opts;
- 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;
- }
-
- opts = SC_get_APD(stmt);
- 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 = &(opts->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))
- {
- if (!CC_begin(stmt->hdbc))
- {
- stmt->errormsg = "Could not begin (in-line) a transaction";
- stmt->errornumber = STMT_EXEC_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- }
-
- /* 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 *) &current_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
- {
- Int2 ctype = current_param->CType;
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(current_param->SQLType);
-
-#ifdef UNICODE_SUPPORT
- if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
- cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
-#endif /* UNICODE_SUPPORT */
- /* 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
- {
-#ifdef UNICODE_SUPPORT
- if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
-#else
- if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
-#endif /* UNICODE_SUPPORT */
- {
- 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
- {
- Int2 ctype = current_param->CType;
-
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(current_param->SQLType);
- buffer = current_param->EXEC_buffer;
- if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
- {
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == ctype)
- old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
- else
-#endif /* UNICODE_SUPPORT */
- old_pos = strlen(buffer);
- }
- if (SQL_NTS == cbValue)
- {
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == ctype)
- cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
- else
-#endif /* UNICODE_SUPPORT */
- cbValue = strlen(rgbValue);
- }
- if (cbValue > 0)
- {
- *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/gpps.c b/src/interfaces/odbc/gpps.c
deleted file mode 100644
index ee73a23eb4e..00000000000
--- a/src/interfaces/odbc/gpps.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*-------
- * GetPrivateProfileString()
- *
- * approximate implementation of
- * Windows NT System Services version of GetPrivateProfileString()
- * probably doesn't handle the NULL key for section name or value key
- * correctly also, doesn't provide Microsoft backwards compatability
- * wrt TAB characters in the value string
- *
- * Microsoft terminates value
- * at the first TAB, but I couldn't discover what the behavior should
- * be regarding TABS in quoted strings so, I treat tabs like any other
- * characters
- *
- * NO comments following value string separated by a TAB
- * are allowed (that is an anachronism anyway)
- * Added code to search for ODBC_INI file in users home directory on
- * Unix
- *-------
- */
-
-#if !defined(WIN32) && !defined(WITH_UNIXODBC) && !defined(WITH_IODBC)
-
-#include "gpps.h"
-
-#include <stdio.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#if HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-#include <sys/types.h>
-#include <string.h>
-#include "misc.h"
-#include "dlg_specific.h"
-
-#ifndef TRUE
-#define TRUE ((BOOL)1)
-#endif
-#ifndef FALSE
-#define FALSE ((BOOL)0)
-#endif
-
-#ifndef ODBCINSTDIR
-#error "ODBCINSTDIR must be defined to compile this file"
-#endif
-
-
-/*
- * theIniFileName is searched for in:
- * $HOME/theIniFileName
- * theIniFileName
- * ODBCINSTDIR/ODBCINST_INI
- */
-DWORD
-GetPrivateProfileString(const char *theSection, /* section name */
- const char *theKey, /* search key name */
- const char *theDefault, /* default value if not
- * found */
- char *theReturnBuffer, /* return value stored
- * here */
- size_t theReturnBufferLength, /* byte length of return
- * buffer */
- const char *theIniFileName) /* pathname of ini file
- * to search */
-{
- char buf[MAXPGPATH];
- char *ptr = 0;
- FILE *aFile = 0;
- size_t aLength;
- char aLine[2048];
- char *aValue;
- char *aStart;
- char *aString;
- size_t aLineLength;
- size_t aReturnLength = 0;
- BOOL aSectionFound = FALSE;
- BOOL aKeyFound = FALSE;
-
- ptr = (char *) getpwuid(getuid()); /* get user info */
-
- if (ptr == NULL || (((struct passwd *) ptr)->pw_dir) == NULL || *(((struct passwd *) ptr)->pw_dir) == '\0')
- ptr = "/home";
- else
- ptr = ((struct passwd *) ptr)->pw_dir; /* get user home dir */
-
- /*
- * If it can't be opened because the paths are too long, then skip it,
- * don't just truncate the path string... The truncated path might
- * accidently be an existing file. The default value will be returned
- * instead.
- */
- if (MAXPGPATH - 1 >= strlen(ptr) + 1 + strlen(theIniFileName))
- {
- sprintf(buf, "%s/%s", ptr, theIniFileName);
- aFile = (FILE *) fopen(buf, PG_BINARY_R);
- }
-
- /*
- * This code makes it so that a file in the users home dir overrides a
- * the "default" file as passed in
- */
- if (!aFile)
- {
- aFile = (FILE *) fopen(theIniFileName, PG_BINARY_R);
- if (!aFile)
- aFile = (FILE *) fopen(ODBCINSTDIR "/" ODBCINST_INI, PG_BINARY_R);
- }
-
- aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
-
- if (theReturnBufferLength == 0 || theReturnBuffer == NULL)
- {
- if (aFile)
- fclose(aFile);
- return 0;
- }
-
- if (aFile == NULL)
- {
- /* no ini file specified, return the default */
- ++aLength; /* room for NULL char */
- aLength = theReturnBufferLength < aLength ?
- theReturnBufferLength : aLength;
- strncpy(theReturnBuffer, theDefault, aLength);
- theReturnBuffer[aLength - 1] = '\0';
- return aLength - 1;
- }
-
- while (fgets(aLine, sizeof(aLine), aFile) != NULL)
- {
- aLineLength = strlen(aLine);
- /* strip final '\n' */
- if (aLineLength > 0 && aLine[aLineLength - 1] == '\n')
- aLine[aLineLength - 1] = '\0';
- switch (*aLine)
- {
- case ' ': /* blank line */
- case ';': /* comment line */
- continue;
- break;
-
- case '[': /* section marker */
- if ((aString = strchr(aLine, ']')))
- {
- aStart = aLine + 1;
- aString--;
- while (isspace((unsigned char) *aStart))
- aStart++;
- while (isspace((unsigned char) *aString))
- aString--;
- *(aString + 1) = '\0';
-
- /* accept as matched if NULL key or exact match */
- if (!theSection || !strcmp(aStart, theSection))
- aSectionFound = TRUE;
- else
- aSectionFound = FALSE;
- }
- break;
-
- default:
-
- /* try to match value keys if in proper section */
- if (aSectionFound)
- {
- /* try to match requested key */
- if ((aString = aValue = strchr(aLine, '=')))
- {
- *aValue = '\0';
- ++aValue;
-
- /* strip leading blanks in value field */
- while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
- *aValue++ = '\0';
- if (aValue >= aLine + sizeof(aLine))
- aValue = "";
- }
- else
- aValue = "";
-
- aStart = aLine;
- while (isspace((unsigned char) *aStart))
- aStart++;
-
- /* strip trailing blanks from key */
- if (aString)
- {
- while (--aString >= aStart && *aString == ' ')
- *aString = '\0';
- }
-
- /* see if key is matched */
- if (theKey == NULL || !strcmp(theKey, aStart))
- {
- /* matched -- first, terminate value part */
- aKeyFound = TRUE;
- aLength = strlen(aValue);
-
- /* remove trailing blanks from aValue if any */
- aString = aValue + aLength - 1;
-
- while (--aString > aValue && *aString == ' ')
- {
- *aString = '\0';
- --aLength;
- }
-
- /* unquote value if quoted */
- if (aLength >= 2 && aValue[0] == '"' &&
- aValue[aLength - 1] == '"')
- {
- /* string quoted with double quotes */
-
- aValue[aLength - 1] = '\0';
- ++aValue;
- aLength -= 2;
- }
- else
- {
- /* single quotes allowed also... */
- if (aLength >= 2 && aValue[0] == '\'' &&
- aValue[aLength - 1] == '\'')
- {
- aValue[aLength - 1] = '\0';
- ++aValue;
- aLength -= 2;
- }
- }
-
- /* compute maximum length copyable */
- aLineLength = (aLength <
- theReturnBufferLength - aReturnLength) ? aLength :
- theReturnBufferLength - aReturnLength;
-
- /* do the copy to return buffer */
- if (aLineLength)
- {
- strncpy(&theReturnBuffer[aReturnLength],
- aValue, aLineLength);
- aReturnLength += aLineLength;
- if (aReturnLength < theReturnBufferLength)
- {
- theReturnBuffer[aReturnLength] = '\0';
- ++aReturnLength;
- }
- }
- if (aFile)
- {
- fclose(aFile);
- aFile = NULL;
- }
- return aReturnLength > 0 ? aReturnLength - 1 : 0;
- }
- }
- break;
- }
- }
-
- if (aFile)
- fclose(aFile);
-
- if (!aKeyFound)
- {
- /* key wasn't found return default */
- ++aLength; /* room for NULL char */
- aLength = theReturnBufferLength < aLength ?
- theReturnBufferLength : aLength;
- strncpy(theReturnBuffer, theDefault, aLength);
- theReturnBuffer[aLength - 1] = '\0';
- aReturnLength = aLength - 1;
- }
- return aReturnLength > 0 ? aReturnLength - 1 : 0;
-}
-
-
-DWORD
-WritePrivateProfileString(const char *theSection, /* section name */
- const char *theKey, /* write key name */
- const char *theBuffer, /* input buffer */
- const char *theIniFileName) /* pathname of ini file
- * to write */
-{
- return 0;
-}
-
-
-#if NOT_USED
-/*
- * Ok. What the hell's the default behaviour for a null input buffer, and null
- * section name. For now if either are null I ignore the request, until
- * I find out different.
- */
-DWORD
-WritePrivateProfileString(char *theSection, /* section name */
- char *theKey, /* write key name */
- char *theBuffer, /* input buffer */
- char *theIniFileName) /* pathname of ini file to
- * write */
-{
- char buf[MAXPGPATH];
- char *ptr = 0;
- FILE *aFile = 0;
- size_t aLength;
- char aLine[2048];
- char *aValue;
- char *aString;
- size_t aLineLength;
- size_t aReturnLength = 0;
-
- BOOL aSectionFound = FALSE;
- BOOL keyFound = FALSE;
- int j = 0;
-
- /* If this isn't correct processing we'll change it later */
- if (theSection == NULL || theKey == NULL || theBuffer == NULL ||
- theIniFileName == NULL)
- return 0;
-
- aLength = strlen(theBuffer);
- if (aLength == 0)
- return 0;
-
- j = strlen(theIniFileName) + 1;
- ptr = (char *) getpwuid(getuid()); /* get user info */
-
- if (ptr == NULL)
- {
- if (MAXPGPATH - 1 < j)
- theIniFileName[MAXPGPATH - 1] = '\0';
-
- sprintf(buf, "%s", theIniFileName);
- }
- ptr = ((struct passwd *) ptr)->pw_dir; /* get user home dir */
- if (ptr == NULL || *ptr == '\0')
- ptr = "/home";
-
- /*
- * This doesn't make it so we find an ini file but allows normal
- * processing to continue further on down. The likelihood is that the
- * file won't be found and thus the default value will be returned.
- */
- if (MAXPGPATH - 1 < strlen(ptr) + j)
- {
- if (MAXPGPATH - 1 < strlen(ptr))
- ptr[MAXPGPATH - 1] = '\0';
- else
- theIniFileName[MAXPGPATH - 1 - strlen(ptr)] = '\0';
- }
-
- sprintf(buf, "%s/%s", ptr, theIniFileName);
-
- /*
- * This code makes it so that a file in the users home dir overrides a
- * the "default" file as passed in
- */
- aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
- if (!aFile)
- {
- sprintf(buf, "%s", theIniFileName);
- aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
- if (!aFile)
- return 0;
- }
-
- aLength = strlen(theBuffer);
-
- /*
- * We have to search for theKey, because if it already exists we have
- * to overwrite it. If it doesn't exist we just write a new line to
- * the file.
- */
- while (fgets(aLine, sizeof(aLine), aFile) != NULL)
- {
- aLineLength = strlen(aLine);
- /* strip final '\n' */
- if (aLineLength > 0 && aLine[aLineLength - 1] == '\n')
- aLine[aLineLength - 1] = '\0';
- switch (*aLine)
- {
- case ' ': /* blank line */
- case ';': /* comment line */
- continue;
- break;
-
- case '[': /* section marker */
- if ((aString = strchr(aLine, ']')))
- {
- *aString = '\0';
-
- /* accept as matched if key exact match */
-
- if (!strcmp(aLine + 1, theSection))
- aSectionFound = TRUE;
- }
- break;
-
- default:
- /* try to match value keys if in proper section */
- if (aSectionFound)
- {
- /* try to match requested key */
-
- if ((aString = aValue = strchr(aLine, '=')))
- {
- *aValue = '\0';
- ++aValue;
-
- /* strip leading blanks in value field */
- while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
- *aValue++ = '\0';
- if (aValue >= aLine + sizeof(aLine))
- aValue = "";
- }
- else
- aValue = "";
-
- /* strip trailing blanks from key */
- if (aString)
- {
- while (--aString >= aLine && *aString == ' ')
- *aString = '\0';
- }
-
- /* see if key is matched */
- if (!strcmp(theKey, aLine))
- {
- keyFound = TRUE;
- /* matched -- first, terminate value part */
-
- /* overwrite current value */
- fseek(aFile, -aLineLength, SEEK_CUR);
- /* overwrite key and value */
- sprintf(aLine, "%s = %s\n", theKey, theBuffer);
- fputs(aLine, aFile);
- }
- }
- }
- break;
- }
-}
-
-if (!keyFound)
-{ /* theKey wasn't in file so */
- if (aFile)
- fclose(aFile);
-
- return aReturnLength > 0 ? aReturnLength - 1 : 0;
-}
-#endif /* NOT_USED */
-
-#endif /* not WIN32 */
diff --git a/src/interfaces/odbc/gpps.h b/src/interfaces/odbc/gpps.h
deleted file mode 100644
index ab133a82d4c..00000000000
--- a/src/interfaces/odbc/gpps.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* GetPrivateProfileString
- * for UNIX use
- */
-#ifndef GPPS_H
-#define GPPS_H
-
-#include "psqlodbc.h"
-
-#ifndef WIN32
-#include <sys/types.h>
-#endif
-
-#define SQLGetPrivateProfileString(a,b,c,d,e,f) GetPrivateProfileString(a,b,c,d,e,f)
-#define SQLWritePrivateProfileString(a,b,c,d) WritePrivateProfileString(a,b,c,d)
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-DWORD
-GetPrivateProfileString(const char *theSection, /* section name */
- const char *theKey, /* search key name */
- const char *theDefault, /* default value if not
- * found */
- char *theReturnBuffer, /* return valuse stored
- * here */
- size_t theBufferLength, /* byte length of return
- * buffer */
- const char *theIniFileName); /* pathname of ini file
- * to search */
-
-DWORD
-WritePrivateProfileString(const char *theSection, /* section name */
- const char *theKey, /* write key name */
- const char *theBuffer, /* input buffer */
- const char *theIniFileName); /* pathname of ini file
- * to write */
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifndef WIN32
-#undef DWORD
-#endif
-
-#endif
diff --git a/src/interfaces/odbc/info.c b/src/interfaces/odbc/info.c
deleted file mode 100644
index 3a3cda32ce4..00000000000
--- a/src/interfaces/odbc/info.c
+++ /dev/null
@@ -1,4509 +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,
- * SQLTablePrivileges, SQLColumnPrivileges(NI)
- *
- * Comments: See "notice.txt" for copyright and license information.
- *--------
- */
-
-#include "psqlodbc.h"
-
-#include <string.h>
-#include <stdio.h>
-
-#ifndef WIN32
-#include <ctype.h>
-#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"
-#ifdef MULTIBYTE
-#include "multibyte.h"
-#endif
-
-
-/* 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 | SQL_BP_DELETE | SQL_BP_UPDATE | SQL_BP_TRANSACTION);
- 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;
- if (PG_VERSION_LT(conn, 6.5))
- value = SQL_TXN_SERIALIZABLE;
- else
- value = SQL_TXN_READ_COMMITTED;
- 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;
- if (conn->schema_support)
- value = MAX_SCHEMA_LEN;
- 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 */
- if (conn->schema_support)
- p = "schema";
- else
- p = "owner";
- break;
-
- case SQL_OWNER_USAGE: /* ODBC 2.0 */
- len = 4;
- value = 0;
- if (conn->schema_support)
- value = SQL_OU_DML_STATEMENTS
- | SQL_OU_TABLE_DEFINITION
- | SQL_OU_INDEX_DEFINITION
- | SQL_OU_PRIVILEGE_DEFINITION
- ;
- break;
-
- case SQL_POS_OPERATIONS: /* ODBC 2.0 */
- len = 4;
- value = (SQL_POS_POSITION | SQL_POS_REFRESH);
-#ifdef DRIVER_CURSOR_IMPLEMENT
- if (ci->updatable_cursors)
- value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- 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->updatable_cursors) ? "Y" : "N";
- break;
-
- case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
- len = 4;
- value = SQL_SCCO_READ_ONLY;
-#ifdef DRIVER_CURSOR_IMPLEMENT
- if (ci->updatable_cursors)
- value |= SQL_SCCO_OPT_ROWVER;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- if (ci->drivers.lie)
- value |= (SQL_SCCO_LOCK | SQL_SCCO_OPT_VALUES);
- break;
-
- case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
- len = 4;
- value = SQL_SO_FORWARD_ONLY;
- if (!ci->drivers.use_declarefetch)
- value |= SQL_SO_STATIC;
- if (ci->updatable_cursors)
- value |= SQL_SO_KEYSET_DRIVEN;
- if (ci->drivers.lie)
- value |= (SQL_SO_DYNAMIC | SQL_SO_MIXED);
- break;
-
- case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
- if (PG_VERSION_GE(conn, 6.5))
- p = "\\";
- else
- 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 = 0;
-#ifdef DRIVER_CURSOR_IMPLEMENT
- if (ci->updatable_cursors)
- value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- 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;
- if (PG_VERSION_LT(conn, 6.5))
- value = SQL_TXN_SERIALIZABLE;
- else if (PG_VERSION_GE(conn, 7.1))
- value = SQL_TXN_READ_COMMITTED | SQL_TXN_SERIALIZABLE;
- else
- value = SQL_TXN_READ_COMMITTED;
- 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;
- return SQL_ERROR;
- }
-
- result = SQL_SUCCESS;
-
- mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", 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)
- {
-#ifdef UNICODE_SUPPORT
- if (conn->unicode)
- {
- len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
- len *= 2;
- }
- else
-#endif /* UNICODE_SUPPORT */
- strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
-
- if (len >= cbInfoValueMax)
- {
- result = SQL_SUCCESS_WITH_INFO;
- conn->errornumber = CONN_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;
- QResultClass *res;
- 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;
- if (res = QR_Constructor(), !res)
- {
- SC_log_error(func, "Error creating result.", stmt);
- return SQL_ERROR;
- }
- SC_set_Result(stmt, res);
-
-#if (ODBCVER >= 0x0399)
- extend_column_bindings(SC_get_ARD(stmt), 19);
-#else
- extend_column_bindings(SC_get_ARD(stmt), 15);
-#endif /* ODBCVER */
-
- QR_set_num_fields(res, 15);
- QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 2, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 10, "MONEY", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
-#if (ODBCVER >=0x0399)
- QR_set_field_info(res, 15, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 16, "SQL_DATATIME_SUB", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 17, "NUM_PREC_RADIX", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 18, "INTERVAL_PRECISION", PG_TYPE_INT2, 2);
-#endif /* ODBCVER */
-
- 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_column_size(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));
-#if (ODBCVER >=0x0399)
- set_nullfield_int2(&row->tuple[15], pgtype_sqldesctype(stmt, pgType));
- set_nullfield_int2(&row->tuple[16], pgtype_datetime_sub(stmt, pgType));
- set_nullfield_int4(&row->tuple[17], pgtype_radix(stmt, pgType));
- set_nullfield_int4(&row->tuple[18], 0);
-#endif /* ODBCVER */
-
- QR_add_tuple(res, 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] = TRUE;
- 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] = TRUE;
- }
- }
- 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 = TRUE;
- 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 = TRUE;
- 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;
- QResultClass *res;
- 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 scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
-
- 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 (conn->schema_support)
- {
- /* view is represented by its relkind since 7.1 */
- strcpy(tables_query, "select relname, nspname, relkind from pg_class, pg_namespace");
- strcat(tables_query, " where relkind in ('r', 'v')");
- }
- else 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'");
- }
-
- if (conn->schema_support)
- schema_strcat(tables_query, " and nspname like '%.*s'", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
- else
- 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]+'");
-
- if (conn->schema_support)
- strcat(tables_query, " and pg_namespace.oid = relnamespace order by nspname, relname");
- else
- strcat(tables_query, " and usesysid = relowner 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;
- }
-
- if (res = QR_Constructor(), !res)
- {
- 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;
- }
- SC_set_Result(stmt, res);
-
- /* 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_column_bindings(SC_get_ARD(stmt), 5);
-
- /* set the field names */
- QR_set_num_fields(res, 5);
- QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 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], "");*/
- 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], table_owner);
- */
-
- mylog("%s: table_name = '%s'\n", func, table_name);
-
- if (conn->schema_support)
- set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
- else
- /* set_tuplefield_string(&row->tuple[1], ""); */
- set_tuplefield_null(&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], "");*/
- set_tuplefield_string(&row->tuple[4], "TABLE");
-
- QR_add_tuple(res, 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;
-}
-
-
-/*
- * PostgreSQL needs 2 '\\' to escape '_' and '%'.
- */
-static int
-reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len, int ccsc)
-{
- int i, outlen;
- const char *in;
- BOOL escape_in = FALSE;
-#ifdef MULTIBYTE
- encoded_str encstr;
-#endif
-
- if (srclen == SQL_NULL_DATA)
- {
- dest[0] = '\0';
- return STRCPY_NULL;
- }
- else if (srclen == SQL_NTS)
- srclen = strlen(src);
- if (srclen <= 0)
- return STRCPY_FAIL;
-#ifdef MULTIBYTE
- encoded_str_constr(&encstr, ccsc, src);
-#endif
- for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++)
- {
-#ifdef MULTIBYTE
- encoded_nextchar(&encstr);
- if (ENCODE_STATUS(encstr) != 0)
- {
- dest[outlen++] = *in;
- continue;
- }
-#endif
- if (escape_in)
- {
- switch (*in)
- {
- case '%':
- case '_':
- dest[outlen++] = '\\'; /* needs 1 more */
- break;
- default:
- dest[outlen++] = '\\';
- if (outlen < dst_len)
- dest[outlen++] = '\\';
- if (outlen < dst_len)
- dest[outlen++] = '\\';
- break;
- }
- }
- if (*in == '\\')
- escape_in = TRUE;
- else
- escape_in = FALSE;
- if (outlen < dst_len)
- dest[outlen++] = *in;
- }
- if (outlen < dst_len)
- dest[outlen] = '\0';
- return outlen;
-}
-
-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,
- UWORD flag)
-{
- static char *func = "PGAPI_Columns";
- StatementClass *stmt = (StatementClass *) hstmt;
- QResultClass *res;
- 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, sqltype,
- reserved_cols,
- result_cols,
- decimal_digits;
- Int4 field_type,
- the_type,
- field_length,
- mod_length,
- column_size,
- ordinal;
- char useStaticPrecision;
- char not_null[MAX_INFO_STRING],
- relhasrules[MAX_INFO_STRING];
- ConnInfo *ci;
- ConnectionClass *conn;
-
-
- mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
-
- 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)
- */
- if (conn->schema_support)
- sprintf(columns_query, "select u.nspname, c.relname, a.attname, a.atttypid"
- ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
- " from pg_namespace u, pg_class c, pg_attribute a, pg_type t"
- " where u.oid = c.relnamespace"
- " and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
- "a.atttypmod");
- else
- 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");
-
- if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0)
- {
- my_strcat(columns_query, " and c.relname = '%.*s'", szTableName, cbTableName);
- if (conn->schema_support)
- schema_strcat(columns_query, " and u.nspname = '%.*s'", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
- else
- my_strcat(columns_query, " and u.usename = '%.*s'", szTableOwner, cbTableOwner);
- my_strcat(columns_query, " and a.attname = '%.*s'", szColumnName, cbColumnName);
- }
- else
- {
- char esc_table_name[MAX_TABLE_LEN * 2];
- int escTbnamelen;
-
- escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
- my_strcat(columns_query, " and c.relname like '%.*s'", esc_table_name, escTbnamelen);
- if (conn->schema_support)
- schema_strcat(columns_query, " and u.nspname like '%.*s'", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
- else
- 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
- */
- if (conn->schema_support)
- strcat(columns_query, " order by u.nspname, c.relname, attnum");
- else
- strcat(columns_query, " order by c.relname, 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;
- }
-
- if (res = QR_Constructor(), !res)
- {
- 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;
- }
- SC_set_Result(stmt, res);
-
- /* the binding structure for a statement is not set up until */
-
- /*
- * a statement is actually executed, so we'll have to do this
- * ourselves.
- */
-#if (ODBCVER >= 0x0300)
- reserved_cols = 18;
-#else
- reserved_cols = 12;
-#endif /* ODBCVER */
- result_cols = reserved_cols + 2;
- extend_column_bindings(SC_get_ARD(stmt), result_cols);
-
- /* set the field names */
- QR_set_num_fields(res, result_cols);
- QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4); /* COLUMN_SIZE */
- QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4); /* BUFFER_LENGTH */
- QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2); /* DECIMAL_DIGITS ***/
- QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 11, "REMARKS", PG_TYPE_TEXT, 254);
-
- /* User defined fields */
-#if (ODBCVER >= 0x0300)
- QR_set_field_info(res, 12, "COLUMN_DEF", PG_TYPE_INT4, 254);
- QR_set_field_info(res, 13, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 14, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 15, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 16, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 17, "IS_NULLABLE", PG_TYPE_TEXT, 254);
-#endif /* ODBCVER */
- QR_set_field_info(res, reserved_cols, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
- QR_set_field_info(res, reserved_cols + 1, "FIELD_TYPE", PG_TYPE_INT4, 4);
-
- ordinal = 1;
- 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() */
- if (conn->schema_support)
- set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
- else
- set_tuplefield_string(&row->tuple[1], "");
- set_tuplefield_string(&row->tuple[2], table_name);
- set_tuplefield_string(&row->tuple[3], "oid");
- sqltype = pgtype_to_concise_type(stmt, the_type);
- set_tuplefield_int2(&row->tuple[4], sqltype);
- set_tuplefield_string(&row->tuple[5], "OID");
-
- set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
- set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(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], "");
-
-#if (ODBCVER >= 0x0300)
- set_tuplefield_null(&row->tuple[12]);
- set_tuplefield_int2(&row->tuple[13], sqltype);
- set_tuplefield_null(&row->tuple[14]);
- set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[16], ordinal);
- set_tuplefield_string(&row->tuple[17], "No");
-#endif /* ODBCVER */
- set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[reserved_cols + 1], the_type);
-
- QR_add_tuple(res, row);
- ordinal++;
- }
- }
-
- 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() */
- if (conn->schema_support)
- set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
- else
- set_tuplefield_string(&row->tuple[1], "");
- set_tuplefield_string(&row->tuple[2], table_name);
- set_tuplefield_string(&row->tuple[3], field_name);
- sqltype = pgtype_to_concise_type(stmt, field_type);
- set_tuplefield_int2(&row->tuple[4], sqltype);
- 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 decimal_digits is stored in atttypmod as follows:
- *
- * column_size =((atttypmod - VARHDRSZ) >> 16) & 0xffff
- * decimal_digits = (atttypmod - VARHDRSZ) & 0xffff
- *
- *----------
- */
- qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,name='%s'\n",
- table_name, field_name, field_type, 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;
-
- column_size = (mod_length >> 16) & 0xffff;
- decimal_digits = 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, column_size, decimal_digits);
-
- set_tuplefield_int4(&row->tuple[6], column_size);
- set_tuplefield_int4(&row->tuple[7], column_size + 2); /* sign+dec.point */
- set_nullfield_int2(&row->tuple[8], decimal_digits);
-#if (ODBCVER >= 0x0300)
- set_tuplefield_null(&row->tuple[15]);
-#endif /* ODBCVER */
- set_tuplefield_int4(&row->tuple[reserved_cols], column_size + 2); /* sign+dec.point */
- }
- }
-
- 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[6], mod_length);
- set_tuplefield_int4(&row->tuple[7], mod_length);
- set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
-#if (ODBCVER >= 0x0300)
- set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, field_type, PG_STATIC, PG_STATIC));
-#endif /* ODBCVER */
- set_tuplefield_int4(&row->tuple[reserved_cols], mod_length);
- }
-
- if (useStaticPrecision)
- {
- mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
-
- set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, field_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
- set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
-#if (ODBCVER >= 0x0300)
- set_tuplefield_null(&row->tuple[15]);
-#endif /* ODBCVER */
- set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, field_type, PG_STATIC, 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], "");
-#if (ODBCVER >= 0x0300)
- set_tuplefield_null(&row->tuple[12]);
- set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type));
- set_nullfield_int2(&row->tuple[14], pgtype_to_datetime_sub(stmt, field_type));
- set_tuplefield_int4(&row->tuple[16], ordinal);
- set_tuplefield_null(&row->tuple[17]);
-#endif /* ODBCVER */
- set_tuplefield_int4(&row->tuple[reserved_cols + 1], field_type);
-
- QR_add_tuple(res, row);
- ordinal++;
-
- 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], "");
- if (conn->schema_support)
- set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
- else
- set_tuplefield_string(&row->tuple[1], "");
- set_tuplefield_string(&row->tuple[2], table_name);
- set_tuplefield_string(&row->tuple[3], "xmin");
- sqltype = pgtype_to_concise_type(stmt, the_type);
- set_tuplefield_int2(&row->tuple[4], sqltype);
- set_tuplefield_string(&row->tuple[5], pgtype_to_name(stmt, the_type));
- set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
- set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(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], "");
-#if (ODBCVER >= 0x0300)
- set_tuplefield_null(&row->tuple[12]);
- set_tuplefield_int2(&row->tuple[13], sqltype);
- set_tuplefield_null(&row->tuple[14]);
- set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[16], ordinal);
- set_tuplefield_string(&row->tuple[17], "No");
-#endif /* ODBCVER */
- set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[reserved_cols + 1], the_type);
-
- QR_add_tuple(res, row);
- ordinal++;
- }
-
- /*
- * 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;
- ConnectionClass *conn;
- QResultClass *res;
- 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 scnm=%x len=%d colType=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType);
-
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
- conn = SC_get_conn(stmt);
- ci = &(conn->connInfo);
-
- stmt->manual_result = TRUE;
-
- /*
- * Create the query to find out if this is a view or not...
- */
- if (conn->schema_support)
- sprintf(columns_query, "select c.relhasrules "
- "from pg_namespace u, pg_class c where "
- "u.oid = c.relnamespace");
- else
- sprintf(columns_query, "select c.relhasrules "
- "from pg_user u, pg_class c where "
- "u.usesysid = c.relowner");
-
- /* TableName cannot contain a string search pattern */
- my_strcat(columns_query, " and c.relname = '%.*s'", szTableName, cbTableName);
- /* SchemaName cannot contain a string search pattern */
- if (conn->schema_support)
- schema_strcat(columns_query, " and u.nspname = '%.*s'", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
- else
- my_strcat(columns_query, " and u.usename = '%.*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);
-
- res = QR_Constructor();
- SC_set_Result(stmt, res);
- extend_column_bindings(SC_get_ARD(stmt), 8);
-
- QR_set_num_fields(res, 8);
- QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 4, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 5, "LENGTH", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 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_concise_type(stmt, PG_TYPE_OID));
- set_tuplefield_string(&row->tuple[3], "OID");
- set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
- set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, PG_TYPE_OID, PG_STATIC));
- set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
-
- QR_add_tuple(res, 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_concise_type(stmt, the_type));
- set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
- set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
- set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
-
- QR_add_tuple(res, row);
- }
- }
- }
- else
- {
- /* 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_concise_type(stmt, PG_TYPE_OID));
- set_tuplefield_string(&row->tuple[3], "OID");
- set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
- set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, PG_TYPE_OID, PG_STATIC));
- set_tuplefield_int2(&row->tuple[7], SQL_PC_NOT_PSEUDO);
-
- QR_add_tuple(res, row);
-
- }
- else if (fColType == SQL_ROWVER)
- {
- Int2 the_type = PG_TYPE_TID;
-
- row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
-
- set_tuplefield_null(&row->tuple[0]);
- set_tuplefield_string(&row->tuple[1], "ctid");
- set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type));
- set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
- set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
- set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
- set_tuplefield_int2(&row->tuple[7], SQL_PC_NOT_PSEUDO);
-
- QR_add_tuple(res, 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;
- ConnectionClass *conn;
- QResultClass *res;
- 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],
- table_qualifier[MAX_INFO_STRING],
- relhasrules[10];
- 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 scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
-
- 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);
-
- if (res = QR_Constructor(), !res)
- {
- stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result.";
- stmt->errornumber = STMT_NO_MEMORY_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- SC_set_Result(stmt, res);
-
- /* 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_column_bindings(SC_get_ARD(stmt), 13);
-
- /* set the field names */
- QR_set_num_fields(res, 13);
- QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 6, "TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
- QR_set_field_info(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 11, "PAGES", PG_TYPE_INT4, 4);
- QR_set_field_info(res, 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;
- }
- table_qualifier[0] = '\0';
- if (conn->schema_support)
- schema_strcat(table_qualifier, "%.*s", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
-
- /*
- * 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;
- /*
- * table_name parameter cannot contain a string search pattern.
- */
- result = PGAPI_Columns(hcol_stmt, "", 0, table_qualifier, SQL_NTS,
- table_name, SQL_NTS, "", 0, PODBC_NOT_SEARCH_PATTERN);
- 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, sizeof(column_name), &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;
-
- if (conn->schema_support)
- sprintf(index_query, "select c.relname, i.indkey, i.indisunique"
- ", i.indisclustered, a.amname, c.relhasrules, n.nspname"
- " from pg_index i, pg_class c, pg_class d, pg_am a, pg_namespace n"
- " where d.relname = '%s'"
- " and n.nspname = '%s'"
- " and n.oid = d.relnamespace"
- " and d.oid = i.indrelid"
- " and i.indexrelid = c.oid"
- " and c.relam = a.oid order by"
- ,table_name, table_qualifier);
- else
- 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 order by"
- ,table_name);
- if (PG_VERSION_GT(SC_get_conn(stmt), 6.4))
- strcat(index_query, " i.indisprimary desc,");
- if (conn->schema_support)
- strcat(index_query, " i.indisunique, n.nspname, c.relname");
- else
- strcat(index_query, " i.indisunique, c.relname");
-
- 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, sizeof(relhasrules), 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], GET_SCHEMA_NAME(table_qualifier));
- 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(res, 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], GET_SCHEMA_NAME(table_qualifier));
- 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(res, 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";
- StatementClass *stmt = (StatementClass *) hstmt;
-
- mylog("%s: entering...\n", func);
-
- /* Neither Access or Borland care about this. */
-
- stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
- stmt->errormsg = "not implemented";
- SC_log_error(func, "Function not implemented", stmt);
- 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;
- QResultClass *res;
- 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], pkscm[MAX_TABLE_LEN + 1];
- Int2 result_cols;
- int qno,
- qstart,
- qend;
-
- mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
-
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
- stmt->manual_result = TRUE;
- stmt->errormsg_created = TRUE;
-
- if (res = QR_Constructor(), !res)
- {
- stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result.";
- stmt->errornumber = STMT_NO_MEMORY_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- SC_set_Result(stmt, res);
-
- /* 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_column_bindings(SC_get_ARD(stmt), result_cols);
-
- /* set the field names */
- QR_set_num_fields(res, result_cols);
- QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(res, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(res, 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;
-
- conn = SC_get_conn(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;
- }
- pkscm[0] = '\0';
- if (conn->schema_support)
- schema_strcat(pkscm, "%.*s", szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
-
- 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;
- }
-
- 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
- */
- if (conn->schema_support)
- sprintf(tables_query, "select ta.attname, ia.attnum"
- " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i, pg_namespace n"
- " where c.relname = '%s'"
- " AND n.nspname = '%s'"
- " AND c.oid = i.indrelid"
- " AND n.oid = c.relnamespace"
- " 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, pkscm);
- else
- 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
- */
- if (conn->schema_support)
- sprintf(tables_query, "select ta.attname, ia.attnum"
- " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i, pg_namespace n"
- " where c.relname = '%s_pkey'"
- " AND n.nspname = '%s'"
- " AND c.oid = i.indexrelid"
- " AND n.oid = c.relnamespace"
- " AND ia.attrelid = i.indexrelid"
- " AND ta.attrelid = i.indrelid"
- " AND ta.attnum = i.indkey[ia.attnum-1]"
- " order by ia.attnum", pktab, pkscm);
- else
- 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], GET_SCHEMA_NAME(pkscm));
- 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(res, 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;
-}
-#ifdef NOT_USED
-static char *
-getClientTableName(ConnectionClass *conn, const char *serverSchemaName, 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, CLEAR_RESULT_ON_ABORT), 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);
- bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
- if (!bError && continueExec)
- {
- if (conn->schema_support)
- sprintf(query, "select OID from pg_class where relname = '%s' and pg_namespace.oid = relnamespace and pg_namespace.nspname = '%s'", serverTableName, serverSchemaName);
- else
- sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
- if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
- {
- if (QR_get_num_tuples(res) > 0)
- strcpy(saveoid, QR_get_value_backend_row(res,