diff options
author | Marc G. Fournier | 2002-08-22 22:43:14 +0000 |
---|---|---|
committer | Marc G. Fournier | 2002-08-22 22:43:14 +0000 |
commit | ed99623fb25412218275b968ec6f4976bfcb260d (patch) | |
tree | 93d3afe871b7c1802542cdd7a49703dc09cfdef5 | |
parent | 987ca836a74e8af052205c253359831c915d6532 (diff) |
Remove all traces of the ODBC driver, which is now on GBorg as the psqlodbc
project ...
87 files changed, 7 insertions, 40003 deletions
diff --git a/GNUmakefile.in b/GNUmakefile.in index 0fcc9878c0..21e85d1113 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -72,7 +72,7 @@ $(distdir).tar: distdir opt_files := src/backend/utils/mb contrib/retep/build.xml \ src/tools src/corba src/data src/tutorial \ $(addprefix src/bin/, pgaccess pgtclsh pg_encoding) \ - $(addprefix src/interfaces/, odbc libpgtcl perl5 python jdbc) \ + $(addprefix src/interfaces/, libpgtcl perl5 python jdbc) \ $(addprefix src/pl/, plperl tcl) docs_files := doc/postgres.tar.gz doc/src doc/TODO.detail @@ -321,10 +321,6 @@ Installation Procedure the only good reason to select a non-default value is if you intend to run multiple PostgreSQL servers on the same machine. - --with-CXX - - Build the C++ interface library. - --with-perl Build the Perl interface module. The Perl interface will be @@ -362,35 +358,6 @@ Installation Procedure use a different version of Tcl or Tk you can specify the directory in which to find them. - --enable-odbc - - Build the ODBC driver. By default, the driver will be independent - of a driver manager. To work better with a driver manager already - installed on your system, use one of the following options in - addition to this one. More information can be found in the - Programmer's Guide. - - --with-iodbc - - Build the ODBC driver for use with iODBC. - - --with-unixodbc - - Build the ODBC driver for use with unixODBC. - - --with-odbcinst=DIRECTORY - - Specifies the directory where the ODBC driver will expect its - "odbcinst.ini" configuration file. The default is - "/usr/local/pgsql/etc" or whatever you specified as - "--sysconfdir". It should be arranged that the driver reads the - same file as the driver manager. - - If either the option "--with-iodbc" or the option - "--with-unixodbc" is used, this option will be ignored because in - that case the driver manager handles the location of the - configuration file. - --with-java Build the JDBC driver and associated Java packages. This option @@ -8,8 +8,11 @@ PostgreSQL is an advanced object-relational database management system that supports an extended subset of the SQL standard, including transactions, foreign keys, subqueries, triggers, user-defined types and functions. This distribution also contains several language -bindings, including C, C++, Perl, Python, and Tcl, as well as drivers -for JDBC and ODBC. +bindings, including C, Perl, Python, and Tcl, as well as drivers +for JDBC. + +As of v7.3, the ODBC and C++ interfaces have been moved over to the +PostgreSQL Projects WebSite @ http://gborg.postgresql.org. See the file INSTALL for instructions on how to build and install PostgreSQL. That file also lists supported operating systems and @@ -845,7 +845,6 @@ Optional Features: --enable-debug build with debugging symbols (-g) --enable-depend turn on automatic dependency tracking --enable-cassert enable assertion checks (for debugging) - --enable-odbc build the ODBC driver package --disable-largefile omit support for large files Optional Packages: @@ -871,9 +870,6 @@ Optional Packages: --with-openssl[=DIR] build with OpenSSL support [/usr/local/ssl] --without-readline do not use Readline --without-zlib do not use Zlib - --with-unixodbc build ODBC driver for unixODBC - --with-iodbc build ODBC driver for iODBC - --with-odbcinst=DIR default directory for odbcinst.ini sysconfdir --with-gnu-ld assume the C compiler uses GNU ld default=no Some influential environment variables: @@ -3476,162 +3472,6 @@ fi; -# -# Optionally enable the building of the ODBC driver -# - -# Old option name -if test "${with_odbc+set}" = set && test "${enable_odbc+set}" != set; then - enable_odbc=$with_odbc -fi - -echo "$as_me:$LINENO: checking whether to build the ODBC driver" >&5 -echo $ECHO_N "checking whether to build the ODBC driver... $ECHO_C" >&6 - - -# Check whether --enable-odbc or --disable-odbc was given. -if test "${enable_odbc+set}" = set; then - enableval="$enable_odbc" - - case $enableval in - yes) - : - ;; - no) - : - ;; - *) - { { echo "$as_me:$LINENO: error: no argument expected for --enable-odbc option" >&5 -echo "$as_me: error: no argument expected for --enable-odbc option" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - -else - enable_odbc=no - -fi; - - - - -# Check whether --with-unixodbc or --without-unixodbc was given. -if test "${with_unixodbc+set}" = set; then - withval="$with_unixodbc" - - case $withval in - yes) - : - ;; - no) - : - ;; - *) - { { echo "$as_me:$LINENO: error: no argument expected for --with-unixodbc option" >&5 -echo "$as_me: error: no argument expected for --with-unixodbc option" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - -else - with_unixodbc=no - -fi; - - - - -# Check whether --with-iodbc or --without-iodbc was given. -if test "${with_iodbc+set}" = set; then - withval="$with_iodbc" - - case $withval in - yes) - : - ;; - no) - : - ;; - *) - { { echo "$as_me:$LINENO: error: no argument expected for --with-iodbc option" >&5 -echo "$as_me: error: no argument expected for --with-iodbc option" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - -else - with_iodbc=no - -fi; - -if test "$with_unixodbc" = yes && test "$with_iodbc" = yes; then - { { echo "$as_me:$LINENO: error: ODBC driver cannot be built for both unixODBC and iODBC" >&5 -echo "$as_me: error: ODBC driver cannot be built for both unixODBC and iODBC" >&2;} - { (exit 1); exit 1; }; } -fi -if test "$with_unixodbc" = yes || test "$with_iodbc" = yes; then - enable_odbc=yes -fi -case $enable_odbc:$with_unixodbc:$with_iodbc in - yes:no:no) echo "$as_me:$LINENO: result: yes (stand-alone)" >&5 -echo "${ECHO_T}yes (stand-alone)" >&6;; - yes:yes:no) echo "$as_me:$LINENO: result: yes (unixODBC)" >&5 -echo "${ECHO_T}yes (unixODBC)" >&6 - -cat >>confdefs.h <<\_ACEOF -#define WITH_UNIXODBC 1 -_ACEOF - - ;; - yes:no:yes) echo "$as_me:$LINENO: result: yes (iODBC)" >&5 -echo "${ECHO_T}yes (iODBC)" >&6 - -cat >>confdefs.h <<\_ACEOF -#define WITH_IODBC 1 -_ACEOF - - ;; - no:*) echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6;; -esac - - - - - -# Allow for overriding the default location of the odbcinst.ini -# file which is normally ${sysconfdir} (i.e., ${prefix}/etc). - - - -# Check whether --with-odbcinst or --without-odbcinst was given. -if test "${with_odbcinst+set}" = set; then - withval="$with_odbcinst" - - case $withval in - yes) - { { echo "$as_me:$LINENO: error: argument required for --with-odbcinst option" >&5 -echo "$as_me: error: argument required for --with-odbcinst option" >&2;} - { (exit 1); exit 1; }; } - ;; - no) - { { echo "$as_me:$LINENO: error: argument required for --with-odbcinst option" >&5 -echo "$as_me: error: argument required for --with-odbcinst option" >&2;} - { (exit 1); exit 1; }; } - ;; - *) - odbcinst_ini_dir=$withval - ;; - esac - -else - odbcinst_ini_dir="\${sysconfdir}" -fi; - - - - - # Assume system is ELF if it predefines __ELF__ as 1, # otherwise believe host_os based default. case $host_os in @@ -16459,10 +16299,6 @@ s,@with_krb5@,$with_krb5,;t t s,@krb_srvtab@,$krb_srvtab,;t t s,@with_pam@,$with_pam,;t t s,@with_openssl@,$with_openssl,;t t -s,@enable_odbc@,$enable_odbc,;t t -s,@with_unixodbc@,$with_unixodbc,;t t -s,@with_iodbc@,$with_iodbc,;t t -s,@odbcinst_ini_dir@,$odbcinst_ini_dir,;t t s,@ELF_SYS@,$ELF_SYS,;t t s,@AWK@,$AWK,;t t s,@FLEX@,$FLEX,;t t diff --git a/configure.in b/configure.in index 63dbe3492e..295aca7830 100644 --- a/configure.in +++ b/configure.in @@ -511,50 +511,6 @@ PGAC_ARG_BOOL(with, zlib, yes, -# -# Optionally enable the building of the ODBC driver -# - -# Old option name -if test "${with_odbc+set}" = set && test "${enable_odbc+set}" != set; then - enable_odbc=$with_odbc -fi - -AC_MSG_CHECKING([whether to build the ODBC driver]) -PGAC_ARG_BOOL(enable, odbc, no, [ --enable-odbc build the ODBC driver package]) -PGAC_ARG_BOOL(with, unixodbc, no, [ --with-unixodbc build ODBC driver for unixODBC]) -PGAC_ARG_BOOL(with, iodbc, no, [ --with-iodbc build ODBC driver for iODBC]) -if test "$with_unixodbc" = yes && test "$with_iodbc" = yes; then - AC_MSG_ERROR([ODBC driver cannot be built for both unixODBC and iODBC]) -fi -if test "$with_unixodbc" = yes || test "$with_iodbc" = yes; then - enable_odbc=yes -fi -case $enable_odbc:$with_unixodbc:$with_iodbc in - yes:no:no) AC_MSG_RESULT([yes (stand-alone)]);; - yes:yes:no) AC_MSG_RESULT([yes (unixODBC)]) - AC_DEFINE(WITH_UNIXODBC, 1, [Define to 1 to build with unixODBC support (--with-unixodbc)]) - ;; - yes:no:yes) AC_MSG_RESULT([yes (iODBC)]) - AC_DEFINE(WITH_IODBC, 1, [Define to 1 to build with iODBC support (--with-iodbc)]) - ;; - no:*) AC_MSG_RESULT(no);; -esac -AC_SUBST([enable_odbc]) -AC_SUBST([with_unixodbc]) -AC_SUBST([with_iodbc]) - - -# Allow for overriding the default location of the odbcinst.ini -# file which is normally ${sysconfdir} (i.e., ${prefix}/etc). -PGAC_ARG_REQ(with, odbcinst, - [ --with-odbcinst=DIR default directory for odbcinst.ini [sysconfdir]], - [odbcinst_ini_dir=$withval], - [odbcinst_ini_dir="\${sysconfdir}"]) -AC_SUBST([odbcinst_ini_dir]) - - - # Assume system is ELF if it predefines __ELF__ as 1, # otherwise believe host_os based default. case $host_os in diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 533a88d0ea..67d32ab0f8 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -111,8 +111,6 @@ override docdir := $(docdir)/postgresql endif endif -odbcinst_ini_dir = @odbcinst_ini_dir@ - javadir := $(DESTDIR)$(datadir)/java localedir := @localedir@ @@ -129,9 +127,6 @@ with_perl = @with_perl@ with_python = @with_python@ with_tcl = @with_tcl@ with_tk = @with_tk@ -enable_odbc = @enable_odbc@ -with_iodbc = @with_iodbc@ -with_unixodbc = @with_unixodbc@ MULTIBYTE = @MULTIBYTE@ enable_shared = @enable_shared@ enable_rpath = @enable_rpath@ diff --git a/src/interfaces/Makefile b/src/interfaces/Makefile index 4cc068f8a0..c6d940c855 100644 --- a/src/interfaces/Makefile +++ b/src/interfaces/Makefile @@ -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 55805e84ea..0000000000 --- a/src/interfaces/odbc/GNUmakefile +++ /dev/null @@ -1,72 +0,0 @@ -#------------------------------------------------------------------------- -# -# GNUMakefile for psqlodbc (Postgres ODBC driver) -# -# $Header$ -# -#------------------------------------------------------------------------- - -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 e6deedaa8b..0000000000 --- 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 f2467c7713..0000000000 --- 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 7fe72d3f6d..0000000000 --- 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 41e9400dce..0000000000 --- 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 e3c0563ec2..0000000000 --- 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 133b4920c0..0000000000 --- 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 2b58619232..0000000000 --- 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, ¶m_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 8f65472e1f..0000000000 --- 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 a5cee114d0..0000000000 --- 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$ - * - */ - -#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 4f96a6f7c5..0000000000 --- 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 99005d3a33..0000000000 --- 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 88c2e9f4c4..0000000000 --- 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 6c08376ac4..0000000000 --- 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 9ac8f8eb6c..0000000000 --- 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 24b456d489..0000000000 --- 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 598c2a2f61..0000000000 --- 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 *) ¤t_param->lobj_oid; - - /* store the fd */ - stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE); - if (stmt->lobj_fd < 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt open large object for writing."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); - mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval); - } - else - { - 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 ee73a23eb4..0000000000 --- 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 ab133a82d4..0000000000 --- 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 3a3cda32ce..0000000000 --- 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, 0, 0)); - else - continueExec = FALSE; - QR_Destructor(res); - } - else - bError = TRUE; - } - continueExec = (continueExec && !bError); - if (bError && CC_is_in_trans(conn)) - { - CC_abort(conn); - bError = FALSE; - } - /* restore the client encoding */ - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); - bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL); - if (bError || !continueExec) - return ret; - sprintf(query, "select relname from pg_class where OID = %s", saveoid); - if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res) - { - if (QR_get_num_tuples(res) > 0) - { - ret = strdup(QR_get_value_backend_row(res, 0, 0)); - *nameAlloced = TRUE; - } - QR_Destructor(res); - } - return ret; -} -static char * -getClientColumnName(ConnectionClass *conn, const char * serverSchemaName, const char *serverTableName, char *serverColumnName, BOOL *nameAlloced) -{ - char query[1024], - saveattrelid[24], - saveattnum[16], - *ret = serverColumnName; - BOOL continueExec = TRUE, - bError = FALSE; - QResultClass *res; - - *nameAlloced = FALSE; - if (!conn->client_encoding || !isMultibyte(serverColumnName)) - return ret; - if (!conn->server_encoding) - { - if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, 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 attrelid, attnum from pg_class, pg_attribute " - "where relname = '%s' and attrelid = pg_class.oid " - "and attname = '%s' and pg_namespace.oid = relnamespace and pg_namespace.nspname = '%s'", serverTableName, serverColumnName, serverSchemaName); - else - sprintf(query, "select attrelid, attnum from pg_class, pg_attribute " - "where relname = '%s' and attrelid = pg_class.oid " - "and attname = '%s'", serverTableName, serverColumnName); - if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res) - { - if (QR_get_num_tuples(res) > 0) - { - strcpy(saveattrelid, QR_get_value_backend_row(res, 0, 0)); - strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1)); - } - else - continueExec = FALSE; - QR_Destructor(res); - } - else - bError = TRUE; - } - continueExec = (continueExec && !bError); - if (bError && CC_is_in_trans(conn)) - { - CC_abort(conn); - bError = FALSE; - } - /* restore the cleint encoding */ - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); - bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL); - if (bError || !continueExec) - return ret; - sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum); - if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res) - { - if (QR_get_num_tuples(res) > 0) - { - ret = strdup(QR_get_value_backend_row(res, 0, 0)); - *nameAlloced = TRUE; - } - QR_Destructor(res); - } - return ret; -} -#endif /* NOT_USED */ -static char * -getClientColumnName(ConnectionClass *conn, UInt4 relid, char *serverColumnName, BOOL *nameAlloced) -{ - char query[1024], saveattnum[16], - *ret = serverColumnName; - BOOL continueExec = TRUE, - bError = FALSE; - QResultClass *res; - - *nameAlloced = FALSE; - if (!conn->client_encoding || !isMultibyte(serverColumnName)) - return ret; - if (!conn->server_encoding) - { - if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res) - { - if (QR_get_num_backend_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) - { - sprintf(query, "select attnum from pg_attribute " - "where attrelid = %u and attname = '%s'", - relid, serverColumnName); - if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res) - { - if (QR_get_num_backend_tuples(res) > 0) - { - strcpy(saveattnum, QR_get_value_backend_row(res, 0, 0)); - } - else - continueExec = FALSE; - QR_Destructor(res); - } - else - bError = TRUE; - } - continueExec = (continueExec && !bError); - if (bError && CC_is_in_trans(conn)) - { - CC_abort(conn); - bError = FALSE; - } - /* restore the cleint encoding */ - sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); - bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL); - if (bError || !continueExec) - return ret; - sprintf(query, "select attname from pg_attribute where attrelid = %u and attnum = %s", relid, saveattnum); - if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res) - { - if (QR_get_num_backend_tuples(res) > 0) - { - ret = strdup(QR_get_value_backend_row(res, 0, 0)); - *nameAlloced = TRUE; - } - QR_Destructor(res); - } - return ret; -} -#endif /* MULTIBYTE */ - -RETCODE SQL_API -PGAPI_ForeignKeys( - HSTMT hstmt, - UCHAR FAR * szPkTableQualifier, - SWORD cbPkTableQualifier, - UCHAR FAR * szPkTableOwner, - SWORD cbPkTableOwner, - UCHAR FAR * szPkTableName, - SWORD cbPkTableName, - UCHAR FAR * szFkTableQualifier, - SWORD cbFkTableQualifier, - UCHAR FAR * szFkTableOwner, - SWORD cbFkTableOwner, - UCHAR FAR * szFkTableName, - SWORD cbFkTableName) -{ - static char *func = "PGAPI_ForeignKeys"; - StatementClass *stmt = (StatementClass *) hstmt; - QResultClass *res; - TupleNode *row; - HSTMT htbl_stmt, - hpkey_stmt; - StatementClass *tbl_stmt; - RETCODE result, - keyresult; - char tables_query[INFO_INQUIRY_LEN]; - char trig_deferrable[2]; - char trig_initdeferred[2]; - char trig_args[1024]; - char upd_rule[MAX_TABLE_LEN], - del_rule[MAX_TABLE_LEN]; - char pk_table_needed[MAX_TABLE_LEN + 1]; -char fk_table_fetched[MAX_TABLE_LEN + 1]; - char fk_table_needed[MAX_TABLE_LEN + 1]; -char pk_table_fetched[MAX_TABLE_LEN + 1]; - char schema_needed[MAX_SCHEMA_LEN + 1]; -char schema_fetched[MAX_SCHEMA_LEN + 1]; - char *pkey_ptr, - *pkey_text, - *fkey_ptr, - *fkey_text; - - ConnectionClass *conn; -#ifdef MULTIBYTE - BOOL pkey_alloced, - fkey_alloced; -#endif /* MULTIBYTE */ - int i, - j, - k, - num_keys; - SWORD trig_nargs, - upd_rule_type = 0, - del_rule_type = 0; - -#if (ODBCVER >= 0x0300) - SWORD defer_type; -#endif - char pkey[MAX_INFO_STRING]; - Int2 result_cols; - UInt4 relid1, relid2; - - mylog("%s: entering...stmt=%u\n", func, stmt); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - stmt->manual_result = TRUE; - stmt->errormsg_created = TRUE; - - if (res = QR_Constructor(), !res) - { - stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys 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. - */ -#if (ODBCVER >= 0x0300) - result_cols = 15; -#else - result_cols = 14; -#endif /* ODBCVER */ - 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, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 8, "KEY_SEQ", PG_TYPE_INT2, 2); - QR_set_field_info(res, 9, "UPDATE_RULE", PG_TYPE_INT2, 2); - QR_set_field_info(res, 10, "DELETE_RULE", PG_TYPE_INT2, 2); - QR_set_field_info(res, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); -#if (ODBCVER >= 0x0300) - QR_set_field_info(res, 14, "DEFERRABILITY", PG_TYPE_INT2, 2); -#endif /* ODBCVER >= 0x0300 */ - - /* - * also, things need to think that this statement is finished so the - * results can be retrieved. - */ - stmt->status = STMT_FINISHED; - - /* set up the current tuple pointer for SQLFetch */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - - result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for PGAPI_ForeignKeys result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - tbl_stmt = (StatementClass *) htbl_stmt; - - pk_table_needed[0] = '\0'; - fk_table_needed[0] = '\0'; - schema_needed[0] = '\0'; - schema_fetched[0] = '\0'; - - make_string(szPkTableName, cbPkTableName, pk_table_needed); - make_string(szFkTableName, cbFkTableName, fk_table_needed); - - conn = SC_get_conn(stmt); -#ifdef MULTIBYTE - pkey_text = fkey_text = NULL; - pkey_alloced = fkey_alloced = FALSE; -#endif /* MULTIBYTE */ - - /* - * Case #2 -- Get the foreign keys in the specified table (fktab) that - * refer to the primary keys of other table(s). - */ - if (fk_table_needed[0] != '\0') - { - mylog("%s: entering Foreign Key Case #2", func); - if (conn->schema_support) - { - schema_strcat(schema_needed, "%.*s", szFkTableOwner, cbFkTableOwner, szFkTableName, cbFkTableName, conn); - sprintf(tables_query, "SELECT pt.tgargs, " - " pt.tgnargs, " - " pt.tgdeferrable, " - " pt.tginitdeferred, " - " pp1.proname, " - " pp2.proname, " - " pc.oid, " - " pc1.oid, " - " pc1.relname, " - " pn.nspname " - "FROM pg_class pc, " - " pg_proc pp1, " - " pg_proc pp2, " - " pg_trigger pt1, " - " pg_trigger pt2, " - " pg_proc pp, " - " pg_trigger pt, " - " pg_class pc1, " - " pg_namespace pn " - "WHERE pt.tgrelid = pc.oid " - "AND pp.oid = pt.tgfoid " - "AND pt1.tgconstrrelid = pc.oid " - "AND pp1.oid = pt1.tgfoid " - "AND pt2.tgfoid = pp2.oid " - "AND pt2.tgconstrrelid = pc.oid " - "AND ((pc.relname='%s') " - "AND (pg_namespace.oid = pc.relnamespace) " - "AND (pg_namespace.nspname = '%s') " - "AND (pp.proname LIKE '%%ins') " - "AND (pp1.proname LIKE '%%upd') " - "AND (pp2.proname LIKE '%%del') " - "AND (pt1.tgrelid=pt.tgconstrrelid) " - "AND (pt1.tgconstrname=pt.tgconstrname) " - "AND (pt2.tgrelid=pt.tgconstrrelid) " - "AND (pt2.tgconstrname=pt.tgconstrname) " - "AND (pt.tgconstrrelid=pc1.oid) " - "AND (pc1.relnamespace=pn.oid))", - fk_table_needed, schema_needed); - } - else - sprintf(tables_query, "SELECT pt.tgargs, " - " pt.tgnargs, " - " pt.tgdeferrable, " - " pt.tginitdeferred, " - " pp1.proname, " - " pp2.proname, " - " pc.oid, " - " pc1.oid, " - " pc1.relname " - "FROM pg_class pc, " - " pg_proc pp1, " - " pg_proc pp2, " - " pg_trigger pt1, " - " pg_trigger pt2, " - " pg_proc pp, " - " pg_trigger pt, " - " pg_class pc1 " - "WHERE pt.tgrelid = pc.oid " - "AND pp.oid = pt.tgfoid " - "AND pt1.tgconstrrelid = pc.oid " - "AND pp1.oid = pt1.tgfoid " - "AND pt2.tgfoid = pp2.oid " - "AND pt2.tgconstrrelid = pc.oid " - "AND ((pc.relname='%s') " - "AND (pp.proname LIKE '%%ins') " - "AND (pp1.proname LIKE '%%upd') " - "AND (pp2.proname LIKE '%%del') " - "AND (pt1.tgrelid=pt.tgconstrrelid) " - "AND (pt1.tgconstrname=pt.tgconstrname) " - "AND (pt2.tgrelid=pt.tgconstrrelid) " - "AND (pt2.tgconstrname=pt.tgconstrname) " - "AND (pt.tgconstrrelid=pc1.oid)) ", - fk_table_needed); - - result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query)); - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY, - trig_args, sizeof(trig_args), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT, - &trig_nargs, 0, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 3, SQL_C_CHAR, - trig_deferrable, sizeof(trig_deferrable), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 4, SQL_C_CHAR, - trig_initdeferred, sizeof(trig_initdeferred), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 5, SQL_C_CHAR, - upd_rule, sizeof(upd_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 6, SQL_C_CHAR, - del_rule, sizeof(del_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG, - &relid1, sizeof(relid1), 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, 8, SQL_C_ULONG, - &relid2, sizeof(relid2), 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, 9, SQL_C_CHAR, - pk_table_fetched, MAX_TABLE_LEN, 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 (conn->schema_support) -{ - result = PGAPI_BindCol(htbl_stmt, 10, SQL_C_CHAR, - schema_fetched, MAX_SCHEMA_LEN, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } -} - - result = PGAPI_Fetch(htbl_stmt); - if (result == SQL_NO_DATA_FOUND) - return SQL_SUCCESS; - - if (result != SQL_SUCCESS) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - keyresult = PGAPI_AllocStmt(stmt->hdbc, &hpkey_stmt); - if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO)) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - keyresult = PGAPI_BindCol(hpkey_stmt, 4, SQL_C_CHAR, - pkey, sizeof(pkey), NULL); - if (keyresult != SQL_SUCCESS) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result."; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hpkey_stmt, SQL_DROP); - return SQL_ERROR; - } - - while (result == SQL_SUCCESS) - { - /* Compute the number of keyparts. */ - num_keys = (trig_nargs - 4) / 2; - - mylog("Foreign Key Case#2: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys); - - /* If there is a pk table specified, then check it. */ - if (pk_table_needed[0] != '\0') - { - /* If it doesn't match, then continue */ - if (strcmp(pk_table_fetched, pk_table_needed)) - { - result = PGAPI_Fetch(htbl_stmt); - continue; - } - } - - keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_fetched, SQL_NTS, pk_table_fetched, SQL_NTS); - if (keyresult != SQL_SUCCESS) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Couldn't get primary keys for PGAPI_ForeignKeys result."; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(hpkey_stmt, SQL_DROP); - return SQL_ERROR; - } - - - /* Get to first primary key */ - pkey_ptr = trig_args; - for (i = 0; i < 5; i++) - pkey_ptr += strlen(pkey_ptr) + 1; - - for (k = 0; k < num_keys; k++) - { - /* Check that the key listed is the primary key */ - keyresult = PGAPI_Fetch(hpkey_stmt); - if (keyresult != SQL_SUCCESS) - { - num_keys = 0; - break; - } -#ifdef MULTIBYTE - pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced); -#else - pkey_text = pkey_ptr; -#endif /* MULTIBYTE */ - mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey); - if (strcmp(pkey_text, pkey)) - { - num_keys = 0; - break; - } -#ifdef MULTIBYTE - if (pkey_alloced) - free(pkey_text); -#endif /* MULTIBYTE */ - /* Get to next primary key */ - for (k = 0; k < 2; k++) - pkey_ptr += strlen(pkey_ptr) + 1; - - } - - /* Set to first fk column */ - fkey_ptr = trig_args; - for (k = 0; k < 4; k++) - fkey_ptr += strlen(fkey_ptr) + 1; - - /* Set update and delete actions for foreign keys */ - if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) - upd_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) - upd_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) - upd_rule_type = SQL_SET_NULL; - - if (!strcmp(upd_rule, "RI_FKey_cascade_del")) - del_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) - del_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) - del_rule_type = SQL_SET_NULL; - -#if (ODBCVER >= 0x0300) - /* Set deferrability type */ - if (!strcmp(trig_initdeferred, "y")) - defer_type = SQL_INITIALLY_DEFERRED; - else if (!strcmp(trig_deferrable, "y")) - defer_type = SQL_INITIALLY_IMMEDIATE; - else - defer_type = SQL_NOT_DEFERRABLE; -#endif /* ODBCVER >= 0x0300 */ - - /* Get to first primary key */ - pkey_ptr = trig_args; - for (i = 0; i < 5; i++) - pkey_ptr += strlen(pkey_ptr) + 1; - - for (k = 0; k < num_keys; k++) - { - row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); - -#ifdef MULTIBYTE - pkey_text = getClientColumnName(conn, relid2, pkey_ptr, &pkey_alloced); - fkey_text = getClientColumnName(conn, relid1, fkey_ptr, &fkey_alloced); -#else - pkey_text = pkey_ptr; - fkey_text = fkey_ptr; -#endif /* MULTIBYTE */ - mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table_fetched, pkey_text); - set_tuplefield_null(&row->tuple[0]); - set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(schema_fetched)); - set_tuplefield_string(&row->tuple[2], pk_table_fetched); - set_tuplefield_string(&row->tuple[3], pkey_text); - - mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text); - set_tuplefield_null(&row->tuple[4]); - set_tuplefield_string(&row->tuple[5], GET_SCHEMA_NAME(schema_needed)); - set_tuplefield_string(&row->tuple[6], fk_table_needed); - set_tuplefield_string(&row->tuple[7], fkey_text); - - mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args); - set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1)); - set_tuplefield_int2(&row->tuple[9], (Int2) upd_rule_type); - set_tuplefield_int2(&row->tuple[10], (Int2) del_rule_type); - set_tuplefield_null(&row->tuple[11]); - set_tuplefield_null(&row->tuple[12]); - set_tuplefield_string(&row->tuple[13], trig_args); -#if (ODBCVER >= 0x0300) - set_tuplefield_int2(&row->tuple[14], defer_type); -#endif /* ODBCVER >= 0x0300 */ - - QR_add_tuple(res, row); -#ifdef MULTIBYTE - if (fkey_alloced) - free(fkey_text); - fkey_alloced = FALSE; - if (pkey_alloced) - free(pkey_text); - pkey_alloced = FALSE; -#endif /* MULTIBYTE */ - /* next primary/foreign key */ - for (i = 0; i < 2; i++) - { - fkey_ptr += strlen(fkey_ptr) + 1; - pkey_ptr += strlen(pkey_ptr) + 1; - } - } - - result = PGAPI_Fetch(htbl_stmt); - } - PGAPI_FreeStmt(hpkey_stmt, SQL_DROP); - } - - /* - * Case #1 -- Get the foreign keys in other tables that refer to the - * primary key in the specified table (pktab). i.e., Who points to - * me? - */ - else if (pk_table_needed[0] != '\0') - { - if (conn->schema_support) - { - schema_strcat(schema_needed, "%.*s", szPkTableOwner, cbPkTableOwner, szPkTableName, cbPkTableName, conn); - sprintf(tables_query, "SELECT pt.tgargs, " - " pt.tgnargs, " - " pt.tgdeferrable, " - " pt.tginitdeferred, " - " pp.proname, " - " pp1.proname, " - " pc.oid, " - " pc1.oid, " - " pc1.relname, " - " pn.nspname " - "FROM pg_class pc, " - " pg_class pc1, " - " pg_class pc2, " - " pg_proc pp, " - " pg_proc pp1, " - " pg_trigger pt, " - " pg_trigger pt1, " - " pg_trigger pt2, " - " pg_namespace pn " - "WHERE pt.tgconstrrelid = pc.oid " - " AND pt.tgrelid = pc1.oid " - " AND pt1.tgfoid = pp1.oid " - " AND pt1.tgconstrrelid = pc1.oid " - " AND pt2.tgconstrrelid = pc2.oid " - " AND pt2.tgfoid = pp.oid " - " AND pc2.oid = pt.tgrelid " - " AND (" - " (pc.relname='%s') " - " AND (pg_namespace.oid = pc.relnamespace) " - " AND (pg_namespace.nspname = '%s') " - " AND (pp.proname Like '%%upd') " - " AND (pp1.proname Like '%%del')" - " AND (pt1.tgrelid = pt.tgconstrrelid) " - " AND (pt2.tgrelid = pt.tgconstrrelid) " - " AND (pn.oid = pc1.relnamespace) " - " )", - pk_table_needed, schema_needed); - } - else - sprintf(tables_query, "SELECT pt.tgargs, " - " pt.tgnargs, " - " pt.tgdeferrable, " - " pt.tginitdeferred, " - " pp.proname, " - " pp1.proname, " - " pc.oid, " - " pc1.oid, " - " pc1.relname " - "FROM pg_class pc, " - " pg_class pc1, " - " pg_class pc2, " - " pg_proc pp, " - " pg_proc pp1, " - " pg_trigger pt, " - " pg_trigger pt1, " - " pg_trigger pt2 " - "WHERE pt.tgconstrrelid = pc.oid " - " AND pt.tgrelid = pc1.oid " - " AND pt1.tgfoid = pp1.oid " - " AND pt1.tgconstrrelid = pc1.oid " - " AND pt2.tgconstrrelid = pc2.oid " - " AND pt2.tgfoid = pp.oid " - " AND pc2.oid = pt.tgrelid " - " AND (" - " (pc.relname='%s') " - " AND (pp.proname Like '%%upd') " - " AND (pp1.proname Like '%%del')" - " AND (pt1.tgrelid = pt.tgconstrrelid) " - " AND (pt2.tgrelid = pt.tgconstrrelid) " - " )", - pk_table_needed); - - result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query)); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY, - trig_args, sizeof(trig_args), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT, - &trig_nargs, 0, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 3, SQL_C_CHAR, - trig_deferrable, sizeof(trig_deferrable), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 4, SQL_C_CHAR, - trig_initdeferred, sizeof(trig_initdeferred), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 5, SQL_C_CHAR, - upd_rule, sizeof(upd_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 6, SQL_C_CHAR, - del_rule, sizeof(del_rule), NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG, - &relid1, sizeof(relid1), 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, 8, SQL_C_ULONG, - &relid2, sizeof(relid2), 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, 9, SQL_C_CHAR, - fk_table_fetched, MAX_TABLE_LEN, 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 (conn->schema_support) -{ - result = PGAPI_BindCol(htbl_stmt, 10, SQL_C_CHAR, - schema_fetched, MAX_SCHEMA_LEN, NULL); - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) - { - stmt->errormsg = tbl_stmt->errormsg; - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } -} - - result = PGAPI_Fetch(htbl_stmt); - if (result == SQL_NO_DATA_FOUND) - return SQL_SUCCESS; - - if (result != SQL_SUCCESS) - { - stmt->errormsg = SC_create_errormsg(htbl_stmt); - stmt->errornumber = tbl_stmt->errornumber; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } - - while (result == SQL_SUCCESS) - { - /* Calculate the number of key parts */ - num_keys = (trig_nargs - 4) / 2;; - - /* Handle action (i.e., 'cascade', 'restrict', 'setnull') */ - if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) - upd_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) - upd_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) - upd_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) - upd_rule_type = SQL_SET_NULL; - - if (!strcmp(upd_rule, "RI_FKey_cascade_del")) - del_rule_type = SQL_CASCADE; - else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) - del_rule_type = SQL_NO_ACTION; - else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) - del_rule_type = SQL_SET_DEFAULT; - else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) - del_rule_type = SQL_SET_NULL; - -#if (ODBCVER >= 0x0300) - /* Set deferrability type */ - if (!strcmp(trig_initdeferred, "y")) - defer_type = SQL_INITIALLY_DEFERRED; - else if (!strcmp(trig_deferrable, "y")) - defer_type = SQL_INITIALLY_IMMEDIATE; - else - defer_type = SQL_NOT_DEFERRABLE; -#endif /* ODBCVER >= 0x0300 */ - - mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys); - - /* Get to first primary key */ - pkey_ptr = trig_args; - for (i = 0; i < 5; i++) - pkey_ptr += strlen(pkey_ptr) + 1; - - /* Get to first foreign key */ - fkey_ptr = trig_args; - for (k = 0; k < 4; k++) - fkey_ptr += strlen(fkey_ptr) + 1; - - for (k = 0; k < num_keys; k++) - { -#ifdef MULTIBYTE - pkey_text = getClientColumnName(conn, relid1, pkey_ptr, &pkey_alloced); - fkey_text = getClientColumnName(conn, relid2, fkey_ptr, &fkey_alloced); -#else - pkey_text = pkey_ptr; - fkey_text = fkey_ptr; -#endif /* MULTIBYTE */ - mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fk_table_fetched, fkey_text); - - row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField)); - - mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text); - set_tuplefield_null(&row->tuple[0]); - set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(schema_needed)); - set_tuplefield_string(&row->tuple[2], pk_table_needed); - set_tuplefield_string(&row->tuple[3], pkey_text); - - mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table_fetched, fkey_text); - set_tuplefield_null(&row->tuple[4]); - set_tuplefield_string(&row->tuple[5], GET_SCHEMA_NAME(schema_fetched)); - set_tuplefield_string(&row->tuple[6], fk_table_fetched); - set_tuplefield_string(&row->tuple[7], fkey_text); - - set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1)); - - mylog("upd_rule = %d, del_rule= %d", upd_rule_type, del_rule_type); - set_nullfield_int2(&row->tuple[9], (Int2) upd_rule_type); - set_nullfield_int2(&row->tuple[10], (Int2) del_rule_type); - - set_tuplefield_null(&row->tuple[11]); - set_tuplefield_null(&row->tuple[12]); - - set_tuplefield_string(&row->tuple[13], trig_args); - -#if (ODBCVER >= 0x0300) - mylog(" defer_type = %d\n", defer_type); - set_tuplefield_int2(&row->tuple[14], defer_type); -#endif /* ODBCVER >= 0x0300 */ - - QR_add_tuple(res, row); -#ifdef MULTIBYTE - if (pkey_alloced) - free(pkey_text); - pkey_alloced = FALSE; - if (fkey_alloced) - free(fkey_text); - fkey_alloced = FALSE; -#endif /* MULTIBYTE */ - - /* next primary/foreign key */ - for (j = 0; j < 2; j++) - { - pkey_ptr += strlen(pkey_ptr) + 1; - fkey_ptr += strlen(fkey_ptr) + 1; - } - } - result = PGAPI_Fetch(htbl_stmt); - } - } - else - { - stmt->errormsg = "No tables specified to PGAPI_ForeignKeys."; - stmt->errornumber = STMT_INTERNAL_ERROR; - SC_log_error(func, "", stmt); - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - return SQL_ERROR; - } -#ifdef MULTIBYTE - if (pkey_alloced) - free(pkey_text); - if (fkey_alloced) - free(fkey_text); -#endif /* MULTIBYTE */ - - PGAPI_FreeStmt(htbl_stmt, SQL_DROP); - - mylog("PGAPI_ForeignKeys(): EXIT, stmt=%u\n", stmt); - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_ProcedureColumns( - HSTMT hstmt, - UCHAR FAR * szProcQualifier, - SWORD cbProcQualifier, - UCHAR FAR * szProcOwner, - SWORD cbProcOwner, - UCHAR FAR * szProcName, - SWORD cbProcName, - UCHAR FAR * szColumnName, - SWORD cbColumnName) -{ - static char *func = "PGAPI_ProcedureColumns"; - StatementClass *stmt = (StatementClass *) hstmt; - - mylog("%s: entering...\n", func); - - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "not implemented"; - SC_log_error(func, "Function not implemented", stmt); - return SQL_ERROR; -} - - -RETCODE SQL_API -PGAPI_Procedures( - HSTMT hstmt, - UCHAR FAR * szProcQualifier, - SWORD cbProcQualifier, - UCHAR FAR * szProcOwner, - SWORD cbProcOwner, - UCHAR FAR * szProcName, - SWORD cbProcName) -{ - static char *func = "PGAPI_Procedures"; - StatementClass *stmt = (StatementClass *) hstmt; - ConnectionClass *conn = SC_get_conn(stmt); - char proc_query[INFO_INQUIRY_LEN]; - QResultClass *res; - - mylog("%s: entering... scnm=%x len=%d\n", func, szProcOwner, cbProcOwner); - - if (PG_VERSION_LT(conn, 6.5)) - { - stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; - stmt->errormsg = "Version is too old"; - SC_log_error(func, "Function not implemented", stmt); - return SQL_ERROR; - } - if (!SC_recycle_statement(stmt)) - return SQL_ERROR; - - /* - * The following seems the simplest implementation - */ - if (conn->schema_support) - strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" "," - " proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" "," - " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" "," - " '' as " "REMARKS" "," - " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_namespace, pg_proc where"); - else - strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", '' as " "PROCEDURE_SCHEM" "," - " proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" "," - " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" "," - " '' as " "REMARKS" "," - " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc"); - if (conn->schema_support) - { - strcat(proc_query, " where pg_proc.pronamespace = pg_namespace.oid"); - schema_strcat(proc_query, " and nspname like '%.*s'", szProcOwner, cbProcOwner, szProcName, cbProcName, conn); - my_strcat(proc_query, " and proname like '%.*s'", szProcName, cbProcName); - } - else - my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName); - - if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "PGAPI_Procedures query error"; - return SQL_ERROR; - } - SC_set_Result(stmt, res); - - /* - * also, things need to think that this statement is finished so the - * results can be retrieved. - */ - stmt->status = STMT_FINISHED; - extend_column_bindings(SC_get_ARD(stmt), 8); - /* set up the current tuple pointer for SQLFetch */ - stmt->currTuple = -1; - stmt->rowset_start = -1; - stmt->current_col = -1; - - return SQL_SUCCESS; -} - - -#define ACLMAX 8 -#define ALL_PRIVILIGES "arwdRxt" -static int -usracl_auth(char *usracl, const char *auth) -{ - int i, j, addcnt = 0; - - for (i = 0; auth[i]; i++) - { - for (j = 0; j < ACLMAX; j++) - { - if (usracl[j] == auth[i]) - break; - else if (!usracl[j]) - { - usracl[j]= auth[i]; - addcnt++; - break; - } - } - } - return addcnt; -} -static void -useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth) -{ - int usercount = QR_get_num_backend_tuples(allures), i, addcnt = 0; - -mylog("user=%s auth=%s\n", user, auth); - if (user[0]) - for (i = 0; i < usercount; i++) - { - if (strcmp(QR_get_value_backend_row(allures, i, 0), user) == 0) - { - addcnt += usracl_auth(useracl[i], auth); - break; - } - } - else - for (i = 0; i < usercount; i++) - { - addcnt += usracl_auth(useracl[i], auth); - } - mylog("addcnt=%d\n", addcnt); -} - -RETCODE SQL_API -PGAPI_TablePrivileges( - HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UWORD flag) -{ - StatementClass *stmt = (StatementClass *) hstmt; - static char *func = "PGAPI_TablePrivileges"; - ConnectionClass *conn = SC_get_conn(stmt); - Int2 result_cols; - char proc_query[INFO_INQUIRY_LEN]; - QResultClass *res, *allures = NULL; - TupleNode *row; - int tablecount, usercount, i, j, k; - BOOL grpauth, sys, su; - char (*useracl)[ACLMAX], *acl, *user, *delim, *auth; - char *reln, *owner, *priv, *schnm = NULL; - - mylog("%s: entering... scnm=%x len-%d\n", func, szTableOwner, cbTableOwner); - if (!SC_recycle_statement(stmt)) - return SQL_ERROR; - - /* - * a statement is actually executed, so we'll have to do this - * ourselves. - */ - result_cols = 7; - extend_column_bindings(SC_get_ARD(stmt), result_cols); - - /* set the field names */ - stmt->manual_result = TRUE; - res = QR_Constructor(); - SC_set_Result(stmt, res); - QR_set_num_fields(res, result_cols); - QR_set_field_info(res, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 1, "TABLE_SCHEM", 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, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING); - QR_set_field_info(res, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING); - - /* - * 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; - if (conn->schema_support) - strncpy_null(proc_query, "select relname, usename, relacl, nspname from pg_namespace, pg_class , pg_user where", sizeof(proc_query)); - else - strncpy_null(proc_query, "select relname, usename, relacl from pg_class , pg_user where", sizeof(proc_query)); - if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0) - { - if (conn->schema_support) - { - schema_strcat(proc_query, " nspname = '%.*s' and", szTableOwner, cbTableOwner, szTableName, cbTableName, conn); - } - my_strcat(proc_query, " relname = '%.*s' and", szTableName, cbTableName); - } - else - { - char esc_table_name[MAX_TABLE_LEN * 2]; - int escTbnamelen; - - if (conn->schema_support) - { - escTbnamelen = reallyEscapeCatalogEscapes(szTableOwner, cbTableOwner, esc_table_name, sizeof(esc_table_name), conn->ccsc); - schema_strcat(proc_query, " nspname like '%.*s' and", esc_table_name, escTbnamelen, szTableName, cbTableName, conn); - } - escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc); - my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen); - } - if (conn->schema_support) - strcat(proc_query, " pg_namespace.oid = relnamespace and"); - strcat(proc_query, " pg_user.usesysid = relowner"); - if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "PGAPI_TablePrivileges query error"; - return SQL_ERROR; - } - strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query)); - tablecount = QR_get_num_backend_tuples(res); - if (allures = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !allures) - { - QR_Destructor(res); - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "PGAPI_TablePrivileges query error"; - return SQL_ERROR; - } - usercount = QR_get_num_backend_tuples(allures); - useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX])); - for (i = 0; i < tablecount; i++) - { - memset(useracl, 0, usercount * sizeof(char[ACLMAX])); - acl = (char *) QR_get_value_backend_row(res, i, 2); - if (acl && acl[0] == '{') - user = acl + 1; - else - user = NULL; - for (; user && *user;) - { - grpauth = FALSE; - if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0) - { - user += 7; - grpauth = TRUE; - } - if (delim = strchr(user, '='), !delim) - break; - *delim = '\0'; - auth = delim + 1; - if (grpauth) - { - if (delim = strchr(auth, '"'), delim) - { - *delim = '\0'; - delim++; - } - } - else if (delim = strchr(auth, ','), delim) - *delim = '\0'; - else if (delim = strchr(auth, '}'), delim) - *delim = '\0'; - if (grpauth) /* handle group privilege */ - { - QResultClass *gres; - int i; - char *grolist, *uid, *delm; - - snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user); - if (gres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), gres != NULL) - { - grolist = QR_get_value_backend_row(gres, 0, 0); - if (grolist && grolist[0] == '{') - { - for (uid = grolist + 1; *uid;) - { - if (delm = strchr(uid, ','), delm) - *delm = '\0'; - else if (delm = strchr(uid, '}'), delm) - *delm = '\0'; -mylog("guid=%s\n", uid); - for (i = 0; i < usercount; i++) - { - if (strcmp(QR_get_value_backend_row(allures, i, 1), uid) == 0) - useracl_upd(useracl, allures, QR_get_value_backend_row(allures, i, 0), auth); - } - uid = delm + 1; - } - } - QR_Destructor(gres); - } - } - else - useracl_upd(useracl, allures, user, auth); - if (!delim) - break; - user = delim + 1; - } - reln = QR_get_value_backend_row(res, i, 0); - owner = QR_get_value_backend_row(res, i, 1); - if (conn->schema_support) - schnm = QR_get_value_backend_row(res, i, 3); - /* The owner has all privileges */ - useracl_upd(useracl, allures, owner, ALL_PRIVILIGES); - for (j = 0; j < usercount; j++) - { - user = QR_get_value_backend_row(allures, j, 0); - su = (strcmp(QR_get_value_backend_row(allures, j, 2), "t") == 0); - sys = (strcmp(user, owner) == 0); - /* Super user has all privileges */ - if (su) - useracl_upd(useracl, allures, user, ALL_PRIVILIGES); - for (k = 0; k < ACLMAX; k++) - { - if (!useracl[j][k]) - break; - switch (useracl[j][k]) - { - case 'R': /* rule */ - case 't': /* trigger */ - continue; - } - row = (TupleNode *) malloc(sizeof(TupleNode) + (7 - 1) *sizeof(TupleField)); - set_tuplefield_string(&row->tuple[0], ""); - if (conn->schema_support) - set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(schnm)); - else - set_tuplefield_string(&row->tuple[1], ""); - set_tuplefield_string(&row->tuple[2], reln); - if (su || sys) - set_tuplefield_string(&row->tuple[3], "_SYSTEM"); - else - set_tuplefield_string(&row->tuple[3], owner); - mylog("user=%s\n", user); - set_tuplefield_string(&row->tuple[4], user); - switch (useracl[j][k]) - { - case 'a': - priv = "INSERT"; - break; - case 'r': - priv = "SELECT"; - break; - case 'w': - priv = "UPDATE"; - break; - case 'd': - priv = "DELETE"; - break; - case 'x': - priv = "REFERENCES"; - break; - default: - priv = ""; - } - set_tuplefield_string(&row->tuple[5], priv); - /* The owner and the super user are grantable */ - if (sys || su) - set_tuplefield_string(&row->tuple[6], "YES"); - else - set_tuplefield_string(&row->tuple[6], "NO"); - QR_add_tuple(SC_get_Result(stmt), row); - } - } - } - free(useracl); - QR_Destructor(res); - QR_Destructor(allures); - return SQL_SUCCESS; -} diff --git a/src/interfaces/odbc/info30.c b/src/interfaces/odbc/info30.c deleted file mode 100644 index 5e5b834690..0000000000 --- a/src/interfaces/odbc/info30.c +++ /dev/null @@ -1,396 +0,0 @@ -/*------- - * Module: info30.c - * - * Description: This module contains routines related to ODBC 3.0 - * SQLGetInfo(). - * - */ - -#ifndef ODBCVER -#define ODBCVER 0x0300 -#endif - -#include "connection.h" -#include "pgapifunc.h" - -RETCODE SQL_API -PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, - SWORD cbInfoValueMax, SWORD FAR * pcbInfoValue) -{ - static char *func = "PGAPI_GetInfo30"; - ConnectionClass *conn = (ConnectionClass *) hdbc; - ConnInfo *ci = &(conn->connInfo); - char *p = NULL; - int len = 0, - value = 0; - RETCODE result; - - switch (fInfoType) - { - case SQL_DYNAMIC_CURSOR_ATTRIBUTES1: - len = 4; - value = 0; - break; - case SQL_DYNAMIC_CURSOR_ATTRIBUTES2: - len = 4; - value = 0; - break; - - case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1: - len = 4; - value = SQL_CA1_NEXT; /* others aren't allowed in ODBC spec */ - break; - case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2: - len = 4; - value = SQL_CA2_READ_ONLY_CONCURRENCY; - break; - case SQL_KEYSET_CURSOR_ATTRIBUTES1: - len = 4; - value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE - | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK - | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION - | SQL_CA1_POS_REFRESH; - if (ci->updatable_cursors || ci->drivers.lie) - value |= (SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE - | SQL_CA1_BULK_ADD - | SQL_CA1_BULK_UPDATE_BY_BOOKMARK - | SQL_CA1_BULK_DELETE_BY_BOOKMARK - | SQL_CA1_BULK_FETCH_BY_BOOKMARK - ); - if (ci->drivers.lie) - value |= (SQL_CA1_LOCK_EXCLUSIVE - | SQL_CA1_LOCK_UNLOCK - | SQL_CA1_POSITIONED_UPDATE - | SQL_CA1_POSITIONED_DELETE - | SQL_CA1_SELECT_FOR_UPDATE - ); - break; - case SQL_KEYSET_CURSOR_ATTRIBUTES2: - len = 4; - value = SQL_CA2_READ_ONLY_CONCURRENCY; - if (ci->updatable_cursors || ci->drivers.lie) - value |= (SQL_CA2_OPT_ROWVER_CONCURRENCY - /*| SQL_CA2_CRC_APPROXIMATE*/ - | SQL_CA2_CRC_EXACT - | SQL_CA2_SENSITIVITY_DELETIONS - | SQL_CA2_SENSITIVITY_UPDATES - /* | SQL_CA2_SENSITIVITY_ADDITIONS */ - ); - if (ci->drivers.lie) - value |= (SQL_CA2_READ_ONLY_CONCURRENCY - | SQL_CA2_LOCK_CONCURRENCY - | SQL_CA2_OPT_VALUES_CONCURRENCY - | SQL_CA2_MAX_ROWS_SELECT - | SQL_CA2_MAX_ROWS_INSERT - | SQL_CA2_MAX_ROWS_DELETE - | SQL_CA2_MAX_ROWS_UPDATE - | SQL_CA2_MAX_ROWS_CATALOG - | SQL_CA2_MAX_ROWS_AFFECTS_ALL - | SQL_CA2_SIMULATE_NON_UNIQUE - | SQL_CA2_SIMULATE_TRY_UNIQUE - | SQL_CA2_SIMULATE_UNIQUE - ); - break; - - case SQL_STATIC_CURSOR_ATTRIBUTES1: - len = 4; - value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE - | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK - | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION - | SQL_CA1_POS_REFRESH; - if (ci->updatable_cursors) - value |= (SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE - | SQL_CA1_BULK_ADD - ); - break; - case SQL_STATIC_CURSOR_ATTRIBUTES2: - len = 4; - value = SQL_CA2_READ_ONLY_CONCURRENCY; - if (ci->updatable_cursors) - value |= (SQL_CA2_OPT_ROWVER_CONCURRENCY - | SQL_CA2_CRC_EXACT - /* | SQL_CA2_SENSITIVITY_ADDITIONS - | SQL_CA2_SENSITIVITY_DELETIONS - | SQL_CA2_SENSITIVITY_UPDATES */ - ); - break; - - case SQL_ODBC_INTERFACE_CONFORMANCE: - len = 4; - value = SQL_OIC_CORE; - if (ci->drivers.lie) - value = SQL_OIC_LEVEL2; - break; - case SQL_ACTIVE_ENVIRONMENTS: - len = 2; - value = 0; - break; - case SQL_AGGREGATE_FUNCTIONS: - len = 4; - value = SQL_AF_ALL; - break; - case SQL_ALTER_DOMAIN: - len = 4; - value = 0; - break; - case SQL_ASYNC_MODE: - len = 4; - value = SQL_AM_NONE; - break; - case SQL_BATCH_ROW_COUNT: - len = 4; - value = SQL_BRC_EXPLICIT; - break; - case SQL_BATCH_SUPPORT: - len = 4; - value = SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT; - break; - case SQL_CATALOG_NAME: - len = 0; - if (PG_VERSION_LE(conn, 7.2)) - p = "N"; - else - p = "Y"; /* hopefully */ - break; - case SQL_COLLATION_SEQ: - len = 0; - p = ""; - break; - case SQL_CREATE_ASSERTION: - len = 4; - value = 0; - break; - case SQL_CREATE_CHARACTER_SET: - len = 4; - value = 0; - break; - case SQL_CREATE_COLLATION: - len = 4; - value = 0; - break; - case SQL_CREATE_DOMAIN: - len = 4; - value = 0; - break; - case SQL_CREATE_SCHEMA: - len = 4; - if (conn->schema_support) - value = SQL_CS_CREATE_SCHEMA | SQL_CS_AUTHORIZATION; - else - value = 0; - break; - case SQL_CREATE_TABLE: - len = 4; - value = SQL_CT_CREATE_TABLE | SQL_CT_TABLE_CONSTRAINT - | SQL_CT_CONSTRAINT_NAME_DEFINITION - | SQL_CT_LOCAL_TEMPORARY | SQL_CT_COLUMN_CONSTRAINT - | SQL_CT_COLUMN_DEFAULT | SQL_CT_CONSTRAINT_INITIALLY_DEFERRED - | SQL_CT_CONSTRAINT_INITIALLY_IMMEDIATE | SQL_CT_CONSTRAINT_DEFERRABLE; - break; - case SQL_CREATE_TRANSLATION: - len = 4; - value = 0; - break; - case SQL_CREATE_VIEW: - len = 4; - value = SQL_CV_CREATE_VIEW; - break; - case SQL_DDL_INDEX: - len = 4; - value = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX; - break; - case SQL_DESCRIBE_PARAMETER: - len = 0; - p = "N"; - break; - case SQL_DROP_ASSERTION: - len = 4; - value = 0; - break; - case SQL_DROP_CHARACTER_SET: - len = 4; - value = 0; - break; - case SQL_DROP_COLLATION: - len = 4; - value = 0; - break; - case SQL_DROP_DOMAIN: - len = 4; - value = 0; - break; - case SQL_DROP_SCHEMA: - len = 4; - if (conn->schema_support) - value = SQL_DS_DROP_SCHEMA | SQL_DS_RESTRICT | SQL_DS_CASCADE; - else - value = 0; - break; - case SQL_DROP_TABLE: - len = 4; - value = SQL_DT_DROP_TABLE; - if (PG_VERSION_GT(conn, 7.2)) /* hopefully */ - value |= (SQL_DT_RESTRICT | SQL_DT_CASCADE); - break; - case SQL_DROP_TRANSLATION: - len = 4; - value = 0; - break; - case SQL_DROP_VIEW: - len = 4; - value = SQL_DV_DROP_VIEW; - if (PG_VERSION_GT(conn, 7.2)) /* hopefully */ - value |= (SQL_DV_RESTRICT | SQL_DV_CASCADE); - break; - case SQL_INDEX_KEYWORDS: - len = 4; - value = SQL_IK_NONE; - case SQL_INFO_SCHEMA_VIEWS: - len = 4; - value = 0; - break; - case SQL_INSERT_STATEMENT: - len = 4; - value = SQL_IS_INSERT_LITERALS | SQL_IS_INSERT_SEARCHED | SQL_IS_SELECT_INTO; - break; - case SQL_MAX_IDENTIFIER_LEN: - len = 4; - value = 32; - break; - case SQL_MAX_ROW_SIZE_INCLUDES_LONG: - len = 0; - p = "Y"; - break; - case SQL_PARAM_ARRAY_ROW_COUNTS: - len = 4; - value = SQL_PARC_BATCH; - break; - case SQL_PARAM_ARRAY_SELECTS: - len = 4; - value = SQL_PAS_BATCH; - break; - case SQL_SQL_CONFORMANCE: - len = 4; - value = SQL_SC_SQL92_ENTRY; - break; - case SQL_SQL92_DATETIME_FUNCTIONS: - len = 4; - value = SQL_SDF_CURRENT_DATE | SQL_SDF_CURRENT_TIME | SQL_SDF_CURRENT_TIMESTAMP; - break; - case SQL_SQL92_FOREIGN_KEY_DELETE_RULE: - len = 4; - value = SQL_SFKD_CASCADE | SQL_SFKD_NO_ACTION | SQL_SFKD_SET_DEFAULT | SQL_SFKD_SET_NULL; - break; - case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE: - len = 4; - value = SQL_SFKU_CASCADE | SQL_SFKU_NO_ACTION | SQL_SFKU_SET_DEFAULT | SQL_SFKU_SET_NULL; - break; - case SQL_SQL92_GRANT: - len = 4; - value = SQL_SG_DELETE_TABLE | SQL_SG_INSERT_TABLE | SQL_SG_REFERENCES_TABLE | SQL_SG_SELECT_TABLE | SQL_SG_UPDATE_TABLE; - break; - case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS: - len = 4; - value = SQL_SNVF_BIT_LENGTH | SQL_SNVF_CHAR_LENGTH - | SQL_SNVF_CHARACTER_LENGTH | SQL_SNVF_EXTRACT - | SQL_SNVF_OCTET_LENGTH | SQL_SNVF_POSITION; - break; - case SQL_SQL92_PREDICATES: - len = 4; - value = SQL_SP_BETWEEN | SQL_SP_COMPARISON - | SQL_SP_EXISTS | SQL_SP_IN - | SQL_SP_ISNOTNULL | SQL_SP_ISNULL - | SQL_SP_LIKE | SQL_SP_OVERLAPS - | SQL_SP_QUANTIFIED_COMPARISON; - break; - case SQL_SQL92_RELATIONAL_JOIN_OPERATORS: - len = 4; - if (PG_VERSION_GE(conn, 7.1)) - value = SQL_SRJO_CROSS_JOIN | SQL_SRJO_EXCEPT_JOIN - | SQL_SRJO_FULL_OUTER_JOIN | SQL_SRJO_INNER_JOIN - | SQL_SRJO_INTERSECT_JOIN | SQL_SRJO_LEFT_OUTER_JOIN - | SQL_SRJO_NATURAL_JOIN | SQL_SRJO_RIGHT_OUTER_JOIN - | SQL_SRJO_UNION_JOIN; - break; - case SQL_SQL92_REVOKE: - len = 4; - value = SQL_SR_DELETE_TABLE | SQL_SR_INSERT_TABLE | SQL_SR_REFERENCES_TABLE | SQL_SR_SELECT_TABLE | SQL_SR_UPDATE_TABLE; - break; - case SQL_SQL92_ROW_VALUE_CONSTRUCTOR: - len = 4; - value = SQL_SRVC_VALUE_EXPRESSION | SQL_SRVC_NULL; - break; - case SQL_SQL92_STRING_FUNCTIONS: - len = 4; - value = SQL_SSF_CONVERT | SQL_SSF_LOWER - | SQL_SSF_UPPER | SQL_SSF_SUBSTRING - | SQL_SSF_TRANSLATE | SQL_SSF_TRIM_BOTH - | SQL_SSF_TRIM_LEADING | SQL_SSF_TRIM_TRAILING; - break; - case SQL_SQL92_VALUE_EXPRESSIONS: - len = 4; - value = SQL_SVE_CASE | SQL_SVE_CAST | SQL_SVE_COALESCE | SQL_SVE_NULLIF; - break; - /* The followings aren't implemented yet */ - case SQL_DATETIME_LITERALS: - len = 4; - case SQL_DM_VER: - len = 0; - case SQL_DRIVER_HDESC: - len = 4; - case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS: - len = 4; - case SQL_STANDARD_CLI_CONFORMANCE: - len = 4; - case SQL_XOPEN_CLI_YEAR: - len = 0; - default: - /* unrecognized key */ - conn->errormsg = "Unrecognized key passed to SQLGetInfo30."; - conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - result = SQL_SUCCESS; - mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax); - 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; -} diff --git a/src/interfaces/odbc/iodbc.h b/src/interfaces/odbc/iodbc.h deleted file mode 100644 index f8e7d248b1..0000000000 --- a/src/interfaces/odbc/iodbc.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _IODBC_H -#define _IODBC_H - -#if !defined(WIN32) && !defined(WIN32_SYSTEM) -#define _UNIX_ - -#include <stdlib.h> -#include <sys/types.h> - -#define MEM_ALLOC(size) (malloc((size_t)(size))) -#define MEM_FREE(ptr) \ -do { \ - if(ptr) \ - free(ptr); \ -} while (0) - -#define STRCPY(t, s) (strcpy((char*)(t), (char*)(s))) -#define STRNCPY(t,s,n) (strncpy((char*)(t), (char*)(s), (size_t)(n))) -#define STRCAT(t, s) (strcat((char*)(t), (char*)(s))) -#define STRNCAT(t,s,n) (strncat((char*)(t), (char*)(s), (size_t)(n))) -#define STREQ(a, b) (strcmp((char*)(a), (char*)(b)) == 0) -#define STRLEN(str) ((str)? strlen((char*)(str)):0) - -#define EXPORT -#define CALLBACK -#define FAR - -typedef signed short SSHOR; -typedef short WORD; -typedef long DWORD; - -typedef WORD WPARAM; -typedef DWORD LPARAM; -typedef void *HWND; -typedef int BOOL; -#endif /* _UNIX_ */ - -#if defined(WIN32) || defined(WIN32_SYSTEM) - -#include <windows.h> -#include <windowsx.h> - -#ifdef _MSVC_ -#define MEM_ALLOC(size) (fmalloc((size_t)(size))) -#define MEM_FREE(ptr) ((ptr)? ffree((PTR)(ptr)):0)) -#define STRCPY(t, s) (fstrcpy((char FAR*)(t), (char FAR*)(s))) -#define STRNCPY(t,s,n) (fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n))) -#define STRLEN(str) ((str)? fstrlen((char FAR*)(str)):0) -#define STREQ(a, b) (fstrcmp((char FAR*)(a), (char FAR*)(b) == 0) -#endif - -#ifdef _BORLAND_ -#define MEM_ALLOC(size) (farmalloc((unsigned long)(size)) -#define MEM_FREE(ptr) ((ptr)? farfree((void far*)(ptr)):0) -#define STRCPY(t, s) (_fstrcpy((char FAR*)(t), (char FAR*)(s))) -#define STRNCPY(t,s,n) (_fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n))) -#define STRLEN(str) ((str)? _fstrlen((char FAR*)(str)):0) -#define STREQ(a, b) (_fstrcmp((char FAR*)(a), (char FAR*)(b) == 0) -#endif -#endif /* WIN32 */ - -#define SYSERR (-1) - -#ifndef NULL -#define NULL ((void FAR*)0UL) -#endif - -#endif diff --git a/src/interfaces/odbc/isql.h b/src/interfaces/odbc/isql.h deleted file mode 100644 index f27c087d52..0000000000 --- a/src/interfaces/odbc/isql.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Modified isql.h file from iodbc. This file should be placed in the - * include path to be used to create ODBC compliant applications. - */ - -#ifndef _INTRINSIC_SQL_H -#define _INTRINSIC_SQL_H - -typedef unsigned char UCHAR; -typedef long int SDWORD; -typedef short int SWORD; -typedef unsigned long int UDWORD; -typedef unsigned short int UWORD; - -typedef void FAR *PTR; - -typedef void FAR *HENV; -typedef void FAR *HDBC; -typedef void FAR *HSTMT; - -typedef signed short RETCODE; - -#ifdef WIN32 -#define SQL_API __stdcall -#else -#define SQL_API EXPORT CALLBACK -#endif - -/*#define ODBCVER 0x0250 */ - -#define SQL_MAX_MESSAGE_LENGTH 512 -#define SQL_MAX_DSN_LENGTH 32 - -/* return code */ -#define SQL_INVALID_HANDLE (-2) -#define SQL_ERROR (-1) -#define SQL_SUCCESS 0 -#define SQL_SUCCESS_WITH_INFO 1 -#define SQL_NO_DATA_FOUND 100 - -/* standard SQL datatypes (agree with ANSI type numbering) */ -#define SQL_CHAR 1 -#define SQL_NUMERIC 2 -#define SQL_DECIMAL 3 -#define SQL_INTEGER 4 -#define SQL_SMALLINT 5 -#define SQL_FLOAT 6 -#define SQL_REAL 7 -#define SQL_DOUBLE 8 -#define SQL_VARCHAR 12 - -#define SQL_TYPE_MIN SQL_CHAR -#define SQL_TYPE_NULL 0 -#define SQL_TYPE_MAX SQL_VARCHAR - -/* C to SQL datatype mapping */ -#define SQL_C_CHAR SQL_CHAR -#define SQL_C_LONG SQL_INTEGER -#define SQL_C_SHORT SQL_SMALLINT -#define SQL_C_FLOAT SQL_REAL -#define SQL_C_DOUBLE SQL_DOUBLE -#define SQL_C_DEFAULT 99 - -#define SQL_NO_NULLS 0 -#define SQL_NULLABLE 1 -#define SQL_NULLABLE_UNKNOWN 2 - -/* some special length values */ -#define SQL_NULL_DATA (-1) -#define SQL_DATA_AT_EXEC (-2) -#define SQL_NTS (-3) - -/* SQLFreeStmt flag values */ -#define SQL_CLOSE 0 -#define SQL_DROP 1 -#define SQL_UNBIND 2 -#define SQL_RESET_PARAMS 3 - -/* SQLTransact flag values */ -#define SQL_COMMIT 0 -#define SQL_ROLLBACK 1 - -/* SQLColAttributes flag values */ -#define SQL_COLUMN_COUNT 0 -#define SQL_COLUMN_LABEL 18 -#define SQL_COLATT_OPT_MAX SQL_COLUMN_LABEL -#define SQL_COLUMN_DRIVER_START 1000 - -#define SQL_COLATT_OPT_MIN SQL_COLUMN_COUNT - -/* Null handles */ -#define SQL_NULL_HENV 0 -#define SQL_NULL_HDBC 0 -#define SQL_NULL_HSTMT 0 - -/* All code below has been added to the original isql.h coming from iodbc */ -typedef unsigned char BYTE; - -/* More SQLColAttributes flag values */ -#define SQL_COLUMN_NAME 1 -#define SQL_COLUMN_TYPE 2 -#define SQL_COLUMN_LENGTH 3 -#define SQL_COLUMN_PRECISION 4 -#define SQL_COLUMN_SCALE 5 -#define SQL_COLUMN_DISPLAY_SIZE 6 -#define SQL_COLUMN_NULLABLE 7 -#define SQL_COLUMN_UNSIGNED 8 -#define SQL_COLUMN_MONEY 9 -#define SQL_COLUMN_UPDATABLE 10 -#define SQL_COLUMN_AUTO_INCREMENT 11 -#define SQL_COLUMN_CASE_SENSITIVE 12 -#define SQL_COLUMN_SEARCHABLE 13 -#define SQL_COLUMN_TYPE_NAME 14 -#define SQL_COLUMN_TABLE_NAME 15 -#define SQL_COLUMN_OWNER_NAME 16 -#define SQL_COLUMN_QUALIFIER_NAME 17 - -/* SQLColAttributes Searchable flags */ -#define SQL_UNSEARCHABLE 0 -#define SQL_LIKE_ONLY 1 -#define SQL_ALL_EXCEPT_LIKE 2 -#define SQL_SEARCHABLE 3 -#define SQL_PRED_SEARCHABLE SQL_SEARCHABLE - -/* SQLColAttributes Updateable flags */ -#define SQL_ATTR_READONLY 0 -#define SQL_ATTR_WRITE 1 -#define SQL_ATTR_READWRITE_UNKNOWN 2 - -/* - * function prototypes previously not contained in isql.h - */ -#ifdef __cplusplus -extern "C" -{ -#endif - -RETCODE SQL_API SQLAllocConnect(HENV henv, - HDBC FAR * phdbc); -RETCODE SQL_API SQLAllocEnv(HENV FAR * phenv); -RETCODE SQL_API SQLAllocStmt(HDBC hdbc, - HSTMT FAR * phstmt); -RETCODE SQL_API SQLBindCol(HSTMT hstmt, - UWORD icol, - SWORD fCType, - PTR rgbValue, - SDWORD cbValueMax, - SDWORD FAR * pcbValue); - -RETCODE SQL_API SQLCancel(HSTMT hstmt); - -RETCODE SQL_API SQLColAttributes(HSTMT hstmt, - UWORD icol, - UWORD fDescType, - PTR rgbDesc, - SWORD cbDescMax, - SWORD FAR * pcbDesc, - SDWORD FAR * pfDesc); - -RETCODE SQL_API SQLConnect(HDBC hdbc, - UCHAR FAR * szDSN, - SWORD cbDSN, - UCHAR FAR * szUID, - SWORD cbUID, - UCHAR FAR * szAuthStr, - SWORD cbAuthStr); - -RETCODE SQL_API SQLDescribeCol(HSTMT hstmt, - UWORD icol, - UCHAR FAR * szColName, - SWORD cbColNameMax, - SWORD FAR * pcbColName, - SWORD FAR * pfSqlType, - UDWORD FAR * pcbColDef, - SWORD FAR * pibScale, - SWORD FAR * pfNullable); - -RETCODE SQL_API SQLDisconnect(HDBC hdbc); - -RETCODE SQL_API SQLError(HENV henv, - HDBC hdbc, - HSTMT hstmt, - UCHAR FAR * szSqlState, - SDWORD FAR * pfNativeError, - UCHAR FAR * szErrorMsg, - SWORD cbErrorMsgMax, - SWORD FAR * pcbErrorMsg); - -RETCODE SQL_API SQLExecDirect(HSTMT hstmt, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStr); - -RETCODE SQL_API SQLExecute(HSTMT hstmt); - -RETCODE SQL_API SQLFetch(HSTMT hstmt); - -RETCODE SQL_API SQLFreeConnect(HDBC hdbc); - -RETCODE SQL_API SQLFreeEnv(HENV henv); - -RETCODE SQL_API SQLFreeStmt(HSTMT hstmt, - UWORD fOption); - -RETCODE SQL_API SQLGetCursorName(HSTMT hstmt, - UCHAR FAR * szCursor, - SWORD cbCursorMax, - SWORD FAR * pcbCursor); - -RETCODE SQL_API SQLNumResultCols(HSTMT hstmt, - SWORD FAR * pccol); - -RETCODE SQL_API SQLPrepare(HSTMT hstmt, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStr); - -RETCODE SQL_API SQLRowCount(HSTMT hstmt, - SDWORD FAR * pcrow); - -RETCODE SQL_API SQLSetCursorName(HSTMT hstmt, - UCHAR FAR * szCursor, - SWORD cbCursor); - -RETCODE SQL_API SQLTransact(HENV henv, - HDBC hdbc, - UWORD fType); - -RETCODE SQL_API SQLSetParam(HSTMT hstmt, - UWORD ipar, - SWORD fCType, - SWORD fSqlType, - UDWORD cbColDef, - SWORD ibScale, - PTR rgbValue, - SDWORD FAR * pcbValue); - -RETCODE SQL_API SQLDataSources(HENV henv, - UWORD Direction, UCHAR FAR * ServerName, - WORD BufferLength1, WORD *NameLength1, - UCHAR FAR * Description, WORD BufferLength2, - WORD *NameLength2); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/interfaces/odbc/isqlext.h b/src/interfaces/odbc/isqlext.h deleted file mode 100644 index 989860b615..0000000000 --- a/src/interfaces/odbc/isqlext.h +++ /dev/null @@ -1,1560 +0,0 @@ -/* - * This file has been modified from the original isqlext.h to add the - * missing function prototypes and appropriate #defines. It is designed - * to be a drop in replacement for isqlext.h from iodbc. - */ - -#ifndef _INTRINSIC_SQLEXT_H -#define _INTRINSIC_SQLEXT_H - -#include "isql.h" - -#define SQL_STILL_EXECUTING 2 -#define SQL_NEED_DATA 99 - -/* extend SQL datatypes */ -#define SQL_DATE 9 -#define SQL_TIME 10 -#define SQL_TIMESTAMP 11 -#define SQL_LONGVARCHAR (-1) -#define SQL_BINARY (-2) -#define SQL_VARBINARY (-3) -#define SQL_LONGVARBINARY (-4) -#define SQL_BIGINT (-5) -#define SQL_TINYINT (-6) -#define SQL_BIT (-7) /* conflict with SQL3 ??? */ -#define SQL_TYPE_DRIVER_START (-80) - -/* C to SQL datatype mapping */ -#define SQL_C_DATE SQL_DATE -#define SQL_C_TIME SQL_TIME -#define SQL_C_TIMESTAMP SQL_TIMESTAMP -#define SQL_C_BINARY SQL_BINARY -#define SQL_C_BIT SQL_BIT -#define SQL_C_TINYINT SQL_TINYINT - -#define SQL_SIGNED_OFFSET (-20) -#define SQL_UNSIGNED_OFFSET (-22) - -#define SQL_C_SLONG (SQL_C_LONG + SQL_SIGNED_OFFSET) -#define SQL_C_SSHORT (SQL_C_SHORT + SQL_SIGNED_OFFSET) -#define SQL_C_STINYINT (SQL_TINYINT + SQL_SIGNED_OFFSET) -#define SQL_C_ULONG (SQL_C_LONG + SQL_UNSIGNED_OFFSET) -#define SQL_C_USHORT (SQL_C_SHORT + SQL_UNSIGNED_OFFSET) -#define SQL_C_UTINYINT (SQL_TINYINT + SQL_UNSIGNED_OFFSET) -#define SQL_C_BOOKMARK SQL_C_ULONG - -#if defined(SQL_TYPE_MIN) -#undef SQL_TYPE_MIN -#define SQL_TYPE_MIN SQL_BIT -/* Note:If SQL_BIT uses SQL3 value (i.e. 14) then, - * SQL_TYPE_MIN need to be defined as SQL_TINYINT - * (i.e. -6). - */ -#endif - -#define SQL_ALL_TYPES 0 - -/* SQLDriverConnect flag values */ -#define SQL_DRIVER_NOPROMPT 0 -#define SQL_DRIVER_COMPLETE 1 -#define SQL_DRIVER_PROMPT 2 -#define SQL_DRIVER_COMPLETE_REQUIRED 3 - -/* SQLSetParam extensions */ -#define SQL_DEFAULT_PARAM (-5) -#define SQL_IGNORE (-6) - -/* function number for SQLGetFunctions and _iodbcdm_getproc */ -#define SQL_API_SQLALLOCCONNECT 1 -#define SQL_API_SQLALLOCENV 2 -#define SQL_API_SQLALLOCSTMT 3 -#define SQL_API_SQLBINDCOL 4 -#define SQL_API_SQLCANCEL 5 -#define SQL_API_SQLCOLATTRIBUTES 6 -#define SQL_API_SQLCONNECT 7 -#define SQL_API_SQLDESCRIBECOL 8 -#define SQL_API_SQLDISCONNECT 9 -#define SQL_API_SQLERROR 10 -#define SQL_API_SQLEXECDIRECT 11 -#define SQL_API_SQLEXECUTE 12 -#define SQL_API_SQLFETCH 13 -#define SQL_API_SQLFREECONNECT 14 -#define SQL_API_SQLFREEENV 15 -#define SQL_API_SQLFREESTMT 16 -#define SQL_API_SQLGETCURSORNAME 17 -#define SQL_API_SQLNUMRESULTCOLS 18 -#define SQL_API_SQLPREPARE 19 -#define SQL_API_SQLROWCOUNT 20 -#define SQL_API_SQLSETCURSORNAME 21 -#define SQL_API_SQLSETPARAM 22 -#define SQL_API_SQLTRANSACT 23 - -#define SQL_NUM_FUNCTIONS 23 - -#define SQL_EXT_API_START 40 - -#define SQL_API_SQLCOLUMNS 40 - -#define SQL_API_SQLDRIVERCONNECT 41 -#define SQL_API_SQLGETCONNECTOPTION 42 -#define SQL_API_SQLGETDATA 43 -#define SQL_API_SQLGETFUNCTIONS 44 -#define SQL_API_SQLGETINFO 45 -#define SQL_API_SQLGETSTMTOPTION 46 -#define SQL_API_SQLGETTYPEINFO 47 -#define SQL_API_SQLPARAMDATA 48 -#define SQL_API_SQLPUTDATA 49 -#define SQL_API_SQLSETCONNECTOPTION 50 -#define SQL_API_SQLSETSTMTOPTION 51 -#define SQL_API_SQLSPECIALCOLUMNS 52 -#define SQL_API_SQLSTATISTICS 53 -#define SQL_API_SQLTABLES 54 - -#define SQL_API_SQLBROWSECONNECT 55 -#define SQL_API_SQLCOLUMNPRIVILEGES 56 -#define SQL_API_SQLDATASOURCES 57 -#define SQL_API_SQLDESCRIBEPARAM 58 -#define SQL_API_SQLEXTENDEDFETCH 59 -#define SQL_API_SQLFOREIGNKEYS 60 -#define SQL_API_SQLMORERESULTS 61 -#define SQL_API_SQLNATIVESQL 62 -#define SQL_API_SQLNUMPARAMS 63 -#define SQL_API_SQLPARAMOPTIONS 64 -#define SQL_API_SQLPRIMARYKEYS 65 -#define SQL_API_SQLPROCEDURECOLUMNS 66 -#define SQL_API_SQLPROCEDURES 67 -#define SQL_API_SQLSETPOS 68 -#define SQL_API_SQLSETSCROLLOPTIONS 69 -#define SQL_API_SQLTABLEPRIVILEGES 70 - -#define SQL_API_SQLDRIVERS 71 -#define SQL_API_SQLBINDPARAMETER 72 -#define SQL_EXT_API_LAST SQL_API_SQLBINDPARAMETER -#define SQL_NUM_EXTENSIONS (SQL_EXT_API_LAST - SQL_EXT_API_START + 1) - -#define SQL_API_ALL_FUNCTIONS 0 - -/* SQLGetInfo infor number */ -#define SQL_INFO_FIRST 0 -#define SQL_DRIVER_HDBC 3 -#define SQL_DRIVER_HENV 4 -#define SQL_DRIVER_HSTMT 5 -#define SQL_DRIVER_NAME 6 -#define SQL_ODBC_VER 10 -#define SQL_CURSOR_COMMIT_BEHAVIOR 23 -#define SQL_CURSOR_ROLLBACK_BEHAVIOR 24 -#define SQL_DEFAULT_TXN_ISOLATION 26 - -#define SQL_TXN_ISOLATION_OPTION 72 -#define SQL_NON_NULLABLE_COLUMNS 75 - -#define SQL_DRIVER_HLIB 76 -#define SQL_DRIVER_ODBC_VER 77 - -#define SQL_QUALIFIER_LOCATION 114 - -#define SQL_INFO_LAST SQL_QUALIFIER_LOCATION - -#define SQL_INFO_DRIVER_START 1000 - - -/* SQL_TXN_ISOLATION_OPTION masks */ -#define SQL_TXN_READ_UNCOMMITTED 0x00000001L -#define SQL_TXN_READ_COMMITTED 0x00000002L -#define SQL_TXN_REPEATABLE_READ 0x00000004L -#define SQL_TXN_SERIALIZABLE 0x00000008L -#define SQL_TXN_VERSIONING 0x00000010L - -/* SQL_CURSOR_COMMIT_BEHAVIOR and SQL_CURSOR_ROLLBACK_BEHAVIOR values */ - -#define SQL_CB_DELETE 0x0000 -#define SQL_CB_CLOSE 0x0001 -#define SQL_CB_PRESERVE 0x0002 - -/* options for SQLGetStmtOption/SQLSetStmtOption */ -#define SQL_QUERY_TIMEOUT 0 -#define SQL_MAX_ROWS 1 -#define SQL_NOSCAN 2 -#define SQL_MAX_LENGTH 3 -#define SQL_ASYNC_ENABLE 4 -#define SQL_BIND_TYPE 5 -#define SQL_CURSOR_TYPE 6 -#define SQL_CONCURRENCY 7 -#define SQL_KEYSET_SIZE 8 -#define SQL_ROWSET_SIZE 9 -#define SQL_SIMULATE_CURSOR 10 -#define SQL_RETRIEVE_DATA 11 -#define SQL_USE_BOOKMARKS 12 -#define SQL_GET_BOOKMARK 13 /* GetStmtOption Only */ -#define SQL_ROW_NUMBER 14 /* GetStmtOption Only */ -#define SQL_STMT_OPT_MAX SQL_ROW_NUMBER - -#define SQL_STMT_OPT_MIN SQL_QUERY_TIMEOUT - -/* - * ODBC 3.0 renames the above to SQL_ATTR_ values. At this time I don't - * know if they have also been renumbered or not, I will assume not. - */ -#define SQL_ATTR_QUERY_TIMEOUT 0 -#define SQL_ATTR_MAX_ROWS 1 -#define SQL_ATTR_NOSCAN 2 -#define SQL_ATTR_MAX_LENGTH 3 -#define SQL_ATTR_ASYNC_ENABLE 4 -#define SQL_ATTR_BIND_TYPE 5 -#define SQL_ATTR_CURSOR_TYPE 6 -#define SQL_ATTR_CONCURRENCY 7 -#define SQL_ATTR_KEYSET_SIZE 8 -#define SQL_ATTR_ROWSET_SIZE 9 -#define SQL_ATTR_SIMULATE_CURSOR 10 -#define SQL_ATTR_RETRIEVE_DATA 11 -#define SQL_ATTR_USE_BOOKMARKS 12 -#define SQL_ATTR_GET_BOOKMARK 13 /* GetStmtOption Only */ -#define SQL_ATTR_ROW_NUMBER 14 /* GetStmtOption Only */ - -/* New in ODBC 3.0 */ -#define SQL_ATTR_APP_PARAM_DESC 15 -#define SQL_ATTR_APP_ROW_DESC 16 -#define SQL_ATTR_CURSOR_SCROLLABLE 17 -#define SQL_ATTR_CURSOR_SENSITITY 18 -#define SQL_ATTR_ENABLE_AUTO_IPD 19 -#define SQL_ATTR_FETCH_BOOKMARK_PTR 20 -#define SQL_ATTR_IMP_PARAM_DESC 21 -#define SQL_ATTR_IMP_ROW_DESC 22 -#define SQL_ATTR_METADATA_ID 23 -#define SQL_ATTR_PARAM_BIND_OFFSET_PTR 24 -#define SQL_ATTR_PARAM_BIND_TYPE 25 -#define SQL_ATTR_PARAM_OPERATION_PTR 26 -#define SQL_ATTR_PARAM_STATUS_PTR 27 -#define SQL_ATTR_PARAMS_PROCESSED_PTR 28 -#define SQL_ATTR_PARAMSET_SIZE 29 -#define SQL_ATTR_ROW_ARRAY_SIZE 30 -#define SQL_ATTR_ROW_BIND_OFFSET_PTR 31 -#define SQL_ATTR_ROW_OPERATION_PTR 32 -#define SQL_ATTR_ROW_STATUS_PTR 33 -#define SQL_ATTR_ROWS_FETCHED_PTR 34 - -#define SQL_STMT_ATTR_MIN SQL_ATTR_QUERY_TIMEOUT -#define SQL_STMT_ATTR_MAX SQL_ATTR_ROWS_FETCHED_PTR - -/* SQL_QUERY_TIMEOUT options */ -#define SQL_QUERY_TIMEOUT_DEFAULT 0UL - -/* SQL_MAX_ROWS options */ -#define SQL_MAX_ROWS_DEFAULT 0UL - -/* SQL_MAX_LENGTH options */ -#define SQL_MAX_LENGTH_DEFAULT 0UL - -/* SQL_CONCURRENCY options */ -#define SQL_CONCUR_READ_ONLY 1 -#define SQL_CONCUR_LOCK 2 -#define SQL_CONCUR_ROWVER 3 -#define SQL_CONCUR_VALUES 4 - -/* options for SQLSetConnectOption/SQLGetConnectOption */ -#define SQL_ACCESS_MODE 101 -#define SQL_AUTOCOMMIT 102 -#define SQL_LOGIN_TIMEOUT 103 -#define SQL_OPT_TRACE 104 -#define SQL_OPT_TRACEFILE 105 -#define SQL_TRANSLATE_DLL 106 -#define SQL_TRANSLATE_OPTION 107 -#define SQL_TXN_ISOLATION 108 -#define SQL_CURRENT_QUALIFIER 109 -#define SQL_ODBC_CURSORS 110 -#define SQL_QUIET_MODE 111 -#define SQL_PACKET_SIZE 112 -#define SQL_CONN_OPT_MAX SQL_PACKET_SIZE -#define SQL_CONNECT_OPT_DRVR_START 1000 - -#define SQL_CONN_OPT_MIN SQL_ACCESS_MODE - -/* SQL_ACCESS_MODE options */ -#define SQL_MODE_READ_WRITE 0UL -#define SQL_MODE_READ_ONLY 1UL -#define SQL_MODE_DEFAULT SQL_MODE_READ_WRITE - -/* SQL_AUTOCOMMIT options */ -#define SQL_AUTOCOMMIT_OFF 0UL -#define SQL_AUTOCOMMIT_ON 1UL -#define SQL_AUTOCOMMIT_DEFAULT SQL_AUTOCOMMIT_ON - -/* SQL_LOGIN_TIMEOUT options */ -#define SQL_LOGIN_TIMEOUT_DEFAULT 15UL - -/* SQL_OPT_TRACE options */ -#define SQL_OPT_TRACE_OFF 0UL -#define SQL_OPT_TRACE_ON 1UL -#define SQL_OPT_TRACE_DEFAULT SQL_OPT_TRACE_OFF -#define SQL_OPT_TRACE_FILE_DEFAULT "odbc.log" - -/* SQL_ODBC_CURSORS options */ -#define SQL_CUR_USE_IF_NEEDED 0UL -#define SQL_CUR_USE_ODBC 1UL -#define SQL_CUR_USE_DRIVER 2UL -#define SQL_CUR_DEFAULT SQL_CUR_USE_DRIVER - -/* Column types and scopes in SQLSpecialColumns. */ -#define SQL_BEST_ROWID 1 -#define SQL_ROWVER 2 - -#define SQL_SCOPE_CURROW 0 -#define SQL_SCOPE_TRANSACTION 1 -#define SQL_SCOPE_SESSION 2 - - -/* SQLExtendedFetch flag values */ -#define SQL_FETCH_NEXT 1 -#define SQL_FETCH_FIRST 2 -#define SQL_FETCH_LAST 3 -#define SQL_FETCH_PRIOR 4 -#define SQL_FETCH_ABSOLUTE 5 -#define SQL_FETCH_RELATIVE 6 -#define SQL_FETCH_BOOKMARK 8 - -/* Defines for SQLBindParameter/SQLProcedureColumns */ -#define SQL_PARAM_TYPE_UNKNOWN 0 -#define SQL_PARAM_INPUT 1 -#define SQL_PARAM_INPUT_OUTPUT 2 -#define SQL_RESULT_COL 3 -#define SQL_PARAM_OUTPUT 4 -#define SQL_RETURN_VALUE 5 - -/* Defines used by Driver Manager for mapping SQLSetParam to SQLBindParameter */ -#define SQL_PARAM_TYPE_DEFAULT SQL_PARAM_INPUT_OUTPUT -#define SQL_SETPARAM_VALUE_MAX (-1L) - -/* SQLStatistics flag values */ -#define SQL_INDEX_UNIQUE 0 -#define SQL_INDEX_ALL 1 - -#define SQL_QUICK 0 -#define SQL_ENSURE 1 - -/* SQLSetScrollOption flag values */ -#define SQL_SCROLL_FORWARD_ONLY 0L -#define SQL_SCROLL_KEYSET_DRIVEN (-1L) -#define SQL_SCROLL_DYNAMIC (-2L) -#define SQL_SCROLL_STATIC (-3L) - -/* Everything below has been added to the original isqlext.h that comes - * with iodbc. -*/ - -#define SCHAR signed char -#define FLOAT float -#define DOUBLE double - -/* SQL DATA TYPES */ -typedef UCHAR SQLCHAR; -typedef SWORD SQLSMALLINT; -typedef UWORD SQLUSMALLINT; -typedef SDWORD SQLINTEGER; -typedef UDWORD SQLUINTEGER; -typedef FLOAT SQLREAL; -typedef DOUBLE SQLDOUBLE; -typedef DOUBLE SQLFLOAT; -typedef SCHAR SQLSCHAR; -typedef UDWORD BOOKMARK; - -#ifdef GCC /* Because I know GCC supports 64 bit ints */ - -typedef long long int ODBCINT64; -typedef unsigned ODBCINT64 SQLUBIGINT; -typedef ODBCINT64 SQLBIGINT; - -#else /* Used even on platforms with 64 bit ints - * but not GCC */ - -typedef struct -{ - SQLUINTEGER dwLowWord; - SQLUINTEGER dwHighWord; -} SQLUBIGINT; - -typedef struct -{ - SQLUINTEGER dwLowWord; - SQLINTEGER dwHighWord; -} SQLBIGINT; -#endif /* GCC */ - -typedef struct tagDATE_STRUCT -{ - SQLSMALLINT year; - SQLUSMALLINT month; - SQLUSMALLINT day; -} DATE_STRUCT, - -SQL_DATE_STRUCT; - -typedef struct tagTIME_STRUCT -{ - SQLUSMALLINT hour; - SQLUSMALLINT minute; - SQLUSMALLINT second; -} TIME_STRUCT, - -SQL_TIME_STRUCT; - -typedef struct tagTIMESTAMP_STRUCT -{ - SQLSMALLINT year; - SQLUSMALLINT month; - SQLUSMALLINT day; - SQLUSMALLINT hour; - SQLUSMALLINT minute; - SQLUSMALLINT second; - SQLUINTEGER fraction; -} TIMESTAMP_STRUCT, - -SQL_TIMESTAMP_STRUCT; - -/* postodbc doesn't use these but what the heck */ -/* Don't know what SQL_MAX_NUMERIC_LEN should be so I can't include this. It's - * ODBC 3.0 anyway. - -typedef struct tagSQL_NUMERIC_STRUCT { - SQLCHAR precision; - SQLSCHAR scale; - SQLCHAR sign; - SQLCHAR val[SQL_MAX_NUMERIC_LEN]; -} SQL_NUMERIC_STRUCT; - -*/ - -typedef struct tagSQLGUID -{ - DWORD Data1; - WORD Data2; - WORD Data3; - BYTE Data4[8]; -} SQLGUID; - -typedef enum -{ - SQL_IS_YEAR = 1, - SQL_IS_MONTH = 2, - SQL_IS_DAY = 3, - SQL_IS_HOUR = 4, - SQL_IS_MINUTE = 5, - SQL_IS_SECOND = 6, - SQL_IS_YEAR_TO_MONTH = 7, - SQL_IS_DAY_TO_HOUR = 8, - SQL_IS_DAY_TO_MINUTE = 9, - SQL_IS_DAY_TO_SECOND = 10, - SQL_IS_HOUR_TO_MINUTE = 11, - SQL_IS_HOUR_TO_SECOND = 12, - SQL_IS_MINUTE_TO_SECOND = 13 -} SQLINTERVAL; - -typedef struct tagSQL_YEAR_MONTH -{ - SQLUINTEGER year; - SQLUINTEGER month; -} SQL_YEAR_MONTH_STRUCT; - -typedef struct tagSQL_DAY_SECOND -{ - SQLUINTEGER day; - SQLUINTEGER hour; - SQLUINTEGER minute; - SQLUINTEGER second; - SQLUINTEGER fraction; -} SQL_DAY_SECOND_STRUCT; - -typedef struct tagSQL_INTERVAL_STRUCT -{ - SQLINTERVAL interval_type; - SQLSMALLINT interval_sign; - union - { - SQL_YEAR_MONTH_STRUCT year_month; - SQL_DAY_SECOND_STRUCT day_second; - } intval; -} SQL_INTERVAL_STRUCT; - -#define SQL_MAX_OPTION_STRING_LENGTH 256 -#define SQL_NUM_EXTENSIONS (SQL_EXT_API_LAST - SQL_EXT_API_START + 1) - -/* defines for SQL datatypes */ -/* -#define SQL_TYPE_DATE -#define SQL_TYPE_TIME -#define SQL_TYPE_TIMESTAMP -#define SQL_CODE_DATE -#define SQL_CODE_TIME -#define SQL_CODE_TIMESTAMP -#define SQL_CODE_MONTH -#define SQL_CODE_YEAR -#define SQL_CODE_YEAR_TO_MONTH -#define SQL_CODE_DAY -#define SQL_CODE_HOUR -#define SQL_CODE_MINUTE -#define SQL_CODE_SECOND -#define SQL_CODE_DAY_TO_HOUR -#define SQL_CODE_DAY_TO_MINUTE -#define SQL_CODE_DAY_TO_SECOND -#define SQL_CODE_HOUR_TO_MINUTE -#define SQL_CODE_HOUR_TO_SECOND -#define SQL_CODE_MINUTE_TO_SECOND -*/ -#define SQL_INTERVAL_YEAR (-80) -#define SQL_INTERVAL_MONTH (-81) -#define SQL_INTERVAL_YEAR_TO_MONTH (-82) -#define SQL_INTERVAL_DAY (-83) -#define SQL_INTERVAL_HOUR (-84) -#define SQL_INTERVAL_MINUTE (-85) -#define SQL_INTERVAL_SECOND (-86) -#define SQL_INTERVAL_DAY_TO_HOUR (-87) -#define SQL_INTERVAL_DAY_TO_MINUTE (-88) -#define SQL_INTERVAL_DAY_TO_SECOND (-89) -#define SQL_INTERVAL_HOUR_TO_MINUTE (-90) -#define SQL_INTERVAL_HOUR_TO_SECOND (-91) -#define SQL_INTERVAL_MINUTE_TO_SECOND (-92) - -#define SQL_UNICODE (-95) -#define SQL_UNICODE_VARCHAR (-96) -#define SQL_UNICODE_LONGVARCHAR (-97) -#define SQL_UNICODE_CHAR SQL_UNICODE - -/* C to SQL data types */ -/* -#define SQL_C_TYPE_DATE SQL_TYPE_DATE -#define SQL_C_TYPE_TIME SQL_TYPE_TIME -#define SQL_C_TYPE_TIMESTAMP SQL_TYPE_TIMESTAMP -#define SQL_C_GUID SQLGUID -*/ -#define SQL_C_INTERVAL_MONTH SQL_INTERVAL_MONTH -#define SQL_C_INTERVAL_YEAR SQL_INTERVAL_YEAR -#define SQL_C_INTERVAL_YEAR_TO_MONTH SQL_INTERVAL_YEAR_TO_MONTH -#define SQL_C_INTERVAL_DAY SQL_INTERVAL_DAY -#define SQL_C_INTERVAL_HOUR SQL_INTERVAL_HOUR -#define SQL_C_INTERVAL_MINUTE SQL_INTERVAL_MINUTE -#define SQL_C_INTERVAL_SECOND SQL_INTERVAL_SECOND -#define SQL_C_INTERVAL_DAY_TO_HOUR SQL_INTERVAL_DAY_TO_HOUR -#define SQL_C_INTERVAL_DAY_TO_MINUTE SQL_INTERVAL_DAY_TO_MINUTE -#define SQL_C_INTERVAL_DAY_TO_SECOND SQL_INTERVAL_DAY_TO_SECOND -#define SQL_C_INTERVAL_HOUR_TO_MINUTE SQL_INTERVAL_HOUR_TO_MINUTE -#define SQL_C_INTERVAL_HOUR_TO_SECOND SQL_INTERVAL_HOUR_TO_SECOND -#define SQL_C_INTERVAL_MINUTE_TO_SECOND SQL_INTERVAL_MINUTE_TO_SECOND -#define SQL_C_NUMERIC SQL_NUMERIC -#define SQL_C_VARBOOKMARK SQL_C_BINARY -#define SQL_C_SBIGINT (SQL_BIGINT + SQL_SIGNED_OFFSET) -#define SQL_C_UBIGINT (SQL_BIGINT + SQL_UNSIGNED_OFFSET) - -#define SQL_TRUE 1UL -#define SQL_FALSE 0UL - -/* SQLGetData */ -#define SQL_NO_TOTAL (-4) - -/* SQLBindParameter */ -#define SQL_LEN_DATA_AT_EXEC_OFFSET (-100) -#define SQL_LEN_DATA_AT_EXEC(length) (-length+SQL_LEN_DATA_AT_EXEC_OFFSET) - -#define SQL_LEN_BINARY_ATTR_OFFSET (-100) -#define SQL_LEN_BINARY_ATTR(length) (-(length)+SQL_LEN_BINARY_ATTR_OFFSET) - -/* SQLExtendedFetch - row status */ -#define SQL_ROW_SUCCESS 0 -#define SQL_ROW_DELETED 1 -#define SQL_ROW_UPDATED 2 -#define SQL_ROW_NOROW 3 -#define SQL_ROW_ADDED 4 -#define SQL_ROW_ERROR 5 - -/* SQLForeignKeys - rule flags */ -#define SQL_CASCADE 0 -#define SQL_RESTRICT 1 -#define SQL_SET_NULL 2 -#define SQL_NO_ACTION 3 /* ODBC 3.0 */ -#define SQL_SET_DEFAULT 4 - -/* SQLForeignKeys - Deferrability (ODBC 3.0) */ -#define SQL_INITIALLY_DEFERRED 5 -#define SQL_INITIALLY_IMMEDIATE 6 -#define SQL_NOT_DEFFERABLE 2 - -/* Constants not in isqlext.h but needed by the driver. I have no idea -* if these correspond correctly with those from Microsoft or not. I don't -* know that it matters as long as the symbolic names are used. I simply -* assigned the numbers in the order they appear in the SQLGetInfo function -* of postodbc. -*/ - -/* - * SQLGetInfo - */ -#define SQL_ACTIVE_CONNECTIONS 0 -#define SQL_ACTIVE_STATEMENTS 1 -#define SQL_DATA_SOURCE_NAME 2 -#define SQL_DRIVER_VER 7 -#define SQL_FETCH_DIRECTION 8 -#define SQL_ODBC_API_CONFORMANCE 9 -#define SQL_ROW_UPDATES 11 -#define SQL_ODBC_SAG_CLI_CONFORMANCE 12 -#define SQL_SERVER_NAME 13 -#define SQL_SEARCH_PATTERN_ESCAPE 14 -#define SQL_ODBC_SQL_CONFORMANCE 15 -#define SQL_DBMS_NAME 17 -#define SQL_DBMS_VER 18 -#define SQL_ACCESSIBLE_TABLES 19 -#define SQL_ACCESSIBLE_PROCEDURES 20 -#define SQL_PROCEDURES 21 -#define SQL_CONCAT_NULL_BEHAVIOR 22 -#define SQL_DATA_SOURCE_READ_ONLY 25 -#define SQL_EXPRESSIONS_IN_ORDERBY 27 -#define SQL_IDENTIFIER_CASE 28 -#define SQL_IDENTIFIER_QUOTE_CHAR 29 -#define SQL_MAX_COLUMN_NAME_LEN 30 -#define SQL_MAX_CURSOR_NAME_LEN 31 -#define SQL_MAX_OWNER_NAME_LEN 32 -#define SQL_MAX_PROCEDURE_NAME_LEN 33 -#define SQL_MAX_QUALIFIER_NAME_LEN 34 -#define SQL_MAX_TABLE_NAME_LEN 35 -#define SQL_MULT_RESULT_SETS 36 -#define SQL_MULTIPLE_ACTIVE_TXN 37 -#define SQL_OUTER_JOINS 38 -#define SQL_OWNER_TERM 39 -#define SQL_PROCEDURE_TERM 40 -#define SQL_QUALIFIER_NAME_SEPARATOR 41 -#define SQL_QUALIFIER_TERM 42 -#define SQL_SCROLL_CONCURRENCY 43 -#define SQL_SCROLL_OPTIONS 44 -#define SQL_TABLE_TERM 45 -#define SQL_TXN_CAPABLE 46 -#define SQL_USER_NAME 47 -#define SQL_CONVERT_FUNCTIONS 48 -#define SQL_NUMERIC_FUNCTIONS 49 -#define SQL_STRING_FUNCTIONS 50 -#define SQL_SYSTEM_FUNCTIONS 51 -#define SQL_TIMEDATE_FUNCTIONS 52 -#define SQL_CONVERT_BIGINT 53 -#define SQL_CONVERT_BINARY 54 -#define SQL_CONVERT_BIT 55 -#define SQL_CONVERT_CHAR 56 -#define SQL_CONVERT_DATE 57 -#define SQL_CONVERT_DECIMAL 58 -#define SQL_CONVERT_DOUBLE 59 -#define SQL_CONVERT_FLOAT 60 -#define SQL_CONVERT_INTEGER 61 -#define SQL_CONVERT_LONGVARCHAR 62 -#define SQL_CONVERT_NUMERIC 63 -#define SQL_CONVERT_REAL 64 -#define SQL_CONVERT_SMALLINT 65 -#define SQL_CONVERT_TIME 66 -#define SQL_CONVERT_TIMESTAMP 67 -#define SQL_CONVERT_TINYINT 68 -#define SQL_CONVERT_VARBINARY 69 -#define SQL_CONVERT_VARCHAR 70 -#define SQL_CONVERT_LONGVARBINARY 71 -#define SQL_ODBC_SQL_OPT_IEF 73 -#define SQL_CORRELATION_NAME 74 -#define SQL_LOCK_TYPES 78 -#define SQL_POS_OPERATIONS 79 -#define SQL_POSITIONED_STATEMENTS 80 -#define SQL_GETDATA_EXTENSIONS 81 -#define SQL_BOOKMARK_PERSISTENCE 82 -#define SQL_STATIC_SENSITIVITY 83 -#define SQL_FILE_USAGE 84 -#define SQL_NULL_COLLATION 85 -#define SQL_ALTER_TABLE 86 -#define SQL_COLUMN_ALIAS 87 -#define SQL_GROUP_BY 88 -#define SQL_KEYWORDS 89 -#define SQL_ORDER_BY_COLUMNS_IN_SELECT 90 -#define SQL_OWNER_USAGE 91 -#define SQL_QUALIFIER_USAGE 92 -#define SQL_QUOTED_IDENTIFIER_CASE 93 -#define SQL_SPECIAL_CHARACTERS 94 -#define SQL_SUBQUERIES 95 -#define SQL_UNION 96 -#define SQL_MAX_COLUMNS_IN_GROUP_BY 97 -#define SQL_MAX_COLUMNS_IN_INDEX 98 -#define SQL_MAX_COLUMNS_IN_ORDER_BY 99 -#define SQL_MAX_COLUMNS_IN_SELECT 100 -#define SQL_MAX_COLUMNS_IN_TABLE 101 -#define SQL_MAX_INDEX_SIZE 102 -#define SQL_MAX_ROW_SIZE_INCLUDES_LONG 103 -#define SQL_MAX_ROW_SIZE 104 -#define SQL_MAX_STATEMENT_LEN 105 -#define SQL_MAX_TABLES_IN_SELECT 106 -#define SQL_MAX_USER_NAME_LEN 107 -#define SQL_MAX_CHAR_LITERAL_LEN 108 -#define SQL_TIMEDATE_ADD_INTERVALS 109 -#define SQL_TIMEDATE_DIFF_INTERVALS 110 -#define SQL_NEED_LONG_DATA_LEN 111 -#define SQL_MAX_BINARY_LITERAL_LEN 112 -#define SQL_LIKE_ESCAPE_CLAUSE 113 - -#define SQL_OJ_CAPABILITIES 65003 -/* ODBC 3.0 alias */ -#define SQL_MAX_SCHEMA_NAME_LEN SQL_MAX_OWNER_NAME_LEN - -/* Bit Masks describing the behaviour of the GetInfo functions named above */ -/* - * alter table behaviour(4 byte val) - */ -#define SQL_AT_ADD_COLUMN 0x00000001L -#define SQL_AT_DROP_COLUMN 0x00000002L - -/* - * BookMark Persistence, a SQLUINTEGER bitmask(ie 4 bytes) -*/ -#define SQL_BP_CLOSE 0x00000001L -#define SQL_BP_DELETE 0x00000002L -#define SQL_BP_DROP 0x00000004L -#define SQL_BP_TRANSACTION 0x00000008L -#define SQL_BP_UPDATE 0x00000010L -#define SQL_BP_OTHER_HSTMT 0x00000020L -#define SQL_BP_SCROLL 0x00000040L - -/* - * Conversion bitmasks for testing which conversions are supported by - * the driver. An application compares the returned bitmask with these - * to determine which conversions are supported. The driver ANDS these - * for the returned bitmask to indicate the supported conversions.(type - * is SQLUINTEGER, i.e. 4 bytes). Note that these masks are defined in - * alphabetical order, I have no idea if this maps to MS's SDK. - */ -#define SQL_CVT_CHAR 0x00000001L -#define SQL_CVT_NUMERIC 0x00000002L -#define SQL_CVT_DECIMAL 0x00000004L -#define SQL_CVT_INTEGER 0x00000008L -#define SQL_CVT_SMALLINT 0x00000010L -#define SQL_CVT_FLOAT 0x00000020L -#define SQL_CVT_REAL 0x00000040L -#define SQL_CVT_DOUBLE 0x00000080L -#define SQL_CVT_VARCHAR 0x00000100L -#define SQL_CVT_LONGVARCHAR 0x00000200L -#define SQL_CVT_BINARY 0x00000400L -#define SQL_CVT_VARBINARY 0x00000800L -#define SQL_CVT_BIT 0x00001000L -#define SQL_CVT_TINYINT 0x00002000L -#define SQL_CVT_BIGINT 0x00004000L -#define SQL_CVT_DATE 0x00008000L -#define SQL_CVT_TIME 0x00010000L -#define SQL_CVT_TIMESTAMP 0x00020000L -#define SQL_CVT_LONGVARBINARY 0x00040000L - - -/* extras added in ODBC 3.0 */ -#define SQL_CVT_INTERVAL_YEAR_MONTH 0x00080000L -#define SQL_CVT_INTERVAL_DAY_TIME 0x00100000L - -/* - * concat null behaviour(2 byte val) - */ -#define SQL_CB_NULL 0x0000 -#define SQL_CB_NON_NULL 0x0001 - -/* - * correlation name - */ -#define SQL_CN_NONE 0x0000 -#define SQL_CN_DIFFERENT 0x0001 -#define SQL_CN_ANY 0x0002 - -/* - * Fetch Direction. A SQLINTEGER bitmask enumerating the supported fetch - * direction options. This information type has been deprecated in - * ODBC 3.0. - */ -#define SQL_FD_FETCH_NEXT 0x00000001L -#define SQL_FD_FETCH_FIRST 0x00000002L -#define SQL_FD_FETCH_LAST 0x00000004L -#define SQL_FD_FETCH_PRIOR 0x00000008L -#define SQL_FD_FETCH_ABSOLUTE 0x00000010L -#define SQL_FD_FETCH_RELATIVE 0x00000020L -#define SQL_FD_FETCH_RESUME 0x00000040L -#define SQL_FD_FETCH_BOOKMARK 0x00000080L - -/* - * Conversion bitmasks for testing which function conversions are supported by - * the driver. An application compares the returned bitmask with these - * to determine which conversions are supported. The driver ANDS these - * for the returned bitmask to indicate the supported conversions.(type - * is SQLUINTEGER, i.e. 4 bytes). Note that these masks are defined in - * alphabetical order, I have no idea if this maps to MS's SDK. - */ -#define SQL_FN_CVT_CONVERT 0x00000001L -#define SQL_FN_CVT_CAST 0x00000002L - -/* - * File Usage. A SQLUSMALLINT indicating how a singel-tier driver treats - * files in a data source. - */ -#define SQL_FILE_NOT_SUPPORTED 0x0000 -#define SQL_FILE_TABLE 0x0001 -#define SQL_FILE_QUALIFIER 0x0002 -#define SQL_FILE_CATALOG SQL_FILE_CATALOG - -/* - * GetData Extensions. A SQLUINTEGER(4 bytes) bitmask enumerating extensions - * to SQLGetData. - */ -#define SQL_GD_ANY_COLUMN 0x00000001L -#define SQL_GD_ANY_ORDER 0x00000002L -#define SQL_GD_BLOCK 0x00000004L -#define SQL_GD_BOUND 0x00000008L - -/* - * Group By. A SQLUSMALLINT value specifying the relationship between the - * columns in the GROUP BY clause and the non-aggregated columns in the - * select list. -*/ -#define SQL_GB_NOT_SUPPORTED 0x0000 -#define SQL_GB_GROUP_BY_EQUALS_SELECT 0x0001 -#define SQL_GB_GROUP_BY_CONTAINS_SELECT 0x0002 -#define SQL_GB_NO_RELATION 0x0003 - -/* added in ODBC 3.0 */ -#define SQL_GB_COLLATE 0x0004 - -/* - * Identifier Case. A SQLUSMALLINT indicating how identifiers are handled. - */ -#define SQL_IC_UPPER 0x0001 -#define SQL_IC_LOWER 0x0002 -#define SQL_IC_SENSITIVE 0x0003 -#define SQL_IC_MIXED 0x0004 - -/* - * Lock types. A SQLINTEGER bitmask enumerating the supported lock types for - * the fLock argument in SQLSetPos. Depreciated in 3.0. - */ -#define SQL_LCK_NO_CHANGE 0x00000001L -#define SQL_LCK_EXCLUSIVE 0x00000002L -#define SQL_LCK_UNLOCK 0x00000004L - -/* - * Non Nullable Columns. A SQLUSMALLINT value indicating if the data source - * supports NOT NULL in columns. - */ -#define SQL_NNC_NULL 0x0000 -#define SQL_NNC_NON_NULL 0x0001 - -/* - * Null Collation. A SQLUSMALLINT value specifying where NULLS are sorted in - * a result set. - */ -#define SQL_NC_HIGH 0x0001 -#define SQL_NC_LOW 0x0003 -#define SQL_NC_START 0x0002 -#define SQL_NC_END 0x0004 - -/* - * Numeric Functions. A SQLUINTEGER bitmask enumerating the scalar numeric - * functions supported by the driver and associated data source. - */ -#define SQL_FN_NUM_ABS 0x00000001L -#define SQL_FN_NUM_ACOS 0x00000002L -#define SQL_FN_NUM_ASIN 0x00000004L -#define SQL_FN_NUM_ATAN 0x00000008L -#define SQL_FN_NUM_ATAN2 0x00000010L -#define SQL_FN_NUM_CEILING 0x00000020L -#define SQL_FN_NUM_COS 0x00000040L -#define SQL_FN_NUM_COT 0x00000080L -#define SQL_FN_NUM_EXP 0x00000100L -#define SQL_FN_NUM_FLOOR 0x00000200L -#define SQL_FN_NUM_LOG 0x00000400L -#define SQL_FN_NUM_MOD 0x00000800L -#define SQL_FN_NUM_SIGN 0x00001000L -#define SQL_FN_NUM_SIN 0x00002000L -#define SQL_FN_NUM_SQRT 0x00004000L -#define SQL_FN_NUM_TAN 0x00008000L -#define SQL_FN_NUM_PI 0x00010000L -#define SQL_FN_NUM_RAND 0x00020000L - -/* Added in ODBC 2.0 */ -#define SQL_FN_NUM_DEGREES 0x00040000L -#define SQL_FN_NUM_LOG10 0x00080000L -#define SQL_FN_NUM_POWER 0x00100000L -#define SQL_FN_NUM_RADIANS 0x00200000L -#define SQL_FN_NUM_ROUND 0x00400000L -#define SQL_FN_NUM_TRUNCATE 0x00800000L - -/* - * Outer Join Capabilites. A SQLUINTEGER bitmask enumerating the types of - * outer joins supported by the driver and data source. - */ -#define SQL_OJ_LEFT 0x00000001L -#define SQL_OJ_RIGHT 0x00000002L -#define SQL_OJ_FULL 0x00000004L -#define SQL_OJ_NESTED 0x00000008L -#define SQL_OJ_NOT_ORDERED 0x00000010L -#define SQL_OJ_INNER 0x00000020L -#define SQL_OJ_ALL_COMPARISON_OPS 0x00000040L - -/* - * ODBC API Conformance. A SQLSMALLINT value indicating a drivers ODBC - * level conformance. Depreciated in 3.0. - */ -#define SQL_OAC_NONE 0x0000 -#define SQL_OAC_LEVEL1 0x0001 -#define SQL_OAC_LEVEL2 0x0002 - -/* - * ODBC SAG CLI Conformance. A SQLSMALLINT value indicating a drivers - * SAG CLI conformance. - */ -#define SQL_OSCC_NOT_COMPLIANT 0x0000 -#define SQL_OSCC_COMPLIANT 0x0001 - -/* - * ODBC SQL Conformance. A SQLSMALLINT value indicating a drivers SQL - * grammar support. Depreciated in 3.0. - */ -#define SQL_OSC_MINIMUM 0x0000 -#define SQL_OSC_CORE 0x0001 -#define SQL_OSC_EXTENDED 0x0002 - -/* - * Owner Usage. A SQLUINTEGER bitmask. - */ -#define SQL_OU_DML_STATEMENTS 0x00000001L -#define SQL_OU_PROCEDURE_INVOCATION 0x00000002L -#define SQL_OU_TABLE_DEFINITION 0x00000004L -#define SQL_OU_INDEX_DEFINITION 0x00000008L -#define SQL_OU_PRIVILEGE_DEFINITION 0x00000010L - -/* - * Schema Usage. A SQLUINTEGER bitmask enumerating the statements in which - * schemas can be used. Renamed in ODBC 3.0 from SQL_OWNER_USAGE - */ -#define SQL_SU_DML_STATEMENTS SQL_OU_DML_STATEMENTS -#define SQL_SU_PROCEDURE_INVOCATION SQL_OU_PROCEDURE_INVOCATION -#define SQL_SU_TABLE_DEFINITION SQL_OU_TABLE_DEFINITION -#define SQL_SU_INDEX_DEFINITION SQL_OU_INDEX_DEFINITION -#define SQL_SU_PRIVILEGE_DEFINITION SQL_OU_PRIVILEGE_DEFINITION - -/* - * Pos. Operations. A SQLINTEGER bitmask enumerating the supported operations - * in SQLSetPos. Depreciated in ODBC 3.0. - */ -#define SQL_POS_POSITION 0x00000001L -#define SQL_POS_REFRESH 0x00000002L -#define SQL_POS_UPDATE 0x00000004L -#define SQL_POS_DELETE 0x00000008L -#define SQL_POS_ADD 0x00000010L - -/* - * SQLSetPos - */ -#define SQL_ENTIRE_ROWSET 0 - -#define SQL_POSITION 0 -#define SQL_REFRESH 1 -#define SQL_UPDATE 2 -#define SQL_DELETE 3 -#define SQL_ADD 4 - -/* - * SQLSetPos Lock options -*/ -#define SQL_LOCK_NO_CHANGE 0 -#define SQL_LOCK_EXCLUSIVE 1 -#define SQL_LOCK_UNLOCK 2 - -#define SQL_POSITION_TO(hstmt,irow) \ - SQLSetPos(hstmt,irow,SQL_POSITION,SQL_LOCK_NO_CHANGE) -#define SQL_LOCK_RECORD(hstmt,irow,fLock) \ - SQLSetPos(hstmt,irow,SQL_POSITION,fLock) -#define SQL_REFRESH_RECORD(hstmt,irow,fLock) \ - SQLSetPos(hstmt,irow,SQL_REFRESH,fLock) -#define SQL_UPDATE_RECORD(hstmt,irow) \ - SQLSetPos(hstmt,irow,SQL_UPDATE,SQL_LOCK_NO_CHANGE) -#define SQL_DELETE_RECORD(hstmt,irow) \ - SQLSetPos(hstmt,irow,SQL_DELETE,SQL_LOCK_NO_CHANGE) -#define SQL_ADD_RECORD(hstmt,irow) \ - SQLSetPos(hstmt,irow,SQL_ADD,SQL_LOCK_NO_CHANGE) - -/* - * Positioned Statements. A SQLINTEGER bitmask enumerating the supported - * positioned SQL statements. - */ -#define SQL_PS_POSITIONED_DELETE 0x00000001L -#define SQL_PS_POSITIONED_UPDATE 0x00000002L -#define SQL_PS_SELECT_FOR_UPDATE 0x00000004L - -/* Qualifier Location. A SQLUSMALLINT value indicating the position of the - * catalog in a qualified table name. - */ -#define SQL_QL_START 0x0001 -#define SQL_QL_END 0x0002 - -/* - * Qualifier Usage. A SQLUINTEGER bitmask. - */ -#define SQL_QU_DML_STATEMENTS 0x00000001L -#define SQL_QU_PROCEDURE_INVOCATION 0x00000002L -#define SQL_QU_TABLE_DEFINITION 0x00000004L -#define SQL_QU_INDEX_DEFINITION 0x00000008L -#define SQL_QU_PRIVILEGE_DEFINITION 0x00000010L - -/* The above is renamed in ODBC 3.0 to Catalog Usage. */ -#define SQL_CU_DML_STATEMENTS SQL_QU_DML_STATEMENTS -#define SQL_CU_PROCEDURE_INVOCATION SQL_QU_PROCEDURE_INVOCATION -#define SQL_CU_TABLE_DEFINITION SQL_QU_TABLE_DEFINITION -#define SQL_CU_INDEX_DEFINITION SQL_QU_INDEX_DEFINITION -#define SQL_CU_PRIVILEGE_DEFINITION SQL_QU_PRIVILEGE_DEFINITION - -/* ODBC 3.0 renamed the above to Catalog Location. */ -#define SQL_CL_START SQL_QL_START -#define SQL_CL_END SQL_QL_END - -/* - * Scroll Concurrency. A SQLINTEGER bitmask enumerating the concurrency - * control options supported for the cursor. Depreciated in ODBC 3.0. - */ -#define SQL_SCCO_READ_ONLY 0x00000001L -#define SQL_SCCO_LOCK 0x00000002L -#define SQL_SCCO_OPT_ROWVER 0x00000004L -#define SQL_SCCO_OPT_VALUES 0x00000008L - - -/* - * Scroll Options. A SQLUINTEGER bitmask enumerating the scroll options - * supported for scrollable cursors. - */ -#define SQL_SO_FORWARD_ONLY 0x00000001L -#define SQL_SO_KEYSET_DRIVEN 0x00000002L -#define SQL_SO_DYNAMIC 0x00000004L -#define SQL_SO_MIXED 0x00000008L -#define SQL_SO_STATIC 0x00000010L - -/* - * Static Sensitity. A SQLINTEGER bitmask enumerating whether changes made - * by an application to a static or keyset-driven cursor through SQLSetPos - * or positioned update or delete statements can be detected by that - * application. - */ -#define SQL_SS_ADDITIONS 0x00000001L -#define SQL_SS_DELETIONS 0x00000002L -#define SQL_SS_UPDATES 0x00000004L - -/* - * String Functions. A SQLUINTEGER bitmask enumerating the scalar string - * functions supported by the driver and associated data source. - */ -#define SQL_FN_STR_CONCAT 0x00000001L -#define SQL_FN_STR_INSERT 0x00000002L -#define SQL_FN_STR_LEFT 0x00000004L -#define SQL_FN_STR_LTRIM 0x00000008L -#define SQL_FN_STR_LENGTH 0x00000010L -#define SQL_FN_STR_LOCATE 0x00000020L -#define SQL_FN_STR_LCASE 0x00000040L -#define SQL_FN_STR_REPEAT 0x00000080L -#define SQL_FN_STR_REPLACE 0x00000100L -#define SQL_FN_STR_RIGHT 0x00000200L -#define SQL_FN_STR_RTRIM 0x00000400L -#define SQL_FN_STR_SUBSTRING 0x00000800L -#define SQL_FN_STR_UCASE 0x00001000L -#define SQL_FN_STR_ASCII 0x00002000L -#define SQL_FN_STR_CHAR 0x00004000L -#define SQL_FN_STR_DIFFERENCE 0x00008000L -#define SQL_FN_STR_LOCATE_2 0x00010000L -#define SQL_FN_STR_SOUNDEX 0x00020000L -#define SQL_FN_STR_SPACE 0x00040000L - -/* introduced in ODBC 3.0 */ -#define SQL_FN_STR_BIT_LENGTH 0x00080000L -#define SQL_FN_STR_CHAR_LENGTH 0x00100000L -#define SQL_FN_STR_CHARACTER_LENGTH 0x00200000L -#define SQL_FN_STR_OCTET_LENGTH 0x00400000L -#define SQL_FN_STR_POSITION 0x00800000L - -/* - * Subqueries. A SQLUINTEGER bitmask enumerating the predicates that support - * subqueries. - */ -#define SQL_SQ_COMPARISON 0x00000001L -#define SQL_SQ_EXISTS 0x00000002L -#define SQL_SQ_IN 0x00000004L -#define SQL_SQ_QUANTIFIED 0x00000008L -#define SQL_SQ_CORRELATED_SUBQUERIES 0x00000010L - -/* - * System Functions. A SQLUINTEGER bitmask enumerating the scalar system - * functions supported by the driver and associated data source. - */ -#define SQL_FN_SYS_USERNAME 0x00000001L -#define SQL_FN_SYS_DBNAME 0x00000002L -#define SQL_FN_SYS_IFNULL 0x00000004L - -/* - * Time-Date add and diff intervals. A SQLUINTEGER bitmask enumerating the - * timestamp intervals supported by the driver and associated data source - * for the TIMESTAMPADD and TIMESTAMPDIFF scalar function. - */ -#define SQL_FN_TSI_FRAC_SECOND 0x00000001L -#define SQL_FN_TSI_SECOND 0x00000002L -#define SQL_FN_TSI_MINUTE 0x00000004L -#define SQL_FN_TSI_HOUR 0x00000008L -#define SQL_FN_TSI_DAY 0x00000010L -#define SQL_FN_TSI_WEEK 0x00000020L -#define SQL_FN_TSI_MONTH 0x00000040L -#define SQL_FN_TSI_QUARTER 0x00000080L -#define SQL_FN_TSI_YEAR 0x00000100L - -/* - * Time/Date functions. A SQLUINTEGER bitmask enumerating the scalar date - * and time functions supported by the driver and associated data source. - */ -#define SQL_FN_TD_NOW 0x00000001L -#define SQL_FN_TD_CURDATE 0x00000002L -#define SQL_FN_TD_DAYOFMONTH 0x00000004L -#define SQL_FN_TD_DAYOFWEEK 0x00000008L -#define SQL_FN_TD_DAYOFYEAR 0x00000010L -#define SQL_FN_TD_MONTH 0x00000020L -#define SQL_FN_TD_QUARTER 0x00000040L -#define SQL_FN_TD_WEEK 0x00000080L -#define SQL_FN_TD_YEAR 0x00000100L -#define SQL_FN_TD_CURTIME 0x00000200L -#define SQL_FN_TD_HOUR 0x00000400L -#define SQL_FN_TD_MINUTE 0x00000800L -#define SQL_FN_TD_SECOND 0x00001000L -#define SQL_FN_TD_TIMESTAMPADD 0x00002000L -#define SQL_FN_TD_TIMESTAMPDIFF 0x00004000L -#define SQL_FN_TD_DAYNAME 0x00008000L -#define SQL_FN_TD_MONTHNAME 0x00010000L - -/* Added in ODBC 3.0 */ -#define SQL_FN_TD_CURRENT_DATE 0x00020000L -#define SQL_FN_TD_CURRENT_TIME 0x00040000L -#define SQL_FN_TD_CURRENT_TIMESTAMP 0x00080000L -#define SQL_FN_TD_EXTRACT 0x00100000L - -/* - * Transaction Capable. A SQLUSMALLINT value describing the transaction - * support in the driver or data source. - */ -#define SQL_TC_NONE 0x0000 -#define SQL_TC_DML 0x0001 -#define SQL_TC_ALL 0x0002 -#define SQL_TC_DDL_COMMIT 0x0003 -#define SQL_TC_DDL_IGNORE 0x0004 - -/* - * Unions. A SQLUINTEGER bitmask enumerating the support for the UNION - * clause. - */ -#define SQL_U_UNION 0x00000001L -#define SQL_U_UNION_ALL 0x00000002L - - -/* SQLStatistics: Type, Smallint */ -#define SQL_TABLE_STAT 0 -#define SQL_INDEX_CLUSTERED 1 -#define SQL_INDEX_HASHED 2 -#define SQL_INDEX_OTHER 3 - -/* SQLProcedures: Type: Smallint */ -#define SQL_PT_UNKNOWN 0 -#define SQL_PT_PROCEDURE 1 -#define SQL_PT_FUNCTION 2 - -/* SQLSpecialColumns: PSEUDO_COLUMN: Smallint */ -#define SQL_PC_UNKNOWN 0 -#define SQL_PC_PSEUDO 1 -#define SQL_PC_NOT_PSEUDO 2 - -/* SQLSet/Get/StmtOptions: ASYNC_ENABLE. A SQLUINTEGER */ -#define SQL_ASYNC_ENABLE_OFF 0UL -#define SQL_ASYNC_ENABLE_ON 1UL -#define SQL_ASYNC_ENABLE_DEFAULT SQL_ASYNC_ENABLE_OFF - -/* - * SQLSet/GetStmtOptions: CONCURRENCY. A SQLUINTEGER. Note most of these - * are above in the original isqlext.h code. - */ -#define SQL_CONCUR_DEFAULT SQL_CONCUR_READ_ONLY - -/* - * SQLSet/GetStmtOptions: CURSOR_SCROLLABLE. A SQLUINTEGER. Added in ODBC - * 3.0. - */ -#define SQL_NONSCROLLABLE 0UL -#define SQL_SCROLLABLE 1UL -#define SQL_CURSOR_SCROLLABLE_DEFAULT SQL_NONSCROLLABLE - -/* - * SQLSet/GetStmtOptions: CURSOR_SENSITITY. A SQLUINTEGER. Added in ODBC - * 3.0. - */ -#define SQL_UNSPECIFIED 0UL -#define SQL_INSENSITIVE 1UL -#define SQL_SENSITIVIE 2UL -#define SQL_CURSOR_SENSITIVITY_DEFAULT SQL_UNSPECIFIED - -/* - * SQLSet/GetStmtOptions: CURSOR_TYPE: A SQLUINTEGER value that specifies the - * cursor type - */ -#define SQL_CURSOR_FORWARD_ONLY 0UL -#define SQL_CURSOR_KEYSET_DRIVEN 1UL -#define SQL_CURSOR_DYNAMIC 2UL -#define SQL_CURSOR_STATIC 3UL -#define SQL_CURSOR_DEFAULT SQL_CURSOR_FORWARD_ONLY - -/* - * ENABLE_AUTO_IPD: A SQLUINTEGER, either SQL_TRUE or SQL_FALSE. Default - * dependent on connection option SQL_ATTR_AUTO_IPD. Added in ODBC 3.0. - */ - -/* - * METADATA_ID: A SQLUINTEGER, either SQL_TRUE or SQL_FALSE. Added in - * ODBC 3.0. - */ -#define SQL_ATTR_METADATA_ID_DEFAULT SQL_FALSE - -/* - * SQLSet/GetStmtOptions: NOSCAN. A SQLUINTEGER value that indicates whether - * the driver should scan SQL strings for escape sequences. - */ -#define SQL_NOSCAN_OFF 0UL -#define SQL_NOSCAN_ON 1UL -#define SQL_NOSCAN_DEFAULT SQL_NOSCAN_OFF - -/* - * SQLSet/GetStmtOptions: PARAM_OPERATION: SQLUSMALLINT *. Added in ODBC 3.0 - * - */ -#define SQL_PARAM_PROCEED 0 -#define SQL_PARAM_IGNORE 1 - -/* - * SQLSet/GetStmtOptions: PARAM_STATUS: SQLUSMALLINT *. Added in ODBC 3.0 - * -*/ -#define SQL_PARAM_SUCCESS 0 -#define SQL_PARAM_SUCCESS_WITH_INFO 6 -#define SQL_PARAM_ERROR 5 -#define SQL_PARAM_UNUSED 7 -#define SQL_PARAM_DIAG_UNAVAILABLE 1 - -/* - * SQLSet/GetStmtOptions: RETRIEVE_DATA: SQLUINTEGER value. - */ -#define SQL_RD_OFF 0UL -#define SQL_RD_ON 1UL -#define SQL_RD_DEFAULT SQL_RD_ON - -/* - * SQLSet/GetStmtOptions: BIND_TYPE: SQLUINTEGER. sets binding orientation. - */ -#define SQL_BIND_BY_COLUMN 0UL -#define SQL_BIND_TYPE_DEFAULT SQL_BIND_BY_COLUMN - -/* - * SQLSet/GetStmtOptions: ROW_OPERATION: SQLUSMALLINT *. Added in ODBC 3.0 - */ -#define SQL_ROW_PROCEED 0 -#define SQL_ROW_IGNORE 1 - -/* - * SQL_ROWSET_SIZE - */ -#define SQL_ROWSET_SIZE_DEFAULT 1UL - -/* - * SQL_KEYSET_SIZE - */ -#define SQL_KEYSET_SIZE_DEFAULT 0UL - -/* - * SQLSet/GetStmtOptions: SIMULATE_CURSOR: SQLUINTEGER value that specifies - * whether drivers that simulate positioned update and delete statements - * guarantee that such statements affect only a single row. - */ -#define SQL_SC_NON_UNIQUE 0UL -#define SQL_SC_TRY_UNIQUE 1UL -#define SQL_SC_UNIQUE 2UL - -/* - * SQLSet/GetStmtOptions: USE_BOOKMARKS: SQLUINTEGER value that specifies - * whether an application will use bookmarks with a cursor. - */ -#define SQL_UB_OFF 0UL -#define SQL_UB_ON 1UL -#define SQL_UB_FIXED SQL_UB_ON /* Deprecated in ODBC - * 3.0 */ -#define SQL_UB_VARIABLE 2UL /* Added in ODBC 3.0 */ -#define SQL_UB_DEFAULT SQL_UB_OFF - -/* Deprecated */ -#define SQL_DATABASE_NAME 16 -#define SQL_FD_FETCH_PREV SQL_FD_FETCH_PRIOR -#define SQL_FETCH_PREV SQL_FETCH_PRIOR -#define SQL_CONCUR_TIMESTAMP SQL_CONCUR_ROWVER -#define SQL_SCCO_OPT_TIMESTAMP SQL_SCCO_OPT_ROWVER -#define SQL_CC_DELETE SQL_CB_DELETE -#define SQL_CR_DELETE SQL_CB_DELETE -#define SQL_CC_CLOSE SQL_CB_CLOSE -#define SQL_CR_CLOSE SQL_CB_CLOSE -#define SQL_CC_PRESERVE SQL_CB_PRESERVE -#define SQL_CR_PRESERVE SQL_CB_PRESERVE -#define SQL_FETCH_RESUME 7 -#define SQL_SCROLL_FORWARD_ONLY 0L -#define SQL_SCROLL_KEYSET_DRIVEN (-1L) -#define SQL_SCROLL_DYNAMIC (-2L) -#define SQL_SCROLL_STATIC (-3L) - -/* - * ODBC keywords - */ -#define SQL_ODBC_KEYWORDS \ -"ABSOLUTE,ACTION,ADA,ADD,ALL,ALLOCATE,ALTER,AND,ANY,ARE,AS,"\ -"ASC,ASSERTION,AT,AUTHORIZATION,AVG,"\ -"BEGIN,BETWEEN,BIT,BIT_LENGTH,BOTH,BY,CASCADE,CASCADED,CASE,CAST,CATALOG,"\ -"CHAR,CHAR_LENGTH,CHARACTER,CHARACTER_LENGTH,CHECK,CLOSE,COALESCE,"\ -"COBOL,COLLATE,COLLATION,COLUMN,COMMIT,CONNECT,CONNECTION,CONSTRAINT,"\ -"CONSTRAINTS,CONTINUE,CONVERT,CORRESPONDING,COUNT,CREATE,CROSS,CURRENT,"\ -"CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURRENT_USER,CURSOR,"\ -"DATE,DAY,DEALLOCATE,DEC,DECIMAL,DECLARE,DEFAULT,DEFERRABLE,"\ -"DEFERRED,DELETE,DESC,DESCRIBE,DESCRIPTOR,DIAGNOSTICS,DISCONNECT,"\ -"DISTINCT,DOMAIN,DOUBLE,DROP,"\ -"ELSE,END,END-EXEC,ESCAPE,EXCEPT,EXCEPTION,EXEC,EXECUTE,"\ -"EXISTS,EXTERNAL,EXTRACT,"\ -"FALSE,FETCH,FIRST,FLOAT,FOR,FOREIGN,FORTRAN,FOUND,FROM,FULL,"\ -"GET,GLOBAL,GO,GOTO,GRANT,GROUP,HAVING,HOUR,"\ -"IDENTITY,IMMEDIATE,IN,INCLUDE,INDEX,INDICATOR,INITIALLY,INNER,"\ -"INPUT,INSENSITIVE,INSERT,INTEGER,INTERSECT,INTERVAL,INTO,IS,ISOLATION,"\ -"JOIN,KEY,LANGUAGE,LAST,LEADING,LEFT,LEVEL,LIKE,LOCAL,LOWER,"\ -"MATCH,MAX,MIN,MINUTE,MODULE,MONTH,MUMPS,"\ -"NAMES,NATIONAL,NATURAL,NCHAR,NEXT,NO,NONE,NOT,NULL,NULLIF,NUMERIC,"\ -"OCTET_LENGTH,OF,ON,ONLY,OPEN,OPTION,OR,ORDER,OUTER,OUTPUT,OVERLAPS,"\ -"PAD,PARTIAL,PASCAL,PLI,POSITION,PRECISION,PREPARE,PRESERVE,"\ -"PRIMARY,PRIOR,PRIVILEGES,PROCEDURE,PUBLIC,"\ -"REFERENCES,RELATIVE,RESTRICT,REVOKE,RIGHT,ROLLBACK,ROWS,"\ -"SCHEMA,SCROLL,SECOND,SECTION,SELECT,SEQUENCE,SESSION,SESSION_USER,SET,SIZE,"\ -"SMALLINT,SOME,SPACE,SQL,SQLCA,SQLCODE,SQLERROR,SQLSTATE,SQLWARNING,"\ -"SUBSTRING,SUM,SYSTEM_USER,"\ -"TABLE,TEMPORARY,THEN,TIME,TIMESTAMP,TIMEZONE_HOUR,TIMEZONE_MINUTE,"\ -"TO,TRAILING,TRANSACTION,TRANSLATE,TRANSLATION,TRIM,TRUE,"\ -"UNION,UNIQUE,UNKNOWN,UPDATE,UPPER,USAGE,USER,USING,"\ -"VALUE,,VARCHAR,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,YEAR" - -#ifdef __cplusplus -extern "C" -{ -#endif - -RETCODE SQL_API SQLSetConnectOption(HDBC, UWORD, UDWORD); -RETCODE SQL_API SQLNumResultCols(HSTMT, SWORD FAR *); - -/* - * function prototypes previously missing from isqlext.h - */ -RETCODE SQL_API SQLColumns(HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UCHAR FAR * szColumnName, - SWORD cbColumnName); - -RETCODE SQL_API SQLDriverConnect(HDBC hdbc, - HWND hwnd, - UCHAR FAR * szConnStrIn, - SWORD cbConnStrIn, - UCHAR FAR * szConnStrOut, - SWORD cbConnStrOutMax, - SWORD FAR * pcbConnStrOut, - UWORD fDriverCompletion); - -RETCODE SQL_API SQLGetConnectOption(HDBC hdbc, - UWORD fOption, - PTR pvParam); - -RETCODE SQL_API SQLGetData(HSTMT hstmt, - UWORD icol, - SWORD fCType, - PTR rgbValue, - SDWORD cbValueMax, - SDWORD FAR * pcbValue); - -RETCODE SQL_API SQLGetFunctions(HDBC hdbc, - UWORD fFunction, - UWORD FAR * pfExists); - -RETCODE SQL_API SQLGetInfo(HDBC hdbc, - UWORD fInfoType, - PTR rgbInfoValue, - SWORD cbInfoValueMax, - SWORD FAR * pcbInfoValue); - -RETCODE SQL_API SQLGetStmtOption(HSTMT hstmt, - UWORD fOption, - PTR pvParam); - -RETCODE SQL_API SQLGetTypeInfo(HSTMT hstmt, - SWORD fSqlType); - -RETCODE SQL_API SQLParamData(HSTMT hstmt, - PTR FAR * prgbValue); - -RETCODE SQL_API SQLPutData(HSTMT hstmt, - PTR rgbValue, - SDWORD cbValue); - -RETCODE SQL_API SQLSetStmtOption(HSTMT hstmt, - UWORD fOption, - UDWORD vParam); - -RETCODE SQL_API SQLSpecialColumns(HSTMT hstmt, - UWORD fColType, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UWORD fScope, - UWORD fNullable); - -RETCODE SQL_API SQLStatistics(HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UWORD fUnique, - UWORD fAccuracy); - -RETCODE SQL_API SQLTables(HSTMT hstmt, - UCHAR FAR * szTableQualifier, - SWORD cbTableQualifier, - UCHAR FAR * szTableOwner, - SWORD cbTableOwner, - UCHAR FAR * szTableName, - SWORD cbTableName, - UCHAR FAR * szTableType, - SWORD cbTableType); - -RETCODE SQL_API SQLBrowseConnect(HDBC hdbc, - UCHAR FAR * szConnStrIn, - SWORD cbConnStrIn, - UCHAR FAR * szConnStrOut, - SWORD cbConnStrOutMax, - SWORD FAR * pcbConnStrOut); - -RETCODE SQL_API SQLColumnPrivileges(HSTMT hs |