+dnl **************************************************************
+dnl Postodbc v0.0250 Installation Program
+dnl
+dnl Welcome to the new improved Postodbc installation program.
+dnl This configuration program is for version 0.0250 of the
+dnl Postodbc software.
+dnl
+dnl EOT
+
+dnl this part selects the template from the one in the
+dnl template directory.
+
+dnl if test "X$with_template" != "X"
+dnl then
+dnl TEMPLATE=template/$with_template
+dnl else
+dnl TEMPLATE=DO_NOT_CHANGE_THIS_INVALID_FILENAME
+dnl fi
+
+AC_MSG_CHECKING(setting template to)
+AC_ARG_WITH(template,
+ [ --with-template=TEMPLATE
+ use operating system template file
+ see template directory],
+ [ TEMPLATE=$withval ],
+ [ host_no_ver=`echo "$host" | sed 's/[[0-9.]]*$//'`
+ GUESS=`grep "$host_no_ver" $TEMPLATEDIR/.similar | sed 's/.*=//' | tail -1`
+ if test "$GUESS"
+ then TEMPLATE="$GUESS"
+ else TEMPLATE=`uname -s | tr A-Z a-z`
+ fi
+ ])
+AC_MSG_RESULT($TEMPLATE)
+
+if test ! -d "$TEMPLATEDIR"
+then
+ cat << EOT
+**************************************************************
+You seem to be missing the template directory needed by
+configure. If you just copied the source from the Postgres
+distribution you should instead have issued the command
+'make standalone' which would have built a distribution
+containing the necessary template directory. The other
+option is that your trying to build from the source
+which is meant to be placed in the Postgres distribution
+directory 'interfaces/odbc'. Depending on your case either get the
+standalone source from the following Web site:
+
+ www.insightdist.com/psqlodbc/
+
+or issue the 'make standalone' command from the
+'interfaces/odbc' directory of your Postgres Distribution,
+or copy the distribution file you have to your Postgres
+distribution's 'interfaces/odbc' directory and try
+again.
+
+If neither of these is the case than please complain
+kindly to the maintainers, their e-mail addresses can
+be found in the Readme files.
+*************************************************************
+EOT
+
+exit
+else
+
+if test ! -f "$TEMPLATEDIR/$TEMPLATE"
+then
+ cat <
+Please select a template from the ones listed below. If no
+template is available, then select the 'generic' one and
+starts 'checking host system type...'
+**************************************************************
+EOT
+ TEMPLATE=generic
+ GUESS=`grep "^$host_no_ver=" $TEMPLATEDIR/.similar 2>/dev/null`
+ if test ! "$GUESS"
+ then host_no_ver=`echo "$host" | sed 's/[[0-9.]]*$//'`
+ GUESS=`grep "$host_no_ver" $TEMPLATEDIR/.similar 2>/dev/null`
+ fi
+ if test "$GUESS"
+ then
+ TEMPLATE=`echo $GUESS | sed 's/.*=//'`
+ fi
+ export TEMPLATE
+ ls $TEMPLATEDIR
+ echo "**************************************************************"
+ $ECHO_N "Appropriate template file { $TEMPLATE }: $ECHO_C"
+ read a
+ if test "$a." != "."
+ then
+ TEMPLATE=$a
+ fi
+ if test ! -f $TEMPLATEDIR/$TEMPLATE
+ then
+ echo "You must choose an appropriate template file."
+ exit
+ fi
+fi
+fi
+
+TEMPLATE=$TEMPLATEDIR/$TEMPLATE
+export TEMPLATE
+echo ""
+
+AROPT=`grep '^AROPT:' $TEMPLATE | awk -F: '{print $2}'`
+SHARED_LIB=`grep '^SHARED_LIB:' $TEMPLATE | awk -F: '{print $2}'`
+CFLAGS=`grep '^CFLAGS:' $TEMPLATE | awk -F: '{print $2}'`
+SRCH_INC=`grep '^SRCH_INC:' $TEMPLATE | awk -F: '{print $2}'`
+SRCH_LIB=`grep '^SRCH_LIB:' $TEMPLATE | awk -F: '{print $2}'`
+DLSUFFIX=`grep '^DLSUFFIX:' $TEMPLATE | awk -F: '{print $2}'`
+DL_LIB=`grep '^DL_LIB:' $TEMPLATE | awk -F: '{print $2}'`
+CC=`grep '^CC:' $TEMPLATE | awk -F: '{print $2}'`
+LIBS=`grep '^LIBS:' $TEMPLATE | awk -F: '{print $2}'`
+
+
+a=$SRCH_INC
+CPPFLAGS=`echo "$a" | sed 's@ *@ @g; s@^\([[^ ]]\)@-I\1@; s@ \([[^ ]]\)@ -I\1@g'`
+
+export CPPFLAGS
+echo "- setting CPPFLAGS=$CPPFLAGS"
+
+a=$SRCH_LIB
+LDFLAGS=`echo "$a" | sed 's@ *@ @g; s@^\([[^ ]]\)@-L\1@; s@ \([[^ ]]\)@ -L\1@g'`
+
+export LDFLAGS
+echo "- setting LDFLAGS=$LDFLAGS"
+
+dnl Allow for overriding the default location of the odbcinst.ini
+dnl file which is normally ${prefix}/share or ${prefix} if this is
+dnl being compiled inside the postgres distribution.
+AC_MSG_CHECKING(setting ODBCINST)
+AC_ARG_WITH(
+ odbcinst,
+ [ --with-odbcinst= change default directory for odbcinst.ini],
+ AC_DEFINE_UNQUOTED(ODBCINST, ${with_odbcinst}) AC_MSG_RESULT($with_odbcinst),
+ AC_DEFINE_UNQUOTED(ODBCINST, ${ODBCINSTDIR}) AC_MSG_RESULT(${ODBCINSTDIR})
+)
+
+if test "X$with_odbcinst" != "X"
+then
+ ODBCINSTDIR=$with_odbcinst
+fi
+
+AC_SUBST(ODBCINSTDIR)
+
+if test "X$with_compiler" != "X"
+then
+ CC=$with_compiler
+else
+ AC_PROG_CC
+fi
+
+AC_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+AC_PROG_CPP
+
+AC_SUBST(PORTNAME)
+AC_SUBST(LDFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(AROPT)
+AC_SUBST(SHARED_LIB)
+AC_SUBST(CFLAGS)
+AC_SUBST(DLSUFFIX)
+AC_SUBST(DL_LIB)
+
+INSTALLPATH="/usr/ucb:$PATH"
+AC_PATH_PROGS(INSTALL, ginstall installbsd bsdinst scoinst install, NONE, $INSTALLPATH)
+if test $INSTALL = "NONE"
+then
+ echo "- No Install Script found - aborting."
+ exit 0;
+fi
+
+INSTLOPTS="-m 444"
+INSTL_EXE_OPTS="-m 555"
+INSTL_LIB_OPTS="-m 644"
+
+case "`basename $INSTALL`" in
+ install|installbsd|scoinst)
+ INSTLOPTS="-c $INSTLOPTS"
+ INSTL_EXE_OPTS="-c $INSTL_EXE_OPTS"
+ INSTL_LIB_OPTS="-c $INSTL_LIB_OPTS";;
+esac
+
+echo "- Using $INSTALL"
+AC_SUBST(INSTALL)
+AC_SUBST(INSTLOPTS)
+AC_SUBST(INSTL_LIB_OPTS)
+AC_SUBST(INSTL_EXE_OPTS)
+
+dnl Check the option to echo to inhibit newlines.
+ECHO_N_OUT=`echo -n "" | wc -c`
+ECHO_C_OUT=`echo "\c" | wc -c`
+if test "$ECHO_N_OUT" -eq 0; then
+ DASH_N='-n'
+ BACKSLASH_C=
+else
+ if test "ECHO_C_OUT" -eq 0; then
+ DASH_N=
+ BACKSLASH_C='\\\\c'
+ else
+ AC_MSG_ERROR("echo behaviour undetermined")
+ fi
+fi
+AC_SUBST(DASH_N)
+AC_SUBST(BACKSLASH_C)
+
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AC_PATH_PROG(find, find)
+AC_PATH_PROG(tar, tar)
+AC_PATH_PROG(split,split)
+
+AC_CHECK_LIB(c, main)
+AC_CHECK_LIB(m, main)
+AC_CHECK_LIB(dl, main)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sys/param.h pwd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+
+dnl Check for any "odd" conditions
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(stricmp)
+
+dnl Check for X libraries
+
+dnl Check for X library
+
+AC_OUTPUT(GNUmakefile Makefile.global)
#include
#include
-#ifndef UNIX
+#ifdef WIN32
#include
#endif
{
EnvironmentClass *env = (EnvironmentClass *)henv;
ConnectionClass *conn;
-char *func="SQLAllocConnect";
+static char *func="SQLAllocConnect";
+
+ mylog( "%s: entering...\n", func);
conn = CC_Constructor();
- mylog("**** SQLAllocConnect: henv = %u, conn = %u\n", henv, conn);
+ mylog("**** %s: henv = %u, conn = %u\n", func, henv, conn);
if( ! conn) {
env->errormsg = "Couldn't allocate memory for Connection object.";
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
-char *func = "SQLConnect";
+static char *func = "SQLConnect";
+
+ mylog( "%s: entering...\n", func);
if ( ! conn) {
CC_log_error(func, "", NULL);
/* fill in any defaults */
getDSNdefaults(ci);
- qlog("conn = %u, SQLConnect(DSN='%s', UID='%s', PWD='%s')\n", conn, ci->dsn, ci->username, ci->password);
+ qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password);
if ( CC_connect(conn, FALSE) <= 0) {
// Error messages are filled in
return SQL_ERROR;
}
+ mylog( "%s: returning...\n", func);
+
return SQL_SUCCESS;
}
SWORD cbConnStrOutMax,
SWORD FAR *pcbConnStrOut)
{
+static char *func="SQLBrowseConnect";
+
+ mylog( "%s: entering...\n", func);
+
return SQL_SUCCESS;
}
HDBC hdbc)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
-char *func = "SQLDisconnect";
+static char *func = "SQLDisconnect";
- mylog("**** in SQLDisconnect\n");
+
+ mylog( "%s: entering...\n", func);
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
- qlog("conn=%u, SQLDisconnect\n", conn);
+ qlog("conn=%u, %s\n", conn, func);
if (conn->status == CONN_EXECUTING) {
conn->errornumber = CONN_IN_USE;
return SQL_ERROR;
}
- mylog("SQLDisconnect: about to CC_cleanup\n");
+ mylog("%s: about to CC_cleanup\n", func);
/* Close the connection and free statements */
CC_cleanup(conn);
- mylog("SQLDisconnect: done CC_cleanup\n");
- mylog("exit SQLDisconnect\n");
+ mylog("%s: done CC_cleanup\n", func);
+ mylog("%s: returning...\n", func);
return SQL_SUCCESS;
}
HDBC hdbc)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
-char *func = "SQLFreeConnect";
+static char *func = "SQLFreeConnect";
- mylog("**** in SQLFreeConnect: hdbc=%u\n", hdbc);
+ mylog( "%s: entering...\n", func);
+ mylog("**** in %s: hdbc=%u\n", func, hdbc);
if ( ! conn) {
CC_log_error(func, "", NULL);
CC_Destructor(conn);
- mylog("exit SQLFreeConnect\n");
+ mylog("%s: returning...\n", func);
return SQL_SUCCESS;
}
*
*/
-ConnectionClass
-*CC_Constructor()
+ConnectionClass *CC_Constructor()
{
ConnectionClass *rv;
}
/* Check for translation dll */
+#ifdef WIN32
if ( self->translation_handle) {
FreeLibrary (self->translation_handle);
self->translation_handle = NULL;
}
+#endif
mylog("exit CC_Cleanup\n");
return TRUE;
CC_set_translation (ConnectionClass *self)
{
+#ifdef WIN32
+
if (self->translation_handle != NULL) {
FreeLibrary (self->translation_handle);
self->translation_handle = NULL;
self->errormsg = "Could not find translation DLL functions.";
return FALSE;
}
-
+#endif
return TRUE;
}
int beresp;
char msgbuffer[ERROR_MSG_LENGTH];
char salt[2];
+static char *func="CC_connect";
+
+ mylog("%s: entering...\n", func);
if ( do_password)
else {
- qlog("Global Options: fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
+ qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
+ POSTGRESDRIVERVERSION,
globals.fetch_max,
globals.socket_buffersize,
globals.unknown_sizes,
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);
+ 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);
/* If the socket was closed for some reason (like a SQLDisconnect, but no SQLFreeConnect
then create a socket now.
CC_send_settings(self);
CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
-// CC_test(self);
+ // CC_test(self);
CC_clear_error(self); /* clear any initial command errors */
self->status = CONN_CONNECTED;
+ mylog("%s: returning...\n", func);
+
return 1;
}
mylog("send_query: done sending query\n");
while(1) {
- /* what type of message is comming now ? */
+ /* what type of message is coming now ? */
id = SOCK_get_char(sock);
if ((SOCK_get_errcode(sock) != 0) || (id == EOF)) {
QR_set_command(res, cmdbuffer);
/* (Quotation from the original comments)
- since backend may produze more than one result for some commands
+ 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
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);
+ 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)
char
CC_send_settings(ConnectionClass *self)
{
-char ini_query[MAX_MESSAGE_LEN];
+// char ini_query[MAX_MESSAGE_LEN];
ConnInfo *ci = &(self->connInfo);
// QResultClass *res;
HSTMT hstmt;
StatementClass *stmt;
RETCODE result;
-SWORD cols = 0;
+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 = _SQLAllocStmt( self, &hstmt);
+
+ result = SQLAllocStmt( self, &hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
return FALSE;
}
stmt = (StatementClass *) hstmt;
- ini_query[0] = '\0';
+ stmt->internal = TRUE; /* ensure no BEGIN/COMMIT/ABORT stuff */
/* Set the Datestyle to the format the driver expects it to be in */
- sprintf(ini_query, "set DateStyle to 'ISO'");
+ result = SQLExecDirect(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 (globals.disable_optimizer)
- sprintf(&ini_query[strlen(ini_query)], "%sset geqo to 'OFF'",
- ini_query[0] != '\0' ? "; " : "");
+ if (globals.disable_optimizer) {
+ result = SQLExecDirect(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);
+
+ }
/* Global settings */
- if (globals.conn_settings[0] != '\0')
- sprintf(&ini_query[strlen(ini_query)], "%s%s",
- ini_query[0] != '\0' ? "; " : "",
- globals.conn_settings);
+ if (globals.conn_settings[0] != '\0') {
+ cs = strdup(globals.conn_settings);
+ ptr = strtok(cs, ";");
+ while (ptr) {
+ result = SQLExecDirect(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')
- sprintf(&ini_query[strlen(ini_query)], "%s%s",
- ini_query[0] != '\0' ? "; " : "",
- ci->conn_settings);
+ if (ci->conn_settings[0] != '\0') {
+ cs = strdup(ci->conn_settings);
+ ptr = strtok(cs, ";");
+ while (ptr) {
+ result = SQLExecDirect(hstmt, ptr, SQL_NTS);
+ if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+ status = FALSE;
- if (ini_query[0] != '\0') {
- mylog("Sending Initial Connection query: '%s'\n", ini_query);
+ mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
- result = _SQLExecDirect(hstmt, ini_query, SQL_NTS);
- if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- _SQLFreeStmt(hstmt, SQL_DROP);
- return FALSE;
+ ptr = strtok(NULL, ";");
}
- _SQLFreeStmt(hstmt, SQL_DROP);
-
+ free(cs);
}
- return TRUE;
+
+
+ SQLFreeStmt(hstmt, SQL_DROP);
+
+ return status;
}
/* This function is just a hack to get the oid of our Large Object oid type.
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 = _SQLAllocStmt( self, &hstmt);
+ result = SQLAllocStmt( self, &hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
return;
}
stmt = (StatementClass *) hstmt;
- result = _SQLExecDirect(hstmt, "select oid from pg_type where typname='" \
- PG_TYPE_LO_NAME \
- "'", SQL_NTS);
+ result = SQLExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- _SQLFreeStmt(hstmt, SQL_DROP);
+ SQLFreeStmt(hstmt, SQL_DROP);
return;
}
- result = _SQLFetch(hstmt);
+ result = SQLFetch(hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- _SQLFreeStmt(hstmt, SQL_DROP);
+ SQLFreeStmt(hstmt, SQL_DROP);
return;
}
- result = _SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
+ result = SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
- _SQLFreeStmt(hstmt, SQL_DROP);
+ SQLFreeStmt(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 = _SQLFreeStmt(hstmt, SQL_DROP);
+ result = SQLFreeStmt(hstmt, SQL_DROP);
}
void
{
if (self) {
qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
+ mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, 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);
void
CC_test(ConnectionClass *self)
{
+static char *func = "CC_test";
HSTMT hstmt1;
RETCODE result;
-SDWORD pcbValue;
-UDWORD pcrow;
-UWORD rgfRowStatus;
-char name[255], type[255];
-SDWORD namelen, typelen;
-SWORD cols;
+char pktab[255], fktab[255], pkcol[255], fkcol[255], tgname[255];
+SDWORD pktab_len, pkcol_len, fktab_len, fkcol_len, ur_len, dr_len, tgname_len;
+SWORD cols, seq;
+SDWORD update_rule, delete_rule;
+
+ mylog( "%s: entering...\n", func);
result = SQLAllocStmt( self, &hstmt1);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
return;
}
- result = SQLTables(hstmt1, "", SQL_NTS, "", SQL_NTS, "", SQL_NTS, "", SQL_NTS);
- qlog("SQLTables result = %d\n", result);
+ result = SQLPrimaryKeys(hstmt1, NULL, 0, NULL, 0, "t1", SQL_NTS);
+
+ qlog("SQLPrimaryKeys result = %d\n", result);
result = SQLNumResultCols(hstmt1, &cols);
qlog("cols SQLTables result = %d\n", result);
- result = SQLBindCol(hstmt1, 3, SQL_C_CHAR, name, sizeof(name), &namelen);
+ result = SQLBindCol(hstmt1, 3, SQL_C_CHAR, pktab, sizeof(pktab), &pktab_len);
qlog("bind result = %d\n", result);
- result = SQLBindCol(hstmt1, 4, SQL_C_CHAR, type, sizeof(type), &typelen);
+ result = SQLBindCol(hstmt1, 4, SQL_C_CHAR, pkcol, sizeof(pkcol), &pkcol_len);
qlog("bind result = %d\n", result);
-
+
+ result = SQLBindCol(hstmt1, 5, SQL_C_SHORT, &seq, 0, NULL);
+ qlog("bind result = %d\n", result);
+
+ result = SQLFetch(hstmt1);
+ qlog("SQLFetch result = %d\n", result);
+ while (result != SQL_NO_DATA_FOUND) {
+ qlog("fetch on stmt1: result = %d, pktab='%s', pkcol='%s', seq=%d\n",
+ result, pktab, pkcol, seq);
+
+ result = SQLFetch(hstmt1);
+ }
+ qlog("SQLFetch result = %d\n", result);
+
+ // Test of case #1
+ result = SQLForeignKeys(hstmt1, "", SQL_NTS, "", SQL_NTS, "t1", SQL_NTS,
+ NULL, 0, NULL, 0, NULL, 0);
+
+ // Test of case #2
+ result = SQLForeignKeys(hstmt1, "", SQL_NTS, "", SQL_NTS, NULL, 0,
+ NULL, 0, NULL, 0, "ar_register", SQL_NTS);
+
+
+ // Test of case #3
+ result = SQLForeignKeys(hstmt1, NULL, 0, NULL, 0, "employee", SQL_NTS,
+ NULL, 0, NULL, 0, "invoice", SQL_NTS);
+
+ qlog("SQLForeignKeys result = %d\n", result);
+
+ result = SQLNumResultCols(hstmt1, &cols);
+ qlog("cols SQLTables result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 3, SQL_C_CHAR, pktab, sizeof(pktab), &pktab_len);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 4, SQL_C_CHAR, pkcol, sizeof(pkcol), &pkcol_len);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 7, SQL_C_CHAR, fktab, sizeof(fktab), &fktab_len);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 8, SQL_C_CHAR, fkcol, sizeof(fkcol), &fkcol_len);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 9, SQL_C_SHORT, &seq, 0, NULL);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 10, SQL_C_LONG, &update_rule, 0, &ur_len);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 11, SQL_C_LONG, &delete_rule, 0, &dr_len);
+ qlog("bind result = %d\n", result);
+
+ result = SQLBindCol(hstmt1, 14, SQL_C_CHAR, tgname, sizeof(tgname), &tgname_len);
+ qlog("bind result = %d\n", result);
+
result = SQLFetch(hstmt1);
qlog("SQLFetch result = %d\n", result);
while (result != SQL_NO_DATA_FOUND) {
- qlog("fetch on stmt1: result=%d, namelen=%d: name='%s', typelen=%d, type='%s'\n", result, namelen, name, typelen, type);
+ qlog("fetch on stmt1: result = %d, pktab='%s', pkcol='%s', fktab='%s', fkcol='%s', seq=%d, update_rule=%d, ur_len=%d, delete_rule=%d, dr_len=%d, tgname='%s', tgname_len=%d\n",
+ result, pktab, pkcol, fktab, fkcol, seq, update_rule, ur_len, delete_rule, dr_len, tgname, tgname_len);
result = SQLFetch(hstmt1);
}
qlog("SQLFetch result = %d\n", result);
+
SQLFreeStmt(hstmt1, SQL_DROP);
}
*/
+
#define __CONNECTION_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
};
/* 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,
/* prototypes */
-ConnectionClass *CC_Constructor();
+ConnectionClass *CC_Constructor(void);
char CC_Destructor(ConnectionClass *self);
int CC_cursor_count(ConnectionClass *self);
char CC_cleanup(ConnectionClass *self);
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include
#include
+#include
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
#include "lobj.h"
#include "connection.h"
-#ifdef UNIX
-#if !HAVE_STRICMP
+#ifndef WIN32
+#ifndef HAVE_STRICMP
#define stricmp(s1,s2) strcasecmp(s1,s2)
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#endif
{ 0, 0 }
};
+char *mapFunction(char *func);
+unsigned int conv_from_octal(unsigned char *s);
+unsigned int conv_from_hex(unsigned char *s);
+char *conv_to_octal(unsigned char val);
/******** A Guide for date/time/timestamp conversions **************
return COPY_OK;
}
+
if (stmt->hdbc->DataSourceToDriver != NULL) {
int length = strlen (value);
stmt->hdbc->DataSourceToDriver (stmt->hdbc->translation_option,
NULL, 0, NULL);
}
+
/********************************************************************
First convert any specific postgres types into more
useable data.
}
+
/* This function inserts parameters into an SQL statements.
It will also modify a SELECT statement for use with declare/fetch cursors.
This function no longer does any dynamic memory allocation!
int
copy_statement_with_parameters(StatementClass *stmt)
{
-char *func="copy_statement_with_parameters";
+static char *func="copy_statement_with_parameters";
unsigned int opos, npos;
char param_string[128], tmp[256], cbuf[TEXT_FIELD_SIZE+5];
int param_number;
/* If the application hasn't set a cursor name, then generate one */
if ( stmt->cursor_name[0] == '\0')
- sprintf(stmt->cursor_name, "SQL_CUR%u", stmt);
+ sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
// For selects, prepend a declare cursor to the statement
if (stmt->statement_type == STMT_TYPE_SELECT && globals.use_declarefetch) {
param_ctype = stmt->parameters[param_number].CType;
param_sqltype = stmt->parameters[param_number].SQLType;
- mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n",
- param_ctype,
- param_sqltype);
+ mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n", param_ctype, param_sqltype);
// replace DEFAULT with something we can use
if(param_ctype == SQL_C_DEFAULT)
st.mm = tss->minute;
st.ss = tss->second;
- 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);
+ 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;
// make sure new_statement is always null-terminated
new_statement[npos] = '\0';
+
if(stmt->hdbc->DriverToDataSource != NULL) {
int length = strlen (new_statement);
stmt->hdbc->DriverToDataSource (stmt->hdbc->translation_option,
NULL, 0, NULL);
}
+
return SQL_SUCCESS;
}
int
convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
{
+ mylog("convert_pgbinary_to_char: value = '%s'\n", value);
+
+ strncpy_null(rgbValue, value, cbValueMax);
return 0;
}
mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]);
o++;
}
+
+ rgbValue[o] = '\0';
+
return o;
}
stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ);
if (stmt->lobj_fd < 0) {
stmt->errornumber = STMT_EXEC_ERROR;
- stmt->errormsg = "Couldnt open large object for writing.";
+ stmt->errormsg = "Couldnt open large object for reading.";
return COPY_GENERAL_ERROR;
}
}
- if (stmt->lobj_fd < 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(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValueMax);
if (retval < 0) {
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef UNIX
+#ifndef WIN32
#include
#include "gpps.h"
#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)
-#if !HAVE_STRICMP
+#ifndef HAVE_STRICMP
#define stricmp(s1,s2) strcasecmp(s1,s2)
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#endif
#include "dlg_specific.h"
#include "convert.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;
-#ifndef UNIX /* best to find a #ifdef for WINDOWS */
+#ifdef WIN32
void
SetDlgStuff(HWND hdlg, ConnInfo *ci)
{
return FALSE;
}
-#endif /* !UNIX */
+#endif /* WIN32 */
void
makeConnectString(char *connect_string, ConnInfo *ci)
// strcpy(ci->conn_settings, value);
}
- mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',readonly='%s',protocol='%s', conn_settings='%s')\n",
- ci->dsn,
- ci->server,
- ci->database,
- ci->username,
- ci->password,
- ci->port,
- ci->readonly,
- ci->protocol,
- ci->conn_settings);
+ mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',readonly='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server,ci->database,ci->username,ci->password,ci->port,ci->readonly,ci->protocol,ci->conn_settings);
}
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)
if ( ci->translation_option[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
+
+ /* Allow override of odbcinst.ini parameters here */
+ getGlobalDefaults(DSN, ODBC_INI, TRUE);
+
+
qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
DSN,
ci->server,
/* This function reads the ODBCINST.INI portion of
the registry and gets any driver defaults.
*/
-void getGlobalDefaults(void)
+void getGlobalDefaults(char *section, char *filename, char override)
{
-char temp[128];
+char temp[256];
// Fetch Count is stored in driver section
- SQLGetPrivateProfileString(DBMS_NAME, INI_FETCH, "",
- temp, sizeof(temp), ODBCINST_INI);
+ SQLGetPrivateProfileString(section, INI_FETCH, "",
+ temp, sizeof(temp), filename);
if ( temp[0] ) {
globals.fetch_max = atoi(temp);
/* sanity check if using cursors */
if (globals.fetch_max <= 0)
globals.fetch_max = FETCH_MAX;
}
-
- else
+ else if ( ! override)
globals.fetch_max = FETCH_MAX;
// Socket Buffersize is stored in driver section
- SQLGetPrivateProfileString(DBMS_NAME, INI_SOCKET, "",
- temp, sizeof(temp), ODBCINST_INI);
+ SQLGetPrivateProfileString(section, INI_SOCKET, "",
+ temp, sizeof(temp), filename);
if ( temp[0] )
globals.socket_buffersize = atoi(temp);
- else
+ else if ( ! override)
globals.socket_buffersize = SOCK_BUFFER_SIZE;
// Debug is stored in the driver section
- SQLGetPrivateProfileString(DBMS_NAME, INI_DEBUG, "0",
- temp, sizeof(temp), ODBCINST_INI);
- globals.debug = atoi(temp);
+ SQLGetPrivateProfileString(section, INI_DEBUG, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
+ globals.debug = atoi(temp);
+ else if ( ! override)
+ globals.debug = DEFAULT_DEBUG;
// CommLog is stored in the driver section
- SQLGetPrivateProfileString(DBMS_NAME, INI_COMMLOG, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.commlog = DEFAULT_COMMLOG;
- else
+ SQLGetPrivateProfileString(section, INI_COMMLOG, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.commlog = atoi(temp);
+ else if ( ! override)
+ globals.commlog = DEFAULT_COMMLOG;
// Optimizer is stored in the driver section only
- SQLGetPrivateProfileString(DBMS_NAME, INI_OPTIMIZER, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.disable_optimizer = DEFAULT_OPTIMIZER;
- else
+ SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.disable_optimizer = atoi(temp);
+ else if ( ! override)
+ globals.disable_optimizer = DEFAULT_OPTIMIZER;
// Recognize Unique Index is stored in the driver section only
- SQLGetPrivateProfileString(DBMS_NAME, INI_UNIQUEINDEX, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.unique_index = DEFAULT_UNIQUEINDEX;
- else
+ SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.unique_index = atoi(temp);
+ else if ( ! override)
+ globals.unique_index = DEFAULT_UNIQUEINDEX;
// Unknown Sizes is stored in the driver section only
- SQLGetPrivateProfileString(DBMS_NAME, INI_UNKNOWNSIZES, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.unknown_sizes = DEFAULT_UNKNOWNSIZES;
- else
+ SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.unknown_sizes = atoi(temp);
+ else if ( ! override)
+ globals.unknown_sizes = DEFAULT_UNKNOWNSIZES;
// Lie about supported functions?
- SQLGetPrivateProfileString(DBMS_NAME, INI_LIE, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.lie = DEFAULT_LIE;
- else
+ SQLGetPrivateProfileString(section, INI_LIE, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.lie = atoi(temp);
+ else if ( ! override)
+ globals.lie = DEFAULT_LIE;
// Parse statements
- SQLGetPrivateProfileString(DBMS_NAME, INI_PARSE, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.parse = DEFAULT_PARSE;
- else
+ SQLGetPrivateProfileString(section, INI_PARSE, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.parse = atoi(temp);
+ else if ( ! override)
+ globals.parse = DEFAULT_PARSE;
// Readonly is stored in the driver section AND per datasource
- SQLGetPrivateProfileString(DBMS_NAME, INI_READONLY, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.readonly = DEFAULT_READONLY;
- else
+ SQLGetPrivateProfileString(section, INI_READONLY, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.readonly = atoi(temp);
+ else if ( ! override)
+ globals.readonly = DEFAULT_READONLY;
// UseDeclareFetch is stored in the driver section only
- SQLGetPrivateProfileString(DBMS_NAME, INI_USEDECLAREFETCH, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
- else
+ SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.use_declarefetch = atoi(temp);
+ else if ( ! override)
+ globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
// Max Varchar Size
- SQLGetPrivateProfileString(DBMS_NAME, INI_MAXVARCHARSIZE, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.max_varchar_size = MAX_VARCHAR_SIZE;
- else
+ SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.max_varchar_size = atoi(temp);
+ else if ( ! override)
+ globals.max_varchar_size = MAX_VARCHAR_SIZE;
// Max TextField Size
- SQLGetPrivateProfileString(DBMS_NAME, INI_MAXLONGVARCHARSIZE, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.max_longvarchar_size = TEXT_FIELD_SIZE;
- else
+ SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.max_longvarchar_size = atoi(temp);
+ else if ( ! override)
+ globals.max_longvarchar_size = TEXT_FIELD_SIZE;
// Text As LongVarchar
- SQLGetPrivateProfileString(DBMS_NAME, INI_TEXTASLONGVARCHAR, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
- else
+ SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.text_as_longvarchar = atoi(temp);
+ else if ( ! override)
+ globals.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
// Unknowns As LongVarchar
- SQLGetPrivateProfileString(DBMS_NAME, INI_UNKNOWNSASLONGVARCHAR, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
- else
+ SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.unknowns_as_longvarchar = atoi(temp);
+ else if ( ! override)
+ globals.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
// Bools As Char
- SQLGetPrivateProfileString(DBMS_NAME, INI_BOOLSASCHAR, "",
- temp, sizeof(temp), ODBCINST_INI);
- if ( temp[0] == '\0')
- globals.bools_as_char = DEFAULT_BOOLSASCHAR;
- else
+ SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, "",
+ temp, sizeof(temp), filename);
+ if ( temp[0] )
globals.bools_as_char = atoi(temp);
+ else if ( ! override)
+ globals.bools_as_char = DEFAULT_BOOLSASCHAR;
-
- // Extra System Table prefixes
- SQLGetPrivateProfileString(DBMS_NAME, INI_EXTRASYSTABLEPREFIXES, "@@@",
- globals.extra_systable_prefixes, sizeof(globals.extra_systable_prefixes), ODBCINST_INI);
- if ( ! strcmp(globals.extra_systable_prefixes, "@@@")) {
+ // 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(globals.extra_systable_prefixes, temp);
+ else if ( ! override)
strcpy(globals.extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES);
- }
+
mylog("globals.extra_systable_prefixes = '%s'\n", globals.extra_systable_prefixes);
- // ConnSettings is stored in the driver section and per datasource for override
- SQLGetPrivateProfileString(DBMS_NAME, INI_CONNSETTINGS, "",
- globals.conn_settings, sizeof(globals.conn_settings), ODBCINST_INI);
+ // Dont allow override of an override!
+ if ( ! override) {
+ // ConnSettings is stored in the driver section and per datasource for override
+ SQLGetPrivateProfileString(section, INI_CONNSETTINGS, "",
+ globals.conn_settings, sizeof(globals.conn_settings), filename);
+ }
}
#define __DLG_SPECIFIC_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "psqlodbc.h"
#include "connection.h"
-#ifndef UNIX
+#ifdef WIN32
#include
#include
#include
#define UNKNOWNS_AS_LONGEST 2
/* INI File Stuff */
-#ifdef UNIX
-#define ODBC_INI ".odbc.ini"
-#define ODBCINST_INI "/etc/odbcinst.ini"
+#ifndef WIN32
+#define ODBC_INI ".odbc.ini"
+#ifdef ODBCINST
+#define xstr(s) str(s)
+#define str(s) #s
+#define ODBCINST_INI xstr(ODBCINST) "/odbcinst.ini"
#else
-#define ODBC_INI "ODBC.INI" /* ODBC initialization file */
-#define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */
+#define ODBCINST_INI "/etc/odbcinst.ini"
#endif
+#else
+#define ODBC_INI "ODBC.INI" /* ODBC initialization file */
+#define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */
+#endif
+
#define INI_DSN DBMS_NAME /* Name of default Datasource in ini file (not used?) */
#define INI_KDESC "Description" /* Data source description */
/* Connection Defaults */
#define DEFAULT_PORT "5432"
#define DEFAULT_READONLY 1
-#define DEFAULT_USEDECLAREFETCH 1
+#define DEFAULT_USEDECLAREFETCH 0
#define DEFAULT_TEXTASLONGVARCHAR 1
#define DEFAULT_UNKNOWNSASLONGVARCHAR 0
#define DEFAULT_BOOLSASCHAR 1
#define DEFAULT_OPTIMIZER 1 // disable
#define DEFAULT_UNIQUEINDEX 0 // dont recognize
#define DEFAULT_COMMLOG 0 // dont log
+#define DEFAULT_DEBUG 0
#define DEFAULT_UNKNOWNSIZES UNKNOWNS_AS_MAX
#define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;"
/* prototypes */
-void getGlobalDefaults(void);
+void getGlobalDefaults(char *section, char *filename, char override);
-#ifndef UNIX
+#ifdef WIN32
void SetDlgStuff(HWND hdlg, ConnInfo *ci);
void GetDlgStuff(HWND hdlg, ConnInfo *ci);
WORD wMsg,
WPARAM wParam,
LPARAM lParam);
-#endif /* ! UNIX */
+#endif /* WIN32 */
void updateGlobals(void);
void writeDSNinfo(ConnInfo *ci);
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include
#include "psqlodbc.h"
#include "connection.h"
-#ifdef UNIX
+#ifndef WIN32
#include
#include
#define NEAR
#include
-#ifdef UNIX
+#ifndef WIN32
#define stricmp(s1,s2) strcasecmp(s1,s2)
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#else
/* prototypes */
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci);
-#ifndef UNIX /* should be something like ifdef WINDOWS */
+#ifdef WIN32
BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);
SWORD FAR *pcbConnStrOut,
UWORD fDriverCompletion)
{
-char *func = "SQLDriverConnect";
+static char *func = "SQLDriverConnect";
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
+#ifdef WIN32
RETCODE dialog_result;
+#endif
char connStrIn[MAX_CONNECT_STRING];
char connStrOut[MAX_CONNECT_STRING];
int retval;
char password_required = FALSE;
+ mylog("%s: entering...\n", func);
+
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
// Fill in any default parameters if they are not there.
getDSNdefaults(ci);
+#ifdef WIN32
dialog:
+#endif
ci->focus_password = password_required;
switch(fDriverCompletion) {
-#ifndef UNIX /* again should be ifdef WINDOWS like */
+#ifdef WIN32
case SQL_DRIVER_PROMPT:
dialog_result = dconn_DoDialog(hwnd, ci);
if(dialog_result != SQL_SUCCESS) {
return SQL_ERROR; /* need a password but not allowed to prompt so error */
}
else {
-#ifndef UNIX
+#ifdef WIN32
password_required = TRUE;
goto dialog;
#else
return SQL_SUCCESS;
}
-#ifndef UNIX /* yet another candidate for ifdef WINDOWS */
+#ifdef WIN32
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci)
{
int dialog_result;
return FALSE;
}
-#endif /* ! UNIX */
+#endif /* WIN32 */
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
{
RETCODE SQL_API SQLAllocEnv(HENV FAR *phenv)
{
-char *func = "SQLAllocEnv";
+static char *func = "SQLAllocEnv";
mylog("**** in SQLAllocEnv ** \n");
RETCODE SQL_API SQLFreeEnv(HENV henv)
{
-char *func = "SQLFreeEnv";
+static char *func = "SQLFreeEnv";
EnvironmentClass *env = (EnvironmentClass *) henv;
mylog("**** in SQLFreeEnv: env = %u ** \n", env);
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);
+ mylog(" added at i =%d, conn->henv = %u, conns[i]->henv = %u\n", i, conn->henv, conns[i]->henv);
return TRUE;
}
#define __ENVIRON_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "psqlodbc.h"
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "psqlodbc.h"
#include
#include
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isqlext.h"
#else
#include "lobj.h"
-RETCODE SQL_API SQLExecDirect(
- HSTMT hstmt,
- UCHAR FAR *szSqlStr,
- SDWORD cbSqlStr)
-{
- return _SQLExecDirect(hstmt, szSqlStr, cbSqlStr);
-}
-
-
// Perform a Prepare on the SQL statement
RETCODE SQL_API SQLPrepare(HSTMT hstmt,
UCHAR FAR *szSqlStr,
SDWORD cbSqlStr)
{
-char *func = "SQLPrepare";
+static char *func = "SQLPrepare";
StatementClass *self = (StatementClass *) hstmt;
+ mylog( "%s: entering...\n", func);
+
if ( ! self) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
// Performs the equivalent of SQLPrepare, followed by SQLExecute.
-RETCODE SQL_API _SQLExecDirect(
+RETCODE SQL_API SQLExecDirect(
HSTMT hstmt,
UCHAR FAR *szSqlStr,
SDWORD cbSqlStr)
{
StatementClass *stmt = (StatementClass *) hstmt;
-char *func = "SQLExecDirect";
+RETCODE SQL_API result;
+static char *func = "SQLExecDirect";
+
+ mylog( "%s: entering...\n", func);
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_ERROR;
}
- mylog("**** SQLExecDirect: hstmt=%u, statement='%s'\n", hstmt, stmt->statement);
+ mylog("**** %s: hstmt=%u, statement='%s'\n", func, hstmt, stmt->statement);
stmt->prepare = FALSE;
stmt->statement_type = statement_type(stmt->statement);
return SQL_ERROR;
}
- mylog("SQLExecDirect: calling SQLExecute\n");
+ mylog("%s: calling SQLExecute...\n", func);
+
+ result = SQLExecute(hstmt);
- return SQLExecute(hstmt);
+ mylog("%s: returned %hd from SQLExecute\n", func, result);
+ return result;
}
// Execute a prepared SQL statement
RETCODE SQL_API SQLExecute(
HSTMT hstmt)
{
-char *func="SQLExecute";
+static char *func="SQLExecute";
StatementClass *stmt = (StatementClass *) hstmt;
ConnectionClass *conn;
int i, retval;
+ mylog("%s: entering...\n", func);
+
if ( ! stmt) {
SC_log_error(func, "", NULL);
+ mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func);
return SQL_INVALID_HANDLE;
}
*/
if ( stmt->prepare && stmt->status == STMT_PREMATURE) {
stmt->status = STMT_FINISHED;
- if (stmt->errormsg == NULL)
+ 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);
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;
}
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;
}
to SQLFreeStmt(SQL_CLOSE) or SQLCancel.
*/
if (stmt->status == STMT_FINISHED) {
+ mylog("%s: recycling statement (should have been done by app)...\n", func);
SC_recycle_statement(stmt);
}
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;
}
return SQL_NEED_DATA;
- mylog("SQLExecute: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", conn->transact_status, strlen(stmt->statement), stmt->statement);
+ 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);
HDBC hdbc,
UWORD fType)
{
-char *func = "SQLTransact";
-extern ConnectionClass **conns;
+static char *func = "SQLTransact";
+extern ConnectionClass *conns[];
ConnectionClass *conn;
QResultClass *res;
char ok, *stmt_string;
int lf;
-mylog("**** SQLTransact: hdbc=%u, henv=%u\n", hdbc, henv);
+ 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);
RETCODE SQL_API SQLCancel(
HSTMT hstmt) // Statement to cancel.
{
-char *func="SQLCancel";
+static char *func="SQLCancel";
StatementClass *stmt = (StatementClass *) hstmt;
+ mylog( "%s: entering...\n", func);
+
// Check if this can handle canceling in the middle of a SQLPutData?
if ( ! stmt) {
SC_log_error(func, "", NULL);
SDWORD cbSqlStrMax,
SDWORD FAR *pcbSqlStr)
{
+static char *func="SQLNativeSql";
+
+ mylog( "%s: entering...\n", func);
strncpy_null(szSqlStr, szSqlStrIn, cbSqlStrMax);
HSTMT hstmt,
PTR FAR *prgbValue)
{
-char *func = "SQLParamData";
+static char *func = "SQLParamData";
StatementClass *stmt = (StatementClass *) hstmt;
int i, retval;
+ mylog( "%s: entering...\n", func);
+
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
- mylog("SQLParamData, enter: data_at_exec=%d, params_alloc=%d\n",
- stmt->data_at_exec, stmt->parameters_allocated);
+ mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated);
if (stmt->data_at_exec < 0) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
PTR rgbValue,
SDWORD cbValue)
{
-char *func = "SQLPutData";
+static char *func = "SQLPutData";
StatementClass *stmt = (StatementClass *) hstmt;
int old_pos, retval;
ParameterInfoClass *current_param;
char *buffer;
+ mylog( "%s: entering...\n", func);
if ( ! stmt) {
SC_log_error(func, "", NULL);
#ifndef WIN32
#if HAVE_CONFIG_H
-#include // produced by configure
+#include "config.h" // produced by configure
#endif
#include
#include
+#include
#if HAVE_PWD_H
#include
#include
#include "gpps.h"
+#include "misc.h"
#ifndef TRUE
#define TRUE ((BOOL)1)
size_t aLength;
char aLine[2048];
char *aValue;
+ char *aStart;
char *aString;
size_t aLineLength;
size_t aReturnLength = 0;
if( (aString = strchr(aLine, ']')) )
{
- *aString = '\0';
+ aStart = aLine + 1;
+ aString--;
+ while (isspace(*aStart)) aStart++;
+ while (isspace(*aString)) aString--;
+ *(aString+1) = '\0';
// accept as matched if NULL key or exact match
- if(!theSection || !strcmp(aLine + 1, theSection))
+ if(!theSection || !strcmp(aStart, theSection))
{
aSectionFound = TRUE;
}
aValue = "";
}
+ aStart = aLine;
+ while(isspace(*aStart)) aStart++;
+
// strip trailing blanks from key
if(aString)
{
- while(--aString >= aLine && *aString == ' ')
+ while(--aString >= aStart && *aString == ' ')
{
*aString = '\0';
}
// see if key is matched
- if(theKey == NULL || !strcmp(theKey, aLine))
+ if(theKey == NULL || !strcmp(theKey, aStart))
{
// matched -- first, terminate value part
#define GPPS_H
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef UNIX
+#ifndef WIN32
#include
#include "iodbc.h"
#endif
}
#endif
-#ifdef UNIX
+#ifndef WIN32
#undef DWORD
#endif
#endif
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include
#include
#include "psqlodbc.h"
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
+#include /* for tolower function */
#else
#include
#include
#include "pgtypes.h"
+/* Trigger related stuff for SQLForeign Keys */
+#define TRIGGER_SHIFT 3
+#define TRIGGER_MASK 0x03
+#define TRIGGER_DELETE 0x01
+#define TRIGGER_UPDATE 0x02
+
+
extern GLOBAL_VALUES globals;
+
// - - - - - - - - -
RETCODE SQL_API SQLGetInfo(
SWORD cbInfoValueMax,
SWORD FAR *pcbInfoValue)
{
-char *func = "SQLGetInfo";
+static char *func = "SQLGetInfo";
ConnectionClass *conn = (ConnectionClass *) hdbc;
+ConnInfo *ci;
char *p;
+ mylog( "%s: entering...\n", func);
+
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
return SQL_INVALID_HANDLE;
}
+ ci = &conn->connInfo;
switch (fInfoType) {
case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */
case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */
// the character used to quote "identifiers" (what are they?)
- // the manual index lists 'owner names' and 'qualifiers' as
- // examples of identifiers. it says return a blank for no
- // quote character, we'll try that...
if (pcbInfoValue) *pcbInfoValue = 1;
- strncpy_null((char *)rgbInfoValue, "\"", (size_t)cbInfoValueMax);
+ strncpy_null((char *)rgbInfoValue, PROTOCOL_62(ci) ? " " : "\"", (size_t)cbInfoValueMax);
break;
case SQL_KEYWORDS: /* ODBC 2.0 */
HSTMT hstmt,
SWORD fSqlType)
{
-char *func = "SQLGetTypeInfo";
+static char *func = "SQLGetTypeInfo";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
int i;
Int4 type;
- mylog("**** in SQLGetTypeInfo: fSqlType = %d\n", fSqlType);
+ mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
if( ! stmt) {
SC_log_error(func, "", NULL);
UWORD fFunction,
UWORD FAR *pfExists)
{
+static char *func="SQLGetFunctions";
+
+ mylog( "%s: entering...\n", func);
+
if (fFunction == SQL_API_ALL_FUNCTIONS) {
if (globals.lie) {
UCHAR FAR * szTableType,
SWORD cbTableType)
{
-char *func = "SQLTables";
+static char *func = "SQLTables";
StatementClass *stmt = (StatementClass *) hstmt;
StatementClass *tbl_stmt;
TupleNode *row;
char regular_table, view, systable;
int i;
-mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
+mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
// Create the query to find out the tables
// **********************************************************************
- strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user where relkind = 'r' ");
+ strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
+ strcat(tables_query, " where relkind = 'r'");
my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);
/* filter out large objects unconditionally (they are not system tables) and match users */
- strcat(tables_query, " and relname !~ '^xinv[0-9]+' and int4out(usesysid) = int4out(relowner) order by relname");
+ strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
+ strcat(tables_query, " and int4out(usesysid) = int4out(relowner)");
+ strcat(tables_query, "order by relname");
// **********************************************************************
UCHAR FAR * szColumnName,
SWORD cbColumnName)
{
-char *func = "SQLColumns";
+static char *func = "SQLColumns";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
HSTMT hcol_stmt;
char columns_query[MAX_STATEMENT_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, field_length, mod_length, result_cols;
-Int4 field_type, the_type;
+Int2 field_number, result_cols;
+Int4 field_type, the_type, field_length, mod_length;
char not_null[MAX_INFO_STRING];
ConnInfo *ci;
-
-mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
+ mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
}
col_stmt = (StatementClass *) hcol_stmt;
+ mylog("SQLColumns: hcol_stmt = %u, col_stmt = %u\n", hcol_stmt, col_stmt);
+
result = SQLExecDirect(hcol_stmt, columns_query,
strlen(columns_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
return SQL_ERROR;
}
- result = SQLBindCol(hcol_stmt, 4, SQL_C_DEFAULT,
+ result = SQLBindCol(hcol_stmt, 4, SQL_C_LONG,
&field_type, 4, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
return SQL_ERROR;
}
- result = SQLBindCol(hcol_stmt, 6, SQL_C_DEFAULT,
+ result = SQLBindCol(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;
return SQL_ERROR;
}
- result = SQLBindCol(hcol_stmt, 7, SQL_C_DEFAULT,
+ result = SQLBindCol(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;
return SQL_ERROR;
}
- result = SQLBindCol(hcol_stmt, 8, SQL_C_DEFAULT,
+ result = SQLBindCol(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;
result = SQLFetch(hcol_stmt);
+
/* Only show oid if option AND there are other columns AND
its not being called by SQLStatistics .
Always show OID if its a system table
row = (TupleNode *)malloc(sizeof(TupleNode) +
(result_cols - 1) * sizeof(TupleField));
+
set_tuplefield_string(&row->tuple[0], "");
// see note in SQLTables()
// set_tuplefield_string(&row->tuple[1], table_owner);
QR_add_tuple(stmt->result, row);
+
result = SQLFetch(hcol_stmt);
+
}
if(result != SQL_NO_DATA_FOUND) {
stmt->errormsg = SC_create_errormsg(hcol_stmt);
UWORD fScope,
UWORD fNullable)
{
-char *func = "SQLSpecialColumns";
+static char *func = "SQLSpecialColumns";
TupleNode *row;
StatementClass *stmt = (StatementClass *) hstmt;
ConnInfo *ci;
-mylog("**** SQLSpecialColumns(): ENTER, stmt=%u\n", stmt);
+mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
UWORD fUnique,
UWORD fAccuracy)
{
-char *func="SQLStatistics";
+static char *func="SQLStatistics";
StatementClass *stmt = (StatementClass *) hstmt;
char index_query[MAX_STATEMENT_LEN];
HSTMT hindx_stmt;
ConnInfo *ci;
char buf[256];
-mylog("**** SQLStatistics(): ENTER, stmt=%u\n", stmt);
+mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
UCHAR FAR * szColumnName,
SWORD cbColumnName)
{
-char *func="SQLColumnPrivileges";
+static char *func="SQLColumnPrivileges";
+
+ mylog("%s: entering...\n", func);
+
/* Neither Access or Borland care about this. */
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
-RETCODE
-getPrimaryKeyString(StatementClass *stmt, char *szTableName, SWORD cbTableName, char *svKey, int *nKey)
+
+
+RETCODE SQL_API SQLPrimaryKeys(
+ HSTMT hstmt,
+ UCHAR FAR * szTableQualifier,
+ SWORD cbTableQualifier,
+ UCHAR FAR * szTableOwner,
+ SWORD cbTableOwner,
+ UCHAR FAR * szTableName,
+ SWORD cbTableName)
{
-char *func = "getPrimaryKeyString";
+static char *func = "SQLPrimaryKeys";
+StatementClass *stmt = (StatementClass *) hstmt;
+TupleNode *row;
+RETCODE result;
+int seq = 0;
HSTMT htbl_stmt;
StatementClass *tbl_stmt;
-RETCODE result;
char tables_query[MAX_STATEMENT_LEN];
char attname[MAX_INFO_STRING];
SDWORD attname_len;
-int nk = 0;
-
- if (nKey != NULL)
- *nKey = 0;
+char pktab[MAX_TABLE_LEN + 1];
+Int2 result_cols;
- svKey[0] = '\0';
+ mylog("%s: entering...stmt=%u\n", func, stmt);
+ if( ! stmt) {
+ SC_log_error(func, "", NULL);
+ return SQL_INVALID_HANDLE;
+ }
+ stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
+ stmt->result = QR_Constructor();
+ if(!stmt->result) {
+ stmt->errormsg = "Couldn't allocate memory for SQLPrimaryKeys result.";
+ stmt->errornumber = STMT_NO_MEMORY_ERROR;
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
+ }
+
+ // the binding structure for a statement is not set up until
+ // a statement is actually executed, so we'll have to do this ourselves.
+ result_cols = 6;
+ extend_bindings(stmt, result_cols);
+
+ // set the field names
+ QR_set_num_fields(stmt->result, result_cols);
+ QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
+ QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+
+
result = SQLAllocStmt( stmt->hdbc, &htbl_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
}
tbl_stmt = (StatementClass *) htbl_stmt;
- tables_query[0] = '\0';
- if ( ! my_strcat(tables_query, "select distinct on attnum a2.attname, a2.attnum from pg_attribute a1, pg_attribute a2, pg_class c, pg_index i where c.relname = '%.*s_pkey' AND c.oid = i.indexrelid AND a1.attrelid = c.oid AND a2.attrelid = c.oid AND (i.indkey[0] = a1.attnum OR i.indkey[1] = a1.attnum OR i.indkey[2] = a1.attnum OR i.indkey[3] = a1.attnum OR i.indkey[4] = a1.attnum OR i.indkey[5] = a1.attnum OR i.indkey[6] = a1.attnum OR i.indkey[7] = a1.attnum) order by a2.attnum",
- szTableName, cbTableName)) {
-
- stmt->errormsg = "No Table specified to getPrimaryKeyString.";
+ pktab[0] = '\0';
+ make_string(szTableName, cbTableName, pktab);
+ if ( pktab[0] == '\0') {
+ stmt->errormsg = "No Table specified to SQLPrimaryKeys.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
- mylog("getPrimaryKeyString: tables_query='%s'\n", tables_query);
+ sprintf(tables_query, "select distinct on attnum a2.attname, a2.attnum from pg_attribute a1, pg_attribute a2, pg_class c, pg_index i where c.relname = '%s_pkey' AND c.oid = i.indexrelid AND a1.attrelid = c.oid AND a2.attrelid = c.oid AND (i.indkey[0] = a1.attnum OR i.indkey[1] = a1.attnum OR i.indkey[2] = a1.attnum OR i.indkey[3] = a1.attnum OR i.indkey[4] = a1.attnum OR i.indkey[5] = a1.attnum OR i.indkey[6] = a1.attnum OR i.indkey[7] = a1.attnum) order by a2.attnum", pktab);
+
+ mylog("SQLPrimaryKeys: tables_query='%s'\n", tables_query);
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
}
result = SQLFetch(htbl_stmt);
+
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) {
- if (strlen(svKey) > 0)
- strcat(svKey, "+");
- strcat(svKey, attname);
+ row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
+
+ set_tuplefield_null(&row->tuple[0]);
+
+ // I have to hide the table owner from Access, otherwise it
+ // insists on referring to the table as 'owner.table'.
+ // (this is valid according to the ODBC SQL grammar, but
+ // Postgres won't support it.)
+
+ set_tuplefield_string(&row->tuple[1], "");
+ set_tuplefield_string(&row->tuple[2], pktab);
+ set_tuplefield_string(&row->tuple[3], attname);
+ set_tuplefield_int2(&row->tuple[4], (Int2) (++seq));
+ set_tuplefield_null(&row->tuple[5]);
+
+ QR_add_tuple(stmt->result, row);
+
+ mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq);
result = SQLFetch(htbl_stmt);
- nk++;
}
if(result != SQL_NO_DATA_FOUND) {
SQLFreeStmt(htbl_stmt, SQL_DROP);
- if (nKey != NULL)
- *nKey = nk;
-
- mylog(">> getPrimaryKeyString: returning nKey=%d, svKey='%s'\n", nk, svKey);
- return result;
-}
-
-RETCODE
-getPrimaryKeyArray(StatementClass *stmt, char *szTableName, SWORD cbTableName, char keyArray[][MAX_INFO_STRING], int *nKey)
-{
-RETCODE result;
-char svKey[MAX_KEYLEN], *svKeyPtr;
-int i = 0;
-
- result = getPrimaryKeyString(stmt, szTableName, cbTableName, svKey, nKey);
- if (result != SQL_SUCCESS && result != SQL_NO_DATA_FOUND)
- // error passed from above
- return result;
-
- // If no keys, return NO_DATA_FOUND
- if (svKey[0] == '\0') {
- mylog("!!!!!! getPrimaryKeyArray: svKey was null\n");
- return SQL_NO_DATA_FOUND;
- }
-
- // mylog(">> primarykeyArray: nKey=%d, svKey='%s'\n", *nKey, svKey);
-
- svKeyPtr = strtok(svKey, "+");
- while (svKeyPtr != NULL && i < MAX_KEYPARTS) {
- strcpy(keyArray[i++], svKeyPtr);
- svKeyPtr = strtok(NULL, "+");
- }
-
- /*
- for (i = 0; i < *nKey; i++)
- mylog(">> keyArray[%d] = '%s'\n", i, keyArray[i]);
- */
-
- return result;
-}
-
-
-RETCODE SQL_API SQLPrimaryKeys(
- HSTMT hstmt,
- UCHAR FAR * szTableQualifier,
- SWORD cbTableQualifier,
- UCHAR FAR * szTableOwner,
- SWORD cbTableOwner,
- UCHAR FAR * szTableName,
- SWORD cbTableName)
-{
-char *func = "SQLPrimaryKeys";
-StatementClass *stmt = (StatementClass *) hstmt;
-TupleNode *row;
-RETCODE result;
-char svKey[MAX_KEYLEN], *ptr;
-int seq = 1, nkeys = 0;
-
-mylog("**** SQLPrimaryKeys(): ENTER, stmt=%u\n", stmt);
-
- if( ! stmt) {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
- stmt->manual_result = TRUE;
-
- result = getPrimaryKeyString(stmt, szTableName, cbTableName, svKey, &nkeys);
-
- mylog(">> PrimaryKeys: getPrimaryKeyString() returned %d, nkeys=%d, svKey = '%s'\n", result, nkeys, svKey);
-
- if (result != SQL_SUCCESS && result != SQL_NO_DATA_FOUND) {
- // error msg passed from above
- return result;
- }
-
- // I'm not sure if this is correct to return when there are no keys or
- // if an empty result set would be better.
- if (nkeys == 0) {
- stmt->errornumber = STMT_INFO_ONLY;
- stmt->errormsg = "No primary keys for this table.";
- return SQL_SUCCESS_WITH_INFO;
- }
-
- stmt->result = QR_Constructor();
- if(!stmt->result) {
- stmt->errormsg = "Couldn't allocate memory for SQLPrimaryKeys result.";
- stmt->errornumber = STMT_NO_MEMORY_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
-
-
- // the binding structure for a statement is not set up until
- // a statement is actually executed, so we'll have to do this ourselves.
- extend_bindings(stmt, 6);
-
- // set the field names
- QR_set_num_fields(stmt->result, 6);
- QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
-
- // add the tuples
- ptr = strtok(svKey, "+");
- while( ptr != NULL) {
- row = (TupleNode *)malloc(sizeof(TupleNode) + (6 - 1) * sizeof(TupleField));
-
- set_tuplefield_string(&row->tuple[0], "");
-
- // I have to hide the table owner from Access, otherwise it
- // insists on referring to the table as 'owner.table'.
- // (this is valid according to the ODBC SQL grammar, but
- // Postgres won't support it.)
-
- mylog(">> primaryKeys: ptab = '%s', seq = %d\n", ptr, seq);
-
- set_tuplefield_string(&row->tuple[1], "");
- set_tuplefield_string(&row->tuple[2], szTableName);
- set_tuplefield_string(&row->tuple[3], ptr);
- set_tuplefield_int2(&row->tuple[4], (Int2) (seq++));
- set_tuplefield_null(&row->tuple[5]);
-
- QR_add_tuple(stmt->result, row);
-
- ptr = strtok(NULL, "+");
- }
// also, things need to think that this statement is finished so
// the results can be retrieved.
UCHAR FAR * szFkTableName,
SWORD cbFkTableName)
{
-char *func = "SQLForeignKeys";
+static char *func = "SQLForeignKeys";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
-HSTMT htbl_stmt;
+HSTMT htbl_stmt, hpkey_stmt;
StatementClass *tbl_stmt;
-RETCODE result;
+RETCODE result, keyresult;
char tables_query[MAX_STATEMENT_LEN];
-char relname[MAX_INFO_STRING], attnames[MAX_INFO_STRING], frelname[MAX_INFO_STRING];
-SDWORD relname_len, attnames_len, frelname_len;
-char *pktab, *fktab;
-char fkey = FALSE;
-char primaryKey[MAX_KEYPARTS][MAX_INFO_STRING];
-char *attnamePtr;
-int pkeys, seq;
+char args[1024], tgname[MAX_INFO_STRING];
+char pktab[MAX_TABLE_LEN + 1], fktab[MAX_TABLE_LEN + 1];
+char *ptr, *pkey_ptr, *pkptr, *fkptr, *frel, *prel;
+int i, k, pkeys, seq, ntabs;
+SWORD nargs, rule_type, action;
+char pkey[MAX_INFO_STRING];
+Int2 result_cols;
+
-mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
+ mylog("%s: entering...stmt=%u\n", func, stmt);
- memset(primaryKey, 0, sizeof(primaryKey));
if( ! stmt) {
SC_log_error(func, "", NULL);
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
+ stmt->result = QR_Constructor();
+ if(!stmt->result) {
+ stmt->errormsg = "Couldn't allocate memory for SQLForeignKeys result.";
+ stmt->errornumber = STMT_NO_MEMORY_ERROR;
+ SC_log_error(func, "", stmt);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
+
+ // the binding structure for a statement is not set up until
+ // a statement is actually executed, so we'll have to do this ourselves.
+ result_cols = 14;
+ extend_bindings(stmt, result_cols);
+
+ // set the field names
+ QR_set_num_fields(stmt->result, result_cols);
+ QR_set_field_info(stmt->result, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
+ QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
+ QR_set_field_info(stmt->result, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
+ QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(stmt->result, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+
+ // 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->current_col = -1;
+
+
result = SQLAllocStmt( stmt->hdbc, &htbl_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
tbl_stmt = (StatementClass *) htbl_stmt;
- pktab = make_string(szPkTableName, cbPkTableName, NULL);
- fktab = make_string(szFkTableName, cbFkTableName, NULL);
+ pktab[0] = '\0';
+ fktab[0] = '\0';
+
+ make_string(szPkTableName, cbPkTableName, pktab);
+ make_string(szFkTableName, cbFkTableName, fktab);
- if (pktab && fktab) {
- // Get the primary key of the table listed in szPkTable
- result = getPrimaryKeyArray(stmt, pktab, (SWORD) strlen(pktab), primaryKey, &pkeys);
- if (result != SQL_SUCCESS && result != SQL_NO_DATA_FOUND) {
- // error msg passed from above
+
+ /* Case #2 -- Get the foreign keys in the specified table (fktab) that
+ refer to the primary keys of other table(s).
+ */
+ if (fktab[0] != '\0') {
+
+ sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs, pg_trigger.tgname from pg_proc, pg_trigger, pg_class where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid AND pg_proc.proname = 'check_primary_key' AND pg_class.relname = '%s'",
+ fktab);
+
+ result = SQLExecDirect(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);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
+
+ result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY,
+ args, 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);
SQLFreeStmt(htbl_stmt, SQL_DROP);
- free(pktab); free(fktab);
- return result;
+ return SQL_ERROR;
}
- if (pkeys == 0) {
- stmt->errornumber = STMT_INFO_ONLY;
- stmt->errormsg = "No primary keys for this table.";
+
+ result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT,
+ &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);
SQLFreeStmt(htbl_stmt, SQL_DROP);
- free(pktab); free(fktab);
- return SQL_SUCCESS_WITH_INFO;
+ return SQL_ERROR;
}
- sprintf(tables_query, "select relname, attnames, frelname from %s where relname='%s' AND frelname='%s'", KEYS_TABLE, fktab, pktab);
- free(pktab); free(fktab);
- }
- else if (pktab) {
- // Get the primary key of the table listed in szPkTable
- result = getPrimaryKeyArray(stmt, pktab, (SWORD) strlen(pktab), primaryKey, &pkeys);
- if (result != SQL_SUCCESS && result != SQL_NO_DATA_FOUND) {
- // error msg passed from above
+ result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
+ tgname, sizeof(tgname), 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);
SQLFreeStmt(htbl_stmt, SQL_DROP);
- free(pktab);
- return result;
+ return SQL_ERROR;
}
- if (pkeys == 0) {
- stmt->errornumber = STMT_INFO_ONLY;
- stmt->errormsg = "No primary keys for this table.";
+
+ result = SQLFetch(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);
SQLFreeStmt(htbl_stmt, SQL_DROP);
- free(pktab);
- return SQL_SUCCESS_WITH_INFO;
+ return SQL_ERROR;
}
- sprintf(tables_query, "select relname, attnames, frelname from %s where frelname='%s'", KEYS_TABLE, pktab);
- free(pktab);
- }
- else if (fktab) {
- // This query could involve multiple calls to getPrimaryKey()
- // so put that off till we know what pktables we need.
- fkey = TRUE;
+ keyresult = SQLAllocStmt( 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 SQLForeignKeys (pkeys) result.";
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
+ }
- sprintf(tables_query, "select relname, attnames, frelname from %s where relname='%s'", KEYS_TABLE, fktab);
- free(fktab);
- }
- else {
- stmt->errormsg = "No tables specified to SQLForeignKeys.";
- stmt->errornumber = STMT_INTERNAL_ERROR;
- SC_log_error(func, "", stmt);
- SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
+ keyresult = SQLBindCol(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 SQLForeignKeys result.";
+ SC_log_error(func, "", stmt);
+ SQLFreeStmt(hpkey_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- result = SQLExecDirect(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);
- SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
+ while (result == SQL_SUCCESS) {
- result = SQLBindCol(htbl_stmt, 1, SQL_C_CHAR,
- relname, MAX_INFO_STRING, &relname_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);
- SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
- result = SQLBindCol(htbl_stmt, 2, SQL_C_CHAR,
- attnames, MAX_INFO_STRING, &attnames_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);
- SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
+ /* Compute the number of keyparts. */
+ pkeys = nargs / 2;
- result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
- frelname, MAX_INFO_STRING, &frelname_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);
- SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
+ mylog("Foreign Key Case#2: nargs = %d, pkeys = %d\n", nargs, pkeys);
- stmt->result = QR_Constructor();
- if(!stmt->result) {
- stmt->errormsg = "Couldn't allocate memory for SQLForeignKeys result.";
- stmt->errornumber = STMT_NO_MEMORY_ERROR;
- SC_log_error(func, "", stmt);
- SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
+ ptr = args;
- // the binding structure for a statement is not set up until
- // a statement is actually executed, so we'll have to do this ourselves.
- extend_bindings(stmt, 13);
+ /* Get to the PK Table Name */
+ for (k = 0; k < pkeys; k++)
+ ptr += strlen(ptr) + 1;
- // set the field names
- QR_set_num_fields(stmt->result, 13);
- QR_set_field_info(stmt->result, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ prel = ptr;
- // add the tuples
- result = SQLFetch(htbl_stmt);
+ mylog("prel = '%s'\n", prel);
- while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) {
+ /* If there is a pk table specified, then check it. */
+ if (pktab[0] != '\0') {
+
+ /* If it doesn't match, then continue */
+ if ( strcmp(prel, pktab)) {
+ result = SQLFetch(htbl_stmt);
+ continue;
+ }
+ }
+
+ keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, prel, SQL_NTS);
+ if (keyresult != SQL_SUCCESS) {
+ stmt->errornumber = STMT_NO_MEMORY_ERROR;
+ stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result.";
+ SC_log_error(func, "", stmt);
+ SQLFreeStmt(hpkey_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
+
+
+ /* Check that the key listed is the primary key */
+ keyresult = SQLFetch(hpkey_stmt);
+ for (k = 0; k < pkeys; k++) {
+
+ ptr += strlen(ptr) + 1;
+ if ( keyresult != SQL_SUCCESS || strcmp(ptr, pkey)) {
+ pkeys = 0;
+ break;
+ }
+ keyresult = SQLFetch(hpkey_stmt);
+ }
+ ptr = prel;
+
+
+
+ /* Set to first fk column */
+ fkptr = args;
+ seq = 0;
+
+ for (k = 0; k < pkeys; k++) {
+
+ row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
+
+ set_tuplefield_null(&row->tuple[0]);
+ set_tuplefield_string(&row->tuple[1], "");
- if (fkey == TRUE) {
- result = getPrimaryKeyArray(stmt, frelname, (SWORD) strlen(frelname), primaryKey, &pkeys);
+ set_tuplefield_string(&row->tuple[2], prel);
- // mylog(">> getPrimaryKeyArray: frelname = '%s', pkeys = %d, result = %d\n", frelname, pkeys, result);
+ // Get to the primary key
+ ptr += strlen(ptr) + 1;
+
+ mylog("prel = '%s', ptr = '%s'\n", prel, ptr);
+
+ set_tuplefield_string(&row->tuple[3], ptr);
+ set_tuplefield_null(&row->tuple[4]);
+ set_tuplefield_string(&row->tuple[5], "");
+
+ set_tuplefield_string(&row->tuple[6], fktab);
+ set_tuplefield_string(&row->tuple[7], fkptr);
+
+ mylog("fktab = '%s', fkptr = '%s'\n", fktab, fkptr);
+
+ set_tuplefield_int2(&row->tuple[8], (Int2) (++seq));
+ set_tuplefield_null(&row->tuple[9]);
+ set_tuplefield_null(&row->tuple[10]);
+ set_tuplefield_null(&row->tuple[11]);
+ set_tuplefield_null(&row->tuple[12]);
+
+ set_tuplefield_string(&row->tuple[13], tgname);
+
+ QR_add_tuple(stmt->result, row);
+
+ // next foreign key
+ fkptr += strlen(fkptr) + 1;
- // If an error occurs or for some reason there is no primary key for a
- // table that is a foreign key, then skip that one.
- if ((result != SQL_SUCCESS && result != SQL_NO_DATA_FOUND) || pkeys == 0) {
- result = SQLFetch(htbl_stmt);
- continue;
}
- /*
- for (i = 0; i< pkeys; i++)
- mylog(">> fkey: pkeys=%d, primaryKey[%d] = '%s'\n", pkeys, i, primaryKey[i]);
- mylog(">> !!!!!!!!! pkeys = %d\n", pkeys);
- */
+ result = SQLFetch(htbl_stmt);
}
+ }
- // mylog(">> attnames='%s'\n", attnames);
+ /* 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 (pktab[0] != '\0') {
+
+ sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs, pg_trigger.tgtype, pg_trigger.tgname from pg_proc, pg_trigger, pg_class where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid AND pg_proc.proname = 'check_foreign_key' AND pg_class.relname = '%s'",
+ pktab);
+
+ result = SQLExecDirect(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);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- attnamePtr = strtok(attnames, "+");
- seq = 0;
+ result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY,
+ args, sizeof(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);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- while (attnamePtr != NULL && seq < pkeys) {
+ result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT,
+ &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);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- row = (TupleNode *)malloc(sizeof(TupleNode) + (13 - 1) * sizeof(TupleField));
+ result = SQLBindCol(htbl_stmt, 3, SQL_C_SHORT,
+ &rule_type, 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);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- set_tuplefield_null(&row->tuple[0]);
+ result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR,
+ tgname, sizeof(tgname), 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);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- // 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.)
+ result = SQLFetch(htbl_stmt);
+ if (result == SQL_NO_DATA_FOUND)
+ return SQL_SUCCESS;
- mylog(">> foreign keys: pktab='%s' patt='%s' fktab='%s' fatt='%s' seq=%d\n",
- frelname, primaryKey[seq], relname, attnamePtr, (seq+1));
+ if(result != SQL_SUCCESS) {
+ stmt->errormsg = SC_create_errormsg(htbl_stmt);
+ stmt->errornumber = tbl_stmt->errornumber;
+ SC_log_error(func, "", stmt);
+ SQLFreeStmt(htbl_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- set_tuplefield_string(&row->tuple[1], "");
- set_tuplefield_string(&row->tuple[2], frelname);
- set_tuplefield_string(&row->tuple[3], primaryKey[seq]);
- set_tuplefield_null(&row->tuple[4]);
- set_tuplefield_string(&row->tuple[5], "");
- set_tuplefield_string(&row->tuple[6], relname);
- set_tuplefield_string(&row->tuple[7], attnamePtr);
- set_tuplefield_int2(&row->tuple[8], (Int2) (++seq));
- set_tuplefield_null(&row->tuple[9]);
- set_tuplefield_null(&row->tuple[10]);
- set_tuplefield_null(&row->tuple[11]);
- set_tuplefield_null(&row->tuple[12]);
+ keyresult = SQLAllocStmt( 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 SQLForeignKeys (pkeys) result.";
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
+ }
- QR_add_tuple(stmt->result, row);
+ keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pktab, SQL_NTS);
+ if (keyresult != SQL_SUCCESS) {
+ stmt->errornumber = STMT_NO_MEMORY_ERROR;
+ stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result.";
+ SC_log_error(func, "", stmt);
+ SQLFreeStmt(hpkey_stmt, SQL_DROP);
+ return SQL_ERROR;
+ }
- attnamePtr = strtok(NULL, "+");
+ keyresult = SQLBindCol(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 SQLForeignKeys result.";
+ SC_log_error(func, "", stmt);
+ SQLFreeStmt(hpkey_stmt, SQL_DROP);
+ return SQL_ERROR;
}
- result = SQLFetch(htbl_stmt);
- }
- if(result != SQL_NO_DATA_FOUND) {
- stmt->errormsg = SC_create_errormsg(htbl_stmt);
- stmt->errornumber = tbl_stmt->errornumber;
+ while (result == SQL_SUCCESS) {
+ // Get the number of tables
+ ptr = args;
+ ntabs = atoi(args);
+ ptr += strlen(ptr) + 1;
+
+
+ // Handle action (i.e., 'cascade', 'restrict', 'setnull')
+ switch(tolower(ptr[0])) {
+ case 'c':
+ action = SQL_CASCADE;
+ break;
+ case 'r':
+ action = SQL_RESTRICT;
+ break;
+ case 's':
+ action = SQL_SET_NULL;
+ break;
+ default:
+ action = -1;
+ break;
+ }
+
+ rule_type >>= TRIGGER_SHIFT;
+ ptr += strlen(ptr) + 1;
+
+ // Calculate the number of key parts
+ pkeys = (nargs - ( 2 + ntabs)) / (ntabs + 1);
+ pkey_ptr = ptr;
+
+
+ keyresult = SQLExtendedFetch(hpkey_stmt, SQL_FETCH_FIRST, -1, NULL, NULL);
+ if ( keyresult != SQL_SUCCESS || strcmp(pkey, ptr)) {
+ ntabs = 0;
+ }
+
+ // Get to the last primary keypart
+ for (i = 1; i < pkeys; i++) {
+
+ // If keypart doesnt match, skip this entry
+ if ( keyresult != SQL_SUCCESS || strcmp(pkey, ptr)) {
+ ntabs = 0;
+ break;
+ }
+ ptr += strlen(ptr) + 1;
+
+ keyresult = SQLExtendedFetch(hpkey_stmt, SQL_FETCH_NEXT, -1, NULL, NULL);
+ }
+
+ mylog("Foreign Key Case#1: nargs = %d, ntabs = %d, pkeys = %d\n", nargs, ntabs, pkeys);
+
+
+ // Get Foreign Key Tables
+ for (i = 0; i < ntabs; i++) {
+
+ seq = 0;
+ pkptr = pkey_ptr;
+
+ ptr += strlen(ptr) + 1;
+ frel = ptr;
+
+ for (k = 0; k < pkeys; k++) {
+
+ row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
+
+ set_tuplefield_null(&row->tuple[0]);
+ set_tuplefield_string(&row->tuple[1], "");
+
+ set_tuplefield_string(&row->tuple[2], pktab);
+ set_tuplefield_string(&row->tuple[3], pkptr);
+
+ mylog("pktab = '%s', pkptr = '%s'\n", pktab, pkptr);
+
+ set_tuplefield_null(&row->tuple[4]);
+ set_tuplefield_string(&row->tuple[5], "");
+ set_tuplefield_string(&row->tuple[6], frel);
+
+ // Get to the foreign key
+ ptr += strlen(ptr) + 1;
+
+ set_tuplefield_string(&row->tuple[7], ptr);
+
+ mylog("frel = '%s', ptr = '%s'\n", frel, ptr);
+ mylog("rule_type = %d, action = %d\n", rule_type, action);
+
+ set_tuplefield_int2(&row->tuple[8], (Int2) (++seq));
+
+ set_nullfield_int2(&row->tuple[9], (Int2) ((rule_type & TRIGGER_UPDATE) ? action : -1));
+ set_nullfield_int2(&row->tuple[10], (Int2) ((rule_type & TRIGGER_DELETE) ? action : -1));
+
+ set_tuplefield_null(&row->tuple[11]);
+ set_tuplefield_null(&row->tuple[12]);
+
+ set_tuplefield_string(&row->tuple[13], tgname);
+
+ QR_add_tuple(stmt->result, row);
+
+ // next primary key
+ pkptr += strlen(pkptr) + 1;
+
+ }
+
+ }
+
+ result = SQLFetch(htbl_stmt);
+ }
+ }
+ else {
+ stmt->errormsg = "No tables specified to SQLForeignKeys.";
+ stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
- }
+ return SQL_ERROR;
+ }
SQLFreeStmt(htbl_stmt, SQL_DROP);
-
- // also, things need to think that this statement is finished so
- // the results can be retrieved.
- stmt->status = STMT_FINISHED;
-
- // set up the current tuple pointer for SQLFetch
- stmt->currTuple = -1;
- stmt->current_col = -1;
+ SQLFreeStmt(hpkey_stmt, SQL_DROP);
mylog("SQLForeignKeys(): EXIT, stmt=%u\n", stmt);
return SQL_SUCCESS;
UCHAR FAR * szColumnName,
SWORD cbColumnName)
{
-char *func="SQLProcedureColumns";
+static char *func="SQLProcedureColumns";
+
+ mylog("%s: entering...\n", func);
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
UCHAR FAR * szProcName,
SWORD cbProcName)
{
-char *func="SQLProcedures";
+static char *func="SQLProcedures";
+
+ mylog("%s: entering...\n", func);
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
UCHAR FAR * szTableName,
SWORD cbTableName)
{
-char *func="SQLTablePrivileges";
+static char *func="SQLTablePrivileges";
+
+ mylog("%s: entering...\n", func);
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
--- /dev/null
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
#ifndef _IODBC_H
#define _IODBC_H
-# if !defined(WINDOWS) && !defined(WIN32_SYSTEM)
+# if !defined(WIN32) && !defined(WIN32_SYSTEM)
# define _UNIX_
# include
# endif /* _UNIX_ */
-# if defined(WINDOWS) || defined(WIN32_SYSTEM)
+# if defined(WIN32) || defined(WIN32_SYSTEM)
# include
# include
# define STREQ(a, b) (_fstrcmp((char FAR*)(a), (char FAR*)(b) == 0)
# endif
-# endif /* WINDOWS */
+# endif /* WIN32 */
# define SYSERR (-1)
#include
#include
+#include
#include "psqlodbc.h"
+#ifndef WIN32
+#if HAVE_PWD_H
+#endif
+#include
+#include
+#else
+#include
/* Byron: is this where Windows keeps def. of getpid ? */
+#endif
extern GLOBAL_VALUES globals;
+void generate_filename(char*,char*,char*);
+void
+generate_filename(char* dirname,char* prefix,char* filename)
+{
+ int pid = 0;
+#ifndef WIN32
+ struct passwd *ptr = 0;
+ ptr = getpwuid(getuid());
+#endif
+ pid = getpid();
+ if(dirname == 0 || filename == 0)
+ return;
+
+ strcpy(filename,dirname);
+ strcat(filename,DIRSEPERATOR);
+ if(prefix != 0)
+ strcat(filename,prefix);
+#ifndef WIN32
+ strcat(filename,ptr->pw_name);
+#endif
+ sprintf(filename,"%s%d%s",filename,pid,".log");
+ return;
+}
#ifdef MY_LOG
{
char *fmt;
char *args;
-
-static FILE *LOGFP = 0;
+char filebuf[80];
+ FILE* LOGFP = globals.mylogFP;
if ( globals.debug) {
va_start(args);
fmt = va_arg(args, char *);
if (! LOGFP) {
- LOGFP = fopen(MYLOGFILE, "w");
+ generate_filename(MYLOGDIR,MYLOGFILE,filebuf);
+ LOGFP = fopen(filebuf, "w");
+ globals.mylogFP = LOGFP;
setbuf(LOGFP, NULL);
}
{
char *fmt;
char *args;
-static FILE *LOGFP = 0;
+char filebuf[80];
+FILE* LOGFP = globals.qlogFP;
if ( globals.commlog) {
va_start(args);
fmt = va_arg(args, char *);
+
if (! LOGFP) {
- LOGFP = fopen(QLOGFILE, "w");
+ generate_filename(QLOGDIR,QLOGFILE,filebuf);
+ LOGFP = fopen(filebuf, "w");
+ globals.qlogFP = LOGFP;
setbuf(LOGFP, NULL);
}
/* Undefine these because windows.h will redefine and cause a warning */
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifndef UNIX
+#ifdef WIN32
#undef va_start
#undef va_end
#endif
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#else
#define __MISC_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef UNIX
+#ifndef WIN32
#include "gpps.h"
#define SQLGetPrivateProfileString(a,b,c,d,e,f) GetPrivateProfileString(a,b,c,d,e,f)
#endif
portion of the registry. You may have to manually add this key.
This logfile is intended for development use, not for an end user!
*/
-// #define MY_LOG
+#define MY_LOG
/* Uncomment Q_LOG to compile in the qlog() statements (Communications log, i.e. CommLog).
#ifdef MY_LOG
-#ifdef UNIX
-#define MYLOGFILE "/tmp/mylog.log"
+#define MYLOGFILE "mylog_"
+#ifndef WIN32
+#define MYLOGDIR "/tmp"
#else
-#define MYLOGFILE "c:\\mylog.log"
+#define MYLOGDIR "c:"
#endif
void mylog(); /* prototype */
#else
#endif
#ifdef Q_LOG
-#ifdef UNIX
-#define QLOGFILE "/tmp/psqlodbc.log"
+#define QLOGFILE "psqlodbc_"
+#ifndef WIN32
+#define QLOGDIR "/tmp"
#else
-#define QLOGFILE "c:\\psqlodbc.log"
+#define QLOGDIR "c:"
#endif
void qlog(); /* prototype */
#else
#define qlog // qlog
#endif
+#ifndef WIN32
+#define DIRSEPERATOR "/"
+#else
+#define DIRSEPERATOR "\\"
+#endif
+
void remove_newlines(char *string);
char *strncpy_null(char *dst, const char *src, int len);
char *trim(char *string);
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "psqlodbc.h"
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
UWORD fOption,
UDWORD vParam)
{
-char *func="SQLSetConnectOption";
+static char *func="SQLSetConnectOption";
ConnectionClass *conn = (ConnectionClass *) hdbc;
+ mylog("%s: entering...\n", func);
+
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
char option[64];
conn->errormsg = "Driver does not support setting this connect option";
conn->errornumber = CONN_UNSUPPORTED_OPTION;
- sprintf(option, "fOption=%d, vParam=%d", fOption, vParam);
+ sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
CC_log_error(func, option, conn);
return SQL_ERROR;
}
UWORD fOption,
PTR pvParam)
{
-char *func="SQLGetConnectOption";
+static char *func="SQLGetConnectOption";
ConnectionClass *conn = (ConnectionClass *) hdbc;
+ mylog("%s: entering...\n", func);
+
if (! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
UWORD fOption,
UDWORD vParam)
{
-char *func="SQLSetStmtOption";
+static char *func="SQLSetStmtOption";
StatementClass *stmt = (StatementClass *) hstmt;
char changed = FALSE;
+ mylog("%s: entering...\n", func);
+
// thought we could fake Access out by just returning SQL_SUCCESS
// all the time, but it tries to set a huge value for SQL_MAX_LENGTH
// and expects the driver to reduce it to the real value
char option[64];
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support setting this statement option";
- sprintf(option, "fOption=%d, vParam=%d", fOption, vParam);
+ sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
SC_log_error(func, option, stmt);
return SQL_ERROR;
}
UWORD fOption,
PTR pvParam)
{
-char *func="SQLGetStmtOption";
+static char *func="SQLGetStmtOption";
StatementClass *stmt = (StatementClass *) hstmt;
+ mylog("%s: entering...\n", func);
+
// thought we could fake Access out by just returning SQL_SUCCESS
// all the time, but it tries to set a huge value for SQL_MAX_LENGTH
// and expects the driver to reduce it to the real value
#include
#include
+#include
#include "statement.h"
#include "connection.h"
#include "qresult.h"
#include "pgtypes.h"
-#ifdef UNIX
-#if !HAVE_STRICMP
+#ifndef WIN32
+#ifndef HAVE_STRICMP
#define stricmp(s1,s2) strcasecmp(s1,s2)
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#endif
#define TAB_INCR 8
#define COL_INCR 16
+char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
+void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
+char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
+
char *
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
{
break;
}
- if ( ispunct(s[i])) {
+ if ( ispunct(s[i]) && s[i] != '_') {
+ mylog("got ispunct: s[%d] = '%c'\n", i, s[i]);
+
if (out == 0) {
token[out++] = s[i++];
break;
char
parse_statement(StatementClass *stmt)
{
+static char *func="parse_statement";
char token[256];
char delim, quote, dquote, numeric, unquoted;
char *ptr;
char in_select = FALSE, in_distinct = FALSE, in_on = FALSE, in_from = FALSE, in_where = FALSE, in_table = FALSE;
char in_field = FALSE, in_expr = FALSE, in_func = FALSE, in_dot = FALSE, in_as = FALSE;
-int j, i, k, n, blevel = 0;
+int j, i, k = 0, n, blevel = 0;
FIELD_INFO **fi;
TABLE_INFO **ti;
char parse;
RETCODE result;
+ mylog("%s: entering...\n", func);
+
ptr = stmt->statement;
fi = stmt->fi;
ti = stmt->ti;
stmt->nfld = 0;
stmt->ntab = 0;
- while (ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) {
+ while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL) {
unquoted = ! ( quote || dquote );
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "psqlodbc.h"
#include "connection.h"
#include "qresult.h"
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
extern GLOBAL_VALUES globals;
+Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
+
/* these are the types we support. all of the pgtype_ functions should */
/* return values for each one of these. */
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "psqlodbc.h"
#include "dlg_specific.h"
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#include "isqlext.h"
GLOBAL_VALUES globals;
-#ifndef UNIX /* again find a WINDOWS #ifdef */
+BOOL _init(void);
+BOOL _fini(void);
+RETCODE SQL_API SQLDummyOrdinal(void);
+
+#ifdef WIN32
HINSTANCE NEAR s_hModule; /* Saved module handle. */
/* This is where the Driver Manager attaches to this Driver */
return FALSE;
}
- getGlobalDefaults();
+ getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE);
break;
case DLL_THREAD_ATTACH:
UNREFERENCED_PARAMETER(lpReserved);
}
-#else /* UNIX */
+#else /* WIN32 */
#ifndef TRUE
#define TRUE (BOOL)1
BOOL
_init(void)
{
- getGlobalDefaults();
+ getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE);
return TRUE;
}
#define __PSQLODBC_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef UNIX
+#include /* for FILE* pointers: see GLOBAL_VALUES */
+
+#ifndef WIN32
#define Int4 long int
#define UInt4 unsigned int
#define Int2 short
/* Driver stuff */
#define DRIVERNAME "PostgreSQL ODBC"
#define DBMS_NAME "PostgreSQL"
-#define DBMS_VERSION "06.30.0248 PostgreSQL 6.3"
-#define POSTGRESDRIVERVERSION "06.30.0248"
+#define DBMS_VERSION "06.30.0250 PostgreSQL 6.3"
+#define POSTGRESDRIVERVERSION "06.30.0250"
-#ifndef UNIX
+#ifdef WIN32
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
#else
#define DRIVER_FILE_NAME "libpsqlodbc.so"
char parse;
char extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
char conn_settings[LARGE_REGISTRY_LEN];
+ FILE* mylogFP;
+ FILE* qlogFP;
} GLOBAL_VALUES;
#define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not including null term) */
-
#include "misc.h"
#endif
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 6,30,2,48
- PRODUCTVERSION 6,30,2,48
+ FILEVERSION 6,30,2,50
+ PRODUCTVERSION 6,30,2,50
FILEFLAGSMASK 0x3L
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "Comments", "PostgreSQL ODBC driver for Windows 95\0"
VALUE "CompanyName", "Insight Distribution Systems\0"
VALUE "FileDescription", "PostgreSQL Driver\0"
- VALUE "FileVersion", " 6.30.0248\0"
+ VALUE "FileVersion", " 6.30.0250\0"
VALUE "InternalName", "psqlodbc\0"
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
VALUE "OriginalFilename", "psqlodbc.dll\0"
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
- VALUE "ProductVersion", " 6.30.0248\0"
+ VALUE "ProductVersion", " 6.30.0250\0"
END
END
BLOCK "VarFileInfo"
SOCK_get_n_char(sock, buffer, len);
buffer[len] = '\0';
- // mylog("qresult: len=%d, buffer='%s'\n", len, buffer);
+ mylog("qresult: len=%d, buffer='%s'\n", len, buffer);
this_tuplefield[field_lf].len = len;
this_tuplefield[field_lf].value = buffer;
/* These functions are for retrieving data from the qresult */
#define QR_get_value_manual(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno))
#define QR_get_value_backend(self, fieldno) (self->tupleField[fieldno].value)
-#define QR_get_value_backend_row(self, tupleno, fieldno) \
- ((self->backend_tuples + (tupleno * self->num_fields))[fieldno].value)
+#define QR_get_value_backend_row(self, tupleno, fieldno) ((self->backend_tuples + (tupleno * self->num_fields))[fieldno].value)
/* These functions are used by both manual and backend results */
#define QR_NumResultCols(self) (CI_get_num_fields(self->fields))
#define QR_get_status(self) (self->status)
// Core Functions
-QResultClass *QR_Constructor();
+QResultClass *QR_Constructor(void);
void QR_Destructor(QResultClass *self);
char QR_read_tuple(QResultClass *self, char binary);
int QR_next_tuple(QResultClass *self);
baby into a database column, even if you will fill up your server's hard disk after a while!
+
+III. Using Row Versioning feature and creating the missing equals operator
+
+In order to use row versioning, you must overload the int4eq function for use
+with the xid type. Also, you need to create an operator to compare xid to int4.
+You must do this for each database you want to use this feature on.
+Here are the details:
+
+create function int4eq(xid,int4)
+ returns bool
+ as ''
+ language 'internal';
+
+create operator = (
+ leftarg=xid,
+ rightarg=int4,
+ procedure=int4eq,
+ commutator='=',
+ negator='<>',
+ restrict=eqsel,
+ join=eqjoinsel
+ );
+
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include
#include
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isqlext.h"
#else
extern GLOBAL_VALUES globals;
-RETCODE SQL_API SQLFetch(HSTMT hstmt)
-{
- return _SQLFetch(hstmt);
-}
-
-RETCODE SQL_API SQLGetData(
- HSTMT hstmt,
- UWORD icol,
- SWORD fCType,
- PTR rgbValue,
- SDWORD cbValueMax,
- SDWORD FAR *pcbValue)
-{
- return _SQLGetData(hstmt, icol, fCType, rgbValue, cbValueMax, pcbValue);
-}
RETCODE SQL_API SQLRowCount(
HSTMT hstmt,
SDWORD FAR *pcrow)
{
-char *func="SQLRowCount";
+static char *func="SQLRowCount";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
char *msg, *ptr;
HSTMT hstmt,
SWORD FAR *pccol)
{
-char *func="SQLNumResultCols";
+static char *func="SQLNumResultCols";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *result;
char parse_ok;
SWORD FAR *pibScale,
SWORD FAR *pfNullable)
{
-char *func="SQLDescribeCol";
+static char *func="SQLDescribeCol";
/* gets all the information about a specific column */
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *result;
-char *col_name;
-Int4 fieldtype;
-int precision;
+char *col_name = NULL;
+Int4 fieldtype = 0;
+int precision = 0;
ConnInfo *ci;
char parse_ok;
+ mylog("%s: entering...\n", func);
+
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
SC_clear_error(stmt);
- if(icol < 1) {
- // we do not support bookmarks
- stmt->errormsg = "Bookmarks are not currently supported.";
- stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
+ /* Dont check for bookmark column. This is the responsibility
+ of the driver manager.
+ */
icol--; /* use zero based column numbers */
SWORD FAR *pcbDesc,
SDWORD FAR *pfDesc)
{
-char *func = "SQLColAttributes";
+static char *func = "SQLColAttributes";
StatementClass *stmt = (StatementClass *) hstmt;
char *value;
-Int4 field_type;
+Int4 field_type = 0;
ConnInfo *ci;
int unknown_sizes;
-int cols;
+int cols = 0;
char parse_ok;
+ mylog("%s: entering...\n", func);
if( ! stmt) {
SC_log_error(func, "", NULL);
ci = &(stmt->hdbc->connInfo);
- if(icol < 1) {
- // we do not support bookmarks
- stmt->errormsg = "Bookmarks are not currently supported.";
- stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
+ /* Dont check for bookmark column. This is the responsibility
+ of the driver manager. For certain types of arguments, the column
+ number is ignored anyway, so it may be 0.
+ */
icol--;
cols = stmt->nfld;
+ /* Column Count is a special case. The Column number is ignored
+ in this case.
+ */
+ if (fDescType == SQL_COLUMN_COUNT) {
+ if (pfDesc)
+ *pfDesc = cols;
+
+ return SQL_SUCCESS;
+ }
+
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) {
if (icol >= cols) {
}
cols = QR_NumResultCols(stmt->result);
+
+ /* Column Count is a special case. The Column number is ignored
+ in this case.
+ */
+ if (fDescType == SQL_COLUMN_COUNT) {
+ if (pfDesc)
+ *pfDesc = cols;
+
+ return SQL_SUCCESS;
+ }
+
if (icol >= cols) {
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in DescribeCol.";
*pfDesc = pgtype_case_sensitive(stmt, field_type);
break;
- case SQL_COLUMN_COUNT:
- if (pfDesc)
- *pfDesc = cols;
- break;
+ /* This special case is handled above.
+
+ case SQL_COLUMN_COUNT:
+ */
case SQL_COLUMN_DISPLAY_SIZE:
if (pfDesc) {
// Returns result data for a single column in the current row.
-RETCODE SQL_API _SQLGetData(
+RETCODE SQL_API SQLGetData(
HSTMT hstmt,
UWORD icol,
SWORD fCType,
SDWORD cbValueMax,
SDWORD FAR *pcbValue)
{
-char *func="SQLGetData";
+static char *func="SQLGetData";
QResultClass *res;
StatementClass *stmt = (StatementClass *) hstmt;
int num_cols, num_rows;
// Returns data for bound columns in the current row ("hstmt->iCursor"),
// advances the cursor.
-RETCODE SQL_API _SQLFetch(
+RETCODE SQL_API SQLFetch(
HSTMT hstmt)
{
-char *func = "SQLFetch";
+static char *func = "SQLFetch";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
int retval;
ColumnInfoClass *ci;
// TupleField *tupleField;
+mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
+
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
return SQL_ERROR;
}
- mylog("manual_result = %d, use_declarefetch = %d\n",
- stmt->manual_result, globals.use_declarefetch);
+ mylog("manual_result = %d, use_declarefetch = %d\n", stmt->manual_result, globals.use_declarefetch);
if ( stmt->manual_result || ! globals.use_declarefetch) {
for (lf=0; lf < num_cols; lf++) {
- mylog("fetch: cols=%d, lf=%d, stmt = %u, stmt->bindings = %u, buffer[] = %u\n",
- num_cols, lf, stmt, stmt->bindings, stmt->bindings[lf].buffer);
+ mylog("fetch: cols=%d, lf=%d, stmt = %u, stmt->bindings = %u, buffer[] = %u\n", num_cols, lf, stmt, stmt->bindings, stmt->bindings[lf].buffer);
if (stmt->bindings[lf].buffer != NULL) {
// this column has a binding
mylog("type = %d\n", type);
- if (stmt->manual_result)
+ if (stmt->manual_result) {
value = QR_get_value_manual(res, stmt->currTuple, lf);
+ mylog("manual_result\n");
+ }
else if (globals.use_declarefetch)
value = QR_get_value_backend(res, lf);
else {
mylog("copy_and_convert: retval = %d\n", retval);
- // check whether the complete result was copied
- if(retval == COPY_UNSUPPORTED_TYPE) {
+
+ switch(retval) {
+ case COPY_OK:
+ break; /* OK, do next bound column */
+
+ case COPY_UNSUPPORTED_TYPE:
stmt->errormsg = "Received an unsupported type from Postgres.";
stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
- } else if(retval == COPY_UNSUPPORTED_CONVERSION) {
+ case COPY_UNSUPPORTED_CONVERSION:
stmt->errormsg = "Couldn't handle the necessary data type conversion.";
stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
- } else if(retval == COPY_RESULT_TRUNCATED) {
- /* The result has been truncated during the copy */
- /* this will generate a SQL_SUCCESS_WITH_INFO result */
+ case COPY_RESULT_TRUNCATED:
stmt->errornumber = STMT_TRUNCATED;
- stmt->errormsg = "A buffer was too small for the return value to fit in";
+ stmt->errormsg = "The buffer was too small for the result.";
return SQL_SUCCESS_WITH_INFO;
- } else if(retval != COPY_OK) {
+ case COPY_GENERAL_ERROR: /* error msg already filled in */
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
+
+ case COPY_NO_DATA_FOUND:
+ SC_log_error(func, "no data found", stmt);
+ return SQL_NO_DATA_FOUND;
+
+ default:
stmt->errormsg = "Unrecognized return value from copy_and_convert_field.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
-
}
}
}
UDWORD FAR *pcrow,
UWORD FAR *rgfRowStatus)
{
-char *func = "SQLExtendedFetch";
+static char *func = "SQLExtendedFetch";
StatementClass *stmt = (StatementClass *) hstmt;
int num_tuples;
RETCODE result;
UWORD fOption,
UWORD fLock)
{
-char *func = "SQLSetPos";
+static char *func = "SQLSetPos";
char buf[128];
sprintf(buf, "SQLSetPos not implemented: irow=%d, fOption=%d, fLock=%d\n", irow, fOption, fLock);
SDWORD crowKeyset,
UWORD crowRowset)
{
-char *func = "SQLSetScrollOptions";
+static char *func = "SQLSetScrollOptions";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
UCHAR FAR *szCursor,
SWORD cbCursor)
{
-char *func="SQLSetCursorName";
+static char *func="SQLSetCursorName";
StatementClass *stmt = (StatementClass *) hstmt;
int len;
-mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n",
- hstmt, szCursor, cbCursor);
+mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n", hstmt, szCursor, cbCursor);
if ( ! stmt) {
SC_log_error(func, "", NULL);
SWORD cbCursorMax,
SWORD FAR *pcbCursor)
{
-char *func="SQLGetCursorName";
+static char *func="SQLGetCursorName";
StatementClass *stmt = (StatementClass *) hstmt;
-mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n",
- hstmt, szCursor, cbCursorMax, pcbCursor);
+mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor);
if ( ! stmt) {
SC_log_error(func, "", NULL);
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "socket.h"
-#ifdef UNIX
+#ifndef WIN32
#include
-#include
-#include
#include /* for memset */
#endif
#define __SOCKET_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef UNIX
+#ifndef WIN32
#include
#include
#include
#include
#include
#define closesocket(xxx) close(xxx)
#define SOCKETFD int
#else
/* Socket prototypes */
-SocketClass *SOCK_Constructor();
+SocketClass *SOCK_Constructor(void);
void SOCK_Destructor(SocketClass *self);
char SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname);
void SOCK_get_n_char(SocketClass *self, char *buffer, int len);
*/
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
#include "statement.h"
#include
#include
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#else
extern GLOBAL_VALUES globals;
-#ifdef UNIX
-#if !HAVE_STRICMP
+#ifndef WIN32
+#ifndef HAVE_STRICMP
#define stricmp(s1,s2) strcasecmp(s1,s2)
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#endif
RETCODE SQL_API SQLAllocStmt(HDBC hdbc,
HSTMT FAR *phstmt)
{
- return _SQLAllocStmt(hdbc, phstmt);
-}
-
-RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
- UWORD fOption)
-{
- return _SQLFreeStmt(hstmt, fOption);
-}
-
-
-RETCODE SQL_API _SQLAllocStmt(HDBC hdbc,
- HSTMT FAR *phstmt)
-{
-char *func="SQLAllocStmt";
+static char *func="SQLAllocStmt";
ConnectionClass *conn = (ConnectionClass *) hdbc;
StatementClass *stmt;
+ mylog("%s: entering...\n", func);
+
if( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
-RETCODE SQL_API _SQLFreeStmt(HSTMT hstmt,
+RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
UWORD fOption)
{
-char *func="SQLFreeStmt";
+static char *func="SQLFreeStmt";
StatementClass *stmt = (StatementClass *) hstmt;
- mylog("**** enter SQLFreeStmt: hstmt=%u, fOption=%d\n", hstmt, fOption);
+ mylog("%s: entering...hstmt=%u, fOption=%d\n", func, hstmt, fOption);
if ( ! stmt) {
SC_log_error(func, "", NULL);
SC_unbind_cols(stmt);
} else if (fOption == SQL_CLOSE) {
- ConnectionClass *conn = stmt->hdbc;
-
/* this should discard all the results, but leave the statement */
/* itself in place (it can be executed again) */
if (!SC_recycle_statement(stmt)) {
*/
StatementClass *
-SC_Constructor()
+SC_Constructor(void)
{
StatementClass *rv;
{
ConnectionClass *conn;
+mylog("recycle statement: self= %u\n", self);
+
/* This would not happen */
if (self->status == STMT_EXECUTING) {
self->errornumber = STMT_SEQUENCE_ERROR;
RETCODE SC_execute(StatementClass *self)
{
-char *func="SC_execute";
+static char *func="SC_execute";
ConnectionClass *conn;
QResultClass *res;
char ok, was_ok, was_nonfatal;
/* The reason is because we can't use declare/fetch cursors without
starting a transaction first.
*/
- if ( ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
+ if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
mylog(" about to begin a transaction on statement = %u\n", self);
res = CC_send_query(conn, "BEGIN", NULL, NULL);
self->result = CC_send_query(conn, self->stmt_with_params, NULL, NULL);
// If we are in autocommit, we must send the commit.
- if (CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
+ if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
CC_send_query(conn, "COMMIT", NULL, NULL);
CC_set_no_trans(conn);
}
self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Error while executing the query";
}
- CC_abort(conn);
+
+ if ( ! self->internal)
+ CC_abort(conn);
}
if (self->errornumber == STMT_OK)
{
if (self) {
qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
+ mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
qlog(" ------------------------------------------------------------\n");
qlog(" hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, self->result);
qlog(" manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);
#define __STATEMENT_H__
#ifdef HAVE_CONFIG_H
-#include
+#include "config.h"
#endif
-#ifdef HAVE_IODBC
+#ifndef WIN32
#include "iodbc.h"
#include "isql.h"
#else
#define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
/* Statement prototypes */
-StatementClass *SC_Constructor();
+StatementClass *SC_Constructor(void);
char SC_Destructor(StatementClass *self);
int statement_type(char *statement);
char parse_statement(StatementClass *stmt);
void SC_free_params(StatementClass *self, char option);
void SC_log_error(char *func, char *desc, StatementClass *self);
-RETCODE SQL_API _SQLAllocStmt(HDBC hdbc, HSTMT FAR *phstmt);
-RETCODE SQL_API _SQLFreeStmt(HSTMT hstmt, UWORD fOption);
-RETCODE SQL_API _SQLExecDirect(HSTMT hstmt, UCHAR FAR *szSqlStr, SDWORD cbSqlStr);
-RETCODE SQL_API _SQLFetch(HSTMT hstmt);
-RETCODE SQL_API _SQLGetData(
- HSTMT hstmt,
- UWORD icol,
- SWORD fCType,
- PTR rgbValue,
- SDWORD cbValueMax,
- SDWORD FAR *pcbValue);
#endif
void set_tuplefield_null(TupleField *tuple_field)
{
tuple_field->len = 0;
- tuple_field->value = strdup("");
+ tuple_field->value = NULL; // strdup("");
}
void set_tuplefield_string(TupleField *tuple_field, char *string)
{
char buffer[10];
+
sprintf(buffer,"%d", value);
tuple_field->len = strlen(buffer)+1;
but these handle automatic NULL determination and call set_tuplefield_null()
if appropriate for the datatype (used by SQLGetTypeInfo).
*/
-#define set_nullfield_string(FLD, VAL) (VAL ? set_tuplefield_string(FLD, VAL) : set_tuplefield_null(FLD))
-#define set_nullfield_int2(FLD, VAL) (VAL != -1 ? set_tuplefield_int2(FLD, VAL) : set_tuplefield_null(FLD))
-#define set_nullfield_int4(FLD, VAL) (VAL != -1 ? set_tuplefield_int4(FLD, VAL) : set_tuplefield_null(FLD))
+#define set_nullfield_string(FLD, VAL) ((VAL) ? set_tuplefield_string(FLD, (VAL)) : set_tuplefield_null(FLD))
+#define set_nullfield_int2(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int2(FLD, (VAL)) : set_tuplefield_null(FLD))
+#define set_nullfield_int4(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int4(FLD, (VAL)) : set_tuplefield_null(FLD))
void set_tuplefield_null(TupleField *tuple_field);
void set_tuplefield_string(TupleField *tuple_field, char *string);