Back out all ODBC formatting changes, and back out removal of <6.4

protocol. I have left in Tom's SOCK_get_next_byte() fix, and the new
win32.mak file addition.  I have also left in the 'X' connection close
fix.
This commit is contained in:
Bruce Momjian 2001-02-14 05:45:46 +00:00
parent 18b04ae131
commit 594e97b72f
45 changed files with 9580 additions and 11060 deletions

View File

@ -2,7 +2,7 @@
#
# GNUMakefile for psqlodbc (Postgres ODBC driver)
#
# $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/GNUmakefile,v 1.12 2001/02/10 16:51:40 petere Exp $
# $Header: /cvsroot/pgsql/src/interfaces/odbc/Attic/GNUmakefile,v 1.13 2001/02/14 05:45:38 momjian Exp $
#
#-------------------------------------------------------------------------
@ -24,6 +24,7 @@ OBJS = info.o bind.o columninfo.o connection.o convert.o drvconn.o \
gpps.o tuple.o tuplelist.o dlg_specific.o $(OBJX)
SHLIB_LINK = $(filter -lm, $(LIBS))
all: all-lib
# Shared library stuff
@ -32,7 +33,6 @@ include $(top_srcdir)/src/Makefile.shlib
# Symbols must be resolved to the version in the shared library because
# the driver manager (e.g., iodbc) provides some symbols with the same
# names and we don't want those. (This issue is probably ELF specific.)
LINK.shared += $(shlib_symbolic)
odbc_headers = isql.h isqlext.h iodbc.h

View File

@ -1,3 +1,4 @@
/* Module: bind.c
*
* Description: This module contains routines related to binding
@ -35,8 +36,7 @@
/* Bind parameters on a statement handle */
RETCODE SQL_API
SQLBindParameter(
RETCODE SQL_API SQLBindParameter(
HSTMT hstmt,
UWORD ipar,
SWORD fParamType,
@ -53,24 +53,20 @@ SQLBindParameter(
mylog( "%s: entering...\n", func);
if (!stmt)
{
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (stmt->parameters_allocated < ipar)
{
if(stmt->parameters_allocated < ipar) {
ParameterInfoClass *old_parameters;
int i,
old_parameters_allocated;
int i, old_parameters_allocated;
old_parameters = stmt->parameters;
old_parameters_allocated = stmt->parameters_allocated;
stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass)*(ipar));
if (!stmt->parameters)
{
if ( ! stmt->parameters) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Could not allocate memory for statement parameters";
SC_log_error(func, "", stmt);
@ -80,8 +76,7 @@ SQLBindParameter(
stmt->parameters_allocated = ipar;
/* copy the old parameters over */
for (i = 0; i < old_parameters_allocated; i++)
{
for(i = 0; i < old_parameters_allocated; i++) {
/* a structure copy should work */
stmt->parameters[i] = old_parameters[i];
}
@ -90,13 +85,9 @@ SQLBindParameter(
if(old_parameters)
free(old_parameters);
/*
* zero out the newly allocated parameters (in case they skipped
* some,
*/
/* zero out the newly allocated parameters (in case they skipped some, */
/* so we don't accidentally try to use them later) */
for (; i < stmt->parameters_allocated; i++)
{
for(; i < stmt->parameters_allocated; i++) {
stmt->parameters[i].buflen = 0;
stmt->parameters[i].buffer = 0;
stmt->parameters[i].used = 0;
@ -112,8 +103,7 @@ SQLBindParameter(
}
}
ipar--; /* use zero based column numbers for the
* below part */
ipar--; /* use zero based column numbers for the below part */
/* store the given info */
stmt->parameters[ipar].buflen = cbValueMax;
@ -125,18 +115,15 @@ SQLBindParameter(
stmt->parameters[ipar].precision = cbColDef;
stmt->parameters[ipar].scale = ibScale;
/*
* If rebinding a parameter that had data-at-exec stuff in it, then
* free that stuff
/* If rebinding a parameter that had data-at-exec stuff in it,
then free that stuff
*/
if (stmt->parameters[ipar].EXEC_used)
{
if (stmt->parameters[ipar].EXEC_used) {
free(stmt->parameters[ipar].EXEC_used);
stmt->parameters[ipar].EXEC_used = NULL;
}
if (stmt->parameters[ipar].EXEC_buffer)
{
if (stmt->parameters[ipar].EXEC_buffer) {
if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY)
free(stmt->parameters[ipar].EXEC_buffer);
stmt->parameters[ipar].EXEC_buffer = NULL;
@ -156,8 +143,7 @@ SQLBindParameter(
/* - - - - - - - - - */
/* Associate a user-supplied buffer with a database column. */
RETCODE SQL_API
SQLBindCol(
RETCODE SQL_API SQLBindCol(
HSTMT hstmt,
UWORD icol,
SWORD fCType,
@ -172,8 +158,7 @@ SQLBindCol(
mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
@ -181,8 +166,7 @@ SQLBindCol(
SC_clear_error(stmt);
if (stmt->status == STMT_EXECUTING)
{
if( stmt->status == STMT_EXECUTING) {
stmt->errormsg = "Can't bind columns while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
@ -190,18 +174,15 @@ SQLBindCol(
}
/* If the bookmark column is being bound, then just save it */
if (icol == 0)
{
if (rgbValue == NULL)
{
if (icol == 0) {
if (rgbValue == NULL) {
stmt->bookmark.buffer = NULL;
stmt->bookmark.used = NULL;
}
else
{
else {
/* Make sure it is the bookmark data type */
if (fCType != SQL_C_BOOKMARK)
{
if ( fCType != SQL_C_BOOKMARK) {
stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
SC_log_error(func, "", stmt);
@ -222,30 +203,25 @@ SQLBindCol(
extend_bindings(stmt, icol);
/* check to see if the bindings were allocated */
if (!stmt->bindings)
{
if ( ! stmt->bindings) {
stmt->errormsg = "Could not allocate memory for bindings.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
icol--; /* use zero based col numbers from here
* out */
icol--; /* use zero based col numbers from here out */
/* Reset for SQLGetData */
stmt->bindings[icol].data_left = -1;
if (rgbValue == NULL)
{
if (rgbValue == NULL) {
/* we have to unbind the column */
stmt->bindings[icol].buflen = 0;
stmt->bindings[icol].buffer = NULL;
stmt->bindings[icol].used = NULL;
stmt->bindings[icol].returntype = SQL_C_CHAR;
}
else
{
} else {
/* ok, bind that column */
stmt->bindings[icol].buflen = cbValueMax;
stmt->bindings[icol].buffer = rgbValue;
@ -267,8 +243,7 @@ SQLBindCol(
/* it is best to say this function is not supported and let the application assume a */
/* data type (most likely varchar). */
RETCODE SQL_API
SQLDescribeParam(
RETCODE SQL_API SQLDescribeParam(
HSTMT hstmt,
UWORD ipar,
SWORD FAR *pfSqlType,
@ -281,14 +256,12 @@ SQLDescribeParam(
mylog( "%s: entering...\n", func);
if (!stmt)
{
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if ((ipar < 1) || (ipar > stmt->parameters_allocated))
{
if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) {
stmt->errormsg = "Invalid parameter number for SQLDescribeParam.";
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
SC_log_error(func, "", stmt);
@ -297,10 +270,7 @@ SQLDescribeParam(
ipar--;
/*
* This implementation is not very good, since it is supposed to
* describe
*/
/* This implementation is not very good, since it is supposed to describe */
/* parameter markers, not bound parameters. */
if(pfSqlType)
*pfSqlType = stmt->parameters[ipar].SQLType;
@ -321,8 +291,7 @@ SQLDescribeParam(
/* Sets multiple values (arrays) for the set of parameter markers. */
RETCODE SQL_API
SQLParamOptions(
RETCODE SQL_API SQLParamOptions(
HSTMT hstmt,
UDWORD crow,
UDWORD FAR *pirow)
@ -344,8 +313,7 @@ SQLParamOptions(
/* like it does for SQLDescribeParam is that some applications don't care and try */
/* to call it anyway. */
/* If the statement does not have parameters, it should just return 0. */
RETCODE SQL_API
SQLNumParams(
RETCODE SQL_API SQLNumParams(
HSTMT hstmt,
SWORD FAR *pcpar)
{
@ -356,37 +324,32 @@ SQLNumParams(
mylog( "%s: entering...\n", func);
if (!stmt)
{
if(!stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (pcpar)
*pcpar = 0;
else
{
else {
SC_log_error(func, "pcpar was null", stmt);
return SQL_ERROR;
}
if (!stmt->statement)
{
if(!stmt->statement) {
/* no statement has been allocated */
stmt->errormsg = "SQLNumParams called with no statement ready.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
else
{
for (i = 0; i < strlen(stmt->statement); i++)
{
} else {
for(i=0; i < strlen(stmt->statement); i++) {
if(stmt->statement[i] == '?' && !in_quote)
(*pcpar)++;
else
{
else {
if (stmt->statement[i] == '\'')
in_quote = (in_quote ? FALSE : TRUE);
}
@ -406,11 +369,11 @@ create_empty_bindings(int num_columns)
int i;
new_bindings = (BindInfoClass *)malloc(num_columns * sizeof(BindInfoClass));
if (!new_bindings)
if(!new_bindings) {
return 0;
}
for (i = 0; i < num_columns; i++)
{
for(i=0; i < num_columns; i++) {
new_bindings[i].buflen = 0;
new_bindings[i].buffer = NULL;
new_bindings[i].used = NULL;
@ -431,15 +394,13 @@ extend_bindings(StatementClass *stmt, int num_columns)
/* if we have too few, allocate room for more, and copy the old */
/* entries into the new structure */
if (stmt->bindings_allocated < num_columns)
{
if(stmt->bindings_allocated < num_columns) {
new_bindings = create_empty_bindings(num_columns);
if (!new_bindings)
{
if ( ! new_bindings) {
mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, stmt->bindings_allocated);
if (stmt->bindings)
{
if (stmt->bindings) {
free(stmt->bindings);
stmt->bindings = NULL;
}
@ -447,8 +408,7 @@ extend_bindings(StatementClass *stmt, int num_columns)
return;
}
if (stmt->bindings)
{
if(stmt->bindings) {
for(i=0; i<stmt->bindings_allocated; i++)
new_bindings[i] = stmt->bindings[i];
@ -457,6 +417,7 @@ extend_bindings(StatementClass *stmt, int num_columns)
stmt->bindings = new_bindings;
stmt->bindings_allocated = num_columns;
}
/* There is no reason to zero out extra bindings if there are */
/* more than needed. If an app has allocated extra bindings, */

View File

@ -15,24 +15,18 @@
/*
* BindInfoClass -- stores information about a bound column
*/
struct BindInfoClass_
{
struct BindInfoClass_ {
Int4 buflen; /* size of buffer */
Int4 data_left; /* amount of data left to read
* (SQLGetData) */
Int4 data_left; /* amount of data left to read (SQLGetData) */
char *buffer; /* pointer to the buffer */
Int4 *used; /* used space in the buffer (for strings
* not counting the '\0') */
Int2 returntype; /* kind of conversion to be applied when
* returning (SQL_C_DEFAULT,
* SQL_C_CHAR...) */
Int4 *used; /* used space in the buffer (for strings not counting the '\0') */
Int2 returntype; /* kind of conversion to be applied when returning (SQL_C_DEFAULT, SQL_C_CHAR...) */
};
/*
* ParameterInfoClass -- stores information about a bound parameter
*/
struct ParameterInfoClass_
{
struct ParameterInfoClass_ {
Int4 buflen;
char *buffer;
Int4 *used;
@ -42,8 +36,7 @@ struct ParameterInfoClass_
UInt4 precision;
Int2 scale;
Oid lobj_oid;
Int4 *EXEC_used; /* amount of data OR the oid of the large
* object */
Int4 *EXEC_used; /* amount of data OR the oid of the large object */
char *EXEC_buffer; /* the data or the FD of the large object */
char data_at_exec;
};

View File

@ -1,3 +1,4 @@
/* Module: columninfo.c
*
* Description: This module contains routines related to
@ -24,8 +25,7 @@ CI_Constructor()
rv = (ColumnInfoClass *) malloc(sizeof(ColumnInfoClass));
if (rv)
{
if (rv) {
rv->num_fields = 0;
rv->name = NULL;
rv->adtid = NULL;
@ -69,21 +69,20 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
mylog("num_fields = %d\n", new_num_fields);
if (self)
{ /* according to that allocate memory */
if (self) { /* according to that allocate memory */
CI_set_num_fields(self, new_num_fields);
}
/* now read in the descriptions */
for (lf = 0; lf < new_num_fields; lf++)
{
for(lf = 0; lf < new_num_fields; lf++) {
SOCK_get_string(sock, new_field_name, MAX_MESSAGE_LEN);
new_adtid = (Oid) SOCK_get_int(sock, 4);
new_adtsize = (Int2) SOCK_get_int(sock, 2);
/* If 6.4 protocol, then read the atttypmod field */
if (PG_VERSION_GE(conn, 6.4))
{
if (PG_VERSION_GE(conn, 6.4)) {
mylog("READING ATTTYPMOD\n");
new_atttypmod = (Int4) SOCK_get_int(sock, 4);
@ -91,6 +90,7 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
new_atttypmod -= 4;
if (new_atttypmod < 0)
new_atttypmod = -1;
}
mylog("CI_read_fields: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d\n", new_field_name, new_adtid, new_adtsize, new_atttypmod);
@ -110,8 +110,7 @@ CI_free_memory(ColumnInfoClass *self)
register Int2 lf;
int num_fields = self->num_fields;
for (lf = 0; lf < num_fields; lf++)
{
for (lf = 0; lf < num_fields; lf++) {
if( self->name[lf])
free (self->name[lf]);
}
@ -143,9 +142,11 @@ void
CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod)
{
/* check bounds */
if ((field_num < 0) || (field_num >= self->num_fields))
if((field_num < 0) || (field_num >= self->num_fields)) {
return;
}
/* store the info */
self->name[field_num] = strdup(new_name);
@ -155,3 +156,4 @@ CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
self->display_size[field_num] = 0;
}

View File

@ -12,8 +12,7 @@
#include "psqlodbc.h"
struct ColumnInfoClass_
{
struct ColumnInfoClass_ {
Int2 num_fields;
char **name; /* list of type names */
Oid *adtid; /* list of type ids */

File diff suppressed because it is too large Load Diff

View File

@ -27,14 +27,11 @@
#endif
typedef enum
{
typedef enum {
CONN_NOT_CONNECTED, /* Connection has not been established */
CONN_CONNECTED, /* Connection is up and has been
* established */
CONN_CONNECTED, /* Connection is up and has been established */
CONN_DOWN, /* Connection is broken */
CONN_EXECUTING /* the connection is currently executing a
* statement */
CONN_EXECUTING /* the connection is currently executing a statement */
} CONN_Status;
/* These errors have general sql error state */
@ -109,8 +106,10 @@ typedef unsigned int ProtocolVersion;
#define PG_PROTOCOL(major, minor) (((major) << 16) | (minor))
#define PG_PROTOCOL_LATEST PG_PROTOCOL(2, 0)
#define PG_PROTOCOL_63 PG_PROTOCOL(1, 0)
#define PG_PROTOCOL_62 PG_PROTOCOL(0, 0)
/* This startup packet is to support latest Postgres protocol */
/* This startup packet is to support latest Postgres protocol (6.4, 6.3) */
typedef struct _StartupPacket
{
ProtocolVersion protoVersion;
@ -122,11 +121,22 @@ typedef struct _StartupPacket
} StartupPacket;
/* This startup packet is to support pre-Postgres 6.3 protocol */
typedef struct _StartupPacket6_2
{
unsigned int authtype;
char database[PATH_SIZE];
char user[NAMEDATALEN];
char options[ARGV_SIZE];
char execfile[ARGV_SIZE];
char tty[PATH_SIZE];
} StartupPacket6_2;
/* Structure to hold all the connection attributes for a specific
connection (used for both registry and file, DSN and DRIVER)
*/
typedef struct
{
typedef struct {
char dsn[MEDIUM_REGISTRY_LEN];
char desc[MEDIUM_REGISTRY_LEN];
char driver[MEDIUM_REGISTRY_LEN];
@ -147,6 +157,12 @@ typedef struct
char focus_password;
} ConnInfo;
/* Macro to determine is the connection using 6.2 protocol? */
#define PROTOCOL_62(conninfo_) (strncmp((conninfo_)->protocol, PG62, strlen(PG62)) == 0)
/* Macro to determine is the connection using 6.3 protocol? */
#define PROTOCOL_63(conninfo_) (strncmp((conninfo_)->protocol, PG63, strlen(PG63)) == 0)
/*
* Macros to compare the server's version with a specified version
* 1st parameter: pointer to a ConnectionClass object
@ -184,8 +200,7 @@ typedef struct
#define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver))
/* This is used to store cached table information in the connection */
struct col_info
{
struct col_info {
QResultClass *result;
char name[MAX_TABLE_LEN+1];
};
@ -222,10 +237,8 @@ typedef BOOL (FAR WINAPI * DriverToDataSourceProc) (UDWORD,
SWORD FAR *);
/******* The Connection handle ************/
struct ConnectionClass_
{
HENV henv; /* environment this connection was created
* on */
struct ConnectionClass_ {
HENV henv; /* environment this connection was created on */
StatementOptions stmtOptions;
char *errormsg;
int errornumber;
@ -241,13 +254,9 @@ struct ConnectionClass_
HINSTANCE translation_handle;
DataSourceToDriverProc DataSourceToDriver;
DriverToDataSourceProc DriverToDataSource;
char transact_status;/* Is a transaction is currently in
* progress */
char errormsg_created; /* has an informative error msg
* been created? */
char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL
* we're connected to -
* DJP 25-1-2001 */
char transact_status; /* Is a transaction is currently in progress */
char errormsg_created; /* has an informative error msg been created? */
char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL we're connected to - DJP 25-1-2001 */
float pg_version_number;
Int2 pg_version_major;
Int2 pg_version_minor;

File diff suppressed because it is too large Load Diff

View File

@ -20,8 +20,7 @@
#define COPY_GENERAL_ERROR 4
#define COPY_NO_DATA_FOUND 5
typedef struct
{
typedef struct {
int m;
int d;
int y;

View File

@ -1,3 +1,4 @@
/* Module: dlg_specific.c
*
* Description: This module contains any specific code for handling
@ -49,13 +50,8 @@ extern GLOBAL_VALUES globals;
void
SetDlgStuff(HWND hdlg, ConnInfo *ci)
{
/*
* If driver attribute NOT present, then set the datasource name and
* description
*/
if (ci->driver[0] == '\0')
{
/* If driver attribute NOT present, then set the datasource name and description */
if (ci->driver[0] == '\0') {
SetDlgItemText(hdlg, IDC_DSNAME, ci->dsn);
SetDlgItemText(hdlg, IDC_DESC, ci->desc);
}
@ -81,14 +77,12 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci)
int CALLBACK
driver_optionsProc(HWND hdlg,
int CALLBACK driver_optionsProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (wMsg)
{
switch (wMsg) {
case WM_INITDIALOG:
CheckDlgButton(hdlg, DRV_COMMLOG, globals.commlog);
@ -99,8 +93,7 @@ driver_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, globals.use_declarefetch);
/* Unknown (Default) Data Type sizes */
switch (globals.unknown_sizes)
{
switch(globals.unknown_sizes) {
case UNKNOWNS_AS_DONTKNOW:
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
break;
@ -133,8 +126,7 @@ driver_optionsProc(HWND hdlg,
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDOK:
globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
@ -164,8 +156,7 @@ driver_optionsProc(HWND hdlg,
globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE);
globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE);
globals.max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for
* SQL_NO_TOTAL */
globals.max_longvarchar_size= GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for SQL_NO_TOTAL */
GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, sizeof(globals.extra_systable_prefixes));
@ -195,8 +186,7 @@ driver_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0);
CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0);
CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0);
switch (DEFAULT_UNKNOWNSIZES)
{
switch(DEFAULT_UNKNOWNSIZES) {
case UNKNOWNS_AS_DONTKNOW:
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
break;
@ -223,13 +213,13 @@ driver_optionsProc(HWND hdlg,
break;
}
}
return FALSE;
}
int CALLBACK
ds_optionsProc(HWND hdlg,
int CALLBACK ds_optionsProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam)
@ -237,8 +227,7 @@ ds_optionsProc(HWND hdlg,
ConnInfo *ci;
char buf[128];
switch (wMsg)
{
switch (wMsg) {
case WM_INITDIALOG:
ci = (ConnInfo *) lParam;
SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK */
@ -246,8 +235,7 @@ ds_optionsProc(HWND hdlg,
/* Change window caption */
if (ci->driver[0])
SetWindowText(hdlg, "Advanced Options (Connection)");
else
{
else {
sprintf(buf, "Advanced Options (%s)", ci->dsn);
SetWindowText(hdlg, buf);
}
@ -256,6 +244,11 @@ ds_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DS_READONLY, atoi(ci->onlyread));
/* Protocol */
if (strncmp(ci->protocol, PG62, strlen(PG62)) == 0)
CheckDlgButton(hdlg, DS_PG62, 1);
else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
CheckDlgButton(hdlg, DS_PG63, 1);
else /* latest */
CheckDlgButton(hdlg, DS_PG64, 1);
@ -273,8 +266,7 @@ ds_optionsProc(HWND hdlg,
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case DS_SHOWOIDCOLUMN:
mylog("WM_COMMAND: DS_SHOWOIDCOLUMN\n");
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
@ -290,6 +282,11 @@ ds_optionsProc(HWND hdlg,
sprintf(ci->onlyread, "%d", IsDlgButtonChecked(hdlg, DS_READONLY));
/* Protocol */
if ( IsDlgButtonChecked(hdlg, DS_PG62))
strcpy(ci->protocol, PG62);
else if ( IsDlgButtonChecked(hdlg, DS_PG63))
strcpy(ci->protocol, PG63);
else /* latest */
strcpy(ci->protocol, PG64);
sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
@ -350,6 +347,7 @@ makeConnectString(char *connect_string, ConnInfo *ci)
void
copyAttributes(ConnInfo *ci, char *attribute, char *value)
{
if(stricmp(attribute, "DSN") == 0)
strcpy(ci->dsn, value);
@ -389,13 +387,13 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0)
strcpy(ci->show_system_tables, value);
else if (stricmp(attribute, INI_CONNSETTINGS) == 0)
{
else if (stricmp(attribute, INI_CONNSETTINGS) == 0) {
decode(value, ci->conn_settings);
/* strcpy(ci->conn_settings, value); */
}
mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server,ci->database,ci->username,ci->password,ci->port,ci->onlyread,ci->protocol,ci->conn_settings);
}
void
@ -432,8 +430,7 @@ getDSNinfo(ConnInfo *ci, char overwrite)
/* If a driver keyword was present, then dont use a DSN and return. */
/* If DSN is null and no driver, then use the default datasource. */
if (DSN[0] == '\0')
{
if ( DSN[0] == '\0') {
if ( ci->driver[0] != '\0')
return;
else
@ -441,8 +438,7 @@ getDSNinfo(ConnInfo *ci, char overwrite)
}
/* brute-force chop off trailing blanks... */
while (*(DSN + strlen(DSN) - 1) == ' ')
*(DSN + strlen(DSN) - 1) = '\0';
while (*(DSN+strlen(DSN)-1) == ' ') *(DSN+strlen(DSN)-1) = '\0';
/* Proceed with getting info for the given DSN. */
@ -482,8 +478,7 @@ getDSNinfo(ConnInfo *ci, char overwrite)
if ( ci->protocol[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_PROTOCOL, "", ci->protocol, sizeof(ci->protocol), ODBC_INI);
if (ci->conn_settings[0] == '\0' || overwrite)
{
if ( ci->conn_settings[0] == '\0' || overwrite) {
SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, "", encoded_conn_settings, sizeof(encoded_conn_settings), ODBC_INI);
decode(encoded_conn_settings, ci->conn_settings);
}
@ -517,6 +512,7 @@ getDSNinfo(ConnInfo *ci, char overwrite)
qlog(" translation_dll='%s',translation_option='%s'\n",
ci->translation_dll,
ci->translation_option);
}
@ -599,8 +595,7 @@ writeDSNinfo(ConnInfo *ci)
/* This function reads the ODBCINST.INI portion of
the registry and gets any driver defaults.
*/
void
getGlobalDefaults(char *section, char *filename, char override)
void getGlobalDefaults(char *section, char *filename, char override)
{
char temp[256];
@ -608,8 +603,7 @@ getGlobalDefaults(char *section, char *filename, char override)
/* Fetch Count is stored in driver section */
SQLGetPrivateProfileString(section, INI_FETCH, "",
temp, sizeof(temp), filename);
if (temp[0])
{
if ( temp[0] ) {
globals.fetch_max = atoi(temp);
/* sanity check if using cursors */
if (globals.fetch_max <= 0)
@ -756,11 +750,7 @@ getGlobalDefaults(char *section, char *filename, char override)
globals.bools_as_char = DEFAULT_BOOLSASCHAR;
/* Extra Systable prefixes */
/*
* Use @@@ to distinguish between blank extra prefixes and no key
* entry
*/
/* Use @@@ to distinguish between blank extra prefixes and no key entry */
SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, "@@@",
temp, sizeof(temp), filename);
if ( strcmp(temp, "@@@" ))
@ -772,13 +762,9 @@ getGlobalDefaults(char *section, char *filename, char override)
/* Dont allow override of an override! */
if (!override)
{
if ( ! override) {
/*
* ConnSettings is stored in the driver section and per datasource
* for 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);
@ -790,10 +776,9 @@ getGlobalDefaults(char *section, char *filename, char override)
else
globals.onlyread = DEFAULT_READONLY;
/*
* Default state for future DSN's protocol attribute This isn't a
* real driver option YET. This is more intended for
* customization from the install.
/* Default state for future DSN's protocol attribute
This isn't a real driver option YET. This is more
intended for customization from the install.
*/
SQLGetPrivateProfileString(section, INI_PROTOCOL, "@@@",
temp, sizeof(temp), filename);
@ -801,6 +786,7 @@ getGlobalDefaults(char *section, char *filename, char override)
strcpy(globals.protocol, temp);
else
strcpy(globals.protocol, DEFAULT_PROTOCOL);
}
}
@ -808,8 +794,7 @@ getGlobalDefaults(char *section, char *filename, char override)
/* This function writes any global parameters (that can be manipulated)
to the ODBCINST.INI portion of the registry
*/
void
updateGlobals(void)
void updateGlobals(void)
{
char tmp[128];

View File

@ -44,13 +44,10 @@
#endif /* WIN32 */
#define INI_DSN DBMS_NAME /* Name of default Datasource in
* ini file (not used?) */
#define INI_DSN DBMS_NAME /* Name of default Datasource in ini file (not used?) */
#define INI_KDESC "Description" /* Data source description */
#define INI_SERVER "Servername" /* Name of Server running
* the Postgres service */
#define INI_PORT "Port" /* Port on which the Postmaster is
* listening */
#define INI_SERVER "Servername" /* Name of Server running the Postgres service */
#define INI_PORT "Port" /* Port on which the Postmaster is listening */
#define INI_DATABASE "Database" /* Database Name */
#define INI_USER "Username" /* Default User Name */
#define INI_PASSWORD "Password" /* Default Password */
@ -58,23 +55,17 @@
#define INI_FETCH "Fetch" /* Fetch Max Count */
#define INI_SOCKET "Socket" /* Socket buffer size */
#define INI_READONLY "ReadOnly" /* Database is read only */
#define INI_COMMLOG "CommLog" /* Communication to backend
* logging */
#define INI_COMMLOG "CommLog" /* Communication to backend logging */
#define INI_PROTOCOL "Protocol" /* What protocol (6.2) */
#define INI_OPTIMIZER "Optimizer" /* Use backend genetic optimizer */
#define INI_KSQO "Ksqo" /* Keyset query optimization */
#define INI_CONNSETTINGS "ConnSettings" /* Anything to send to
* backend on successful
* connection */
#define INI_UNIQUEINDEX "UniqueIndex" /* Recognize unique
* indexes */
#define INI_UNKNOWNSIZES "UnknownSizes" /* How to handle unknown
* result set sizes */
#define INI_CONNSETTINGS "ConnSettings" /* Anything to send to backend on successful connection */
#define INI_UNIQUEINDEX "UniqueIndex" /* Recognize unique indexes */
#define INI_UNKNOWNSIZES "UnknownSizes" /* How to handle unknown result set sizes */
#define INI_CANCELASFREESTMT "CancelAsFreeStmt"
#define INI_USEDECLAREFETCH "UseDeclareFetch" /* Use Declare/Fetch
* cursors */
#define INI_USEDECLAREFETCH "UseDeclareFetch" /* Use Declare/Fetch cursors */
/* More ini stuff */
#define INI_TEXTASLONGVARCHAR "TextAsLongVarchar"
@ -99,8 +90,7 @@
/* Connection Defaults */
#define DEFAULT_PORT "5432"
#define DEFAULT_READONLY 1
#define DEFAULT_PROTOCOL "6.4" /* the latest protocol is
* the default */
#define DEFAULT_PROTOCOL "6.4" /* the latest protocol is the default */
#define DEFAULT_USEDECLAREFETCH 0
#define DEFAULT_TEXTASLONGVARCHAR 1
#define DEFAULT_UNKNOWNSASLONGVARCHAR 0
@ -139,7 +129,6 @@ int CALLBACK ds_optionsProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam);
#endif /* WIN32 */
void updateGlobals(void);

View File

@ -1,3 +1,4 @@
/* Module: drvconn.c
*
* Description: This module contains only routines related to
@ -59,14 +60,12 @@ BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LP
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */
#endif
extern GLOBAL_VALUES globals;
RETCODE SQL_API
SQLDriverConnect(
RETCODE SQL_API SQLDriverConnect(
HDBC hdbc,
HWND hwnd,
UCHAR FAR *szConnStrIn,
@ -79,10 +78,8 @@ SQLDriverConnect(
static char *func = "SQLDriverConnect";
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
#ifdef WIN32
RETCODE dialog_result;
#endif
RETCODE result;
char connStrIn[MAX_CONNECT_STRING];
@ -94,8 +91,7 @@ SQLDriverConnect(
mylog("%s: entering...\n", func);
if (!conn)
{
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
@ -125,13 +121,13 @@ dialog:
#endif
ci->focus_password = password_required;
switch (fDriverCompletion)
{
switch(fDriverCompletion) {
#ifdef WIN32
case SQL_DRIVER_PROMPT:
dialog_result = dconn_DoDialog(hwnd, ci);
if (dialog_result != SQL_SUCCESS)
if(dialog_result != SQL_SUCCESS) {
return dialog_result;
}
break;
case SQL_DRIVER_COMPLETE_REQUIRED:
@ -145,12 +141,13 @@ dialog:
ci->server[0] == '\0' ||
ci->database[0] == '\0' ||
ci->port[0] == '\0' ||
password_required)
{
password_required) {
dialog_result = dconn_DoDialog(hwnd, ci);
if (dialog_result != SQL_SUCCESS)
if(dialog_result != SQL_SUCCESS) {
return dialog_result;
}
}
break;
#else
case SQL_DRIVER_PROMPT:
@ -161,17 +158,14 @@ dialog:
break;
}
/*
* Password is not a required parameter unless authentication asks for
* it. For now, I think it's better to just let the application ask
* over and over until a password is entered (the user can always hit
* Cancel to get out)
/* Password is not a required parameter unless authentication asks for it.
For now, I think it's better to just let the application ask over and over until
a password is entered (the user can always hit Cancel to get out)
*/
if( ci->username[0] == '\0' ||
ci->server[0] == '\0' ||
ci->database[0] == '\0' ||
ci->port[0] == '\0')
{
ci->port[0] == '\0') {
/* (password_required && ci->password[0] == '\0')) */
return SQL_NO_DATA_FOUND;
@ -180,16 +174,12 @@ dialog:
/* do the actual connect */
retval = CC_connect(conn, password_required);
if (retval < 0)
{ /* need a password */
if (fDriverCompletion == SQL_DRIVER_NOPROMPT)
{
if (retval < 0) { /* need a password */
if (fDriverCompletion == SQL_DRIVER_NOPROMPT) {
CC_log_error(func, "Need password but Driver_NoPrompt", conn);
return SQL_ERROR; /* need a password but not allowed to
* prompt so error */
return SQL_ERROR; /* need a password but not allowed to prompt so error */
}
else
{
else {
#ifdef WIN32
password_required = TRUE;
goto dialog;
@ -198,8 +188,7 @@ dialog:
#endif
}
}
else if (retval == 0)
{
else if (retval == 0) {
/* error msg filled in above */
CC_log_error(func, "Error from CC_Connect", conn);
return SQL_ERROR;
@ -213,22 +202,18 @@ dialog:
makeConnectString(connStrOut, ci);
len = strlen(connStrOut);
if (szConnStrOut)
{
if(szConnStrOut) {
/*
* Return the completed string to the caller. The correct method
* is to only construct the connect string if a dialog was put up,
* otherwise, it should just copy the connection input string to
* the output. However, it seems ok to just always construct an
* output string. There are possible bad side effects on working
* applications (Access) by implementing the correct behavior,
* anyway.
/* Return the completed string to the caller. The correct method is to
only construct the connect string if a dialog was put up, otherwise,
it should just copy the connection input string to the output.
However, it seems ok to just always construct an output string. There
are possible bad side effects on working applications (Access) by
implementing the correct behavior, anyway.
*/
strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);
if (len >= cbConnStrOutMax)
{
if (len >= cbConnStrOutMax) {
result = SQL_SUCCESS_WITH_INFO;
conn->errornumber = CONN_TRUNCATED;
conn->errormsg = "The buffer was too small for the result.";
@ -247,29 +232,27 @@ dialog:
}
#ifdef WIN32
RETCODE
dconn_DoDialog(HWND hwnd, ConnInfo *ci)
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci)
{
int dialog_result;
mylog("dconn_DoDialog: ci = %u\n", ci);
if (hwnd)
{
if(hwnd) {
dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_CONFIG),
hwnd, dconn_FDriverConnectProc, (LPARAM) ci);
if (!dialog_result || (dialog_result == -1))
if(!dialog_result || (dialog_result == -1)) {
return SQL_NO_DATA_FOUND;
else
} else {
return SQL_SUCCESS;
}
}
return SQL_ERROR;
}
BOOL FAR PASCAL
dconn_FDriverConnectProc(
BOOL FAR PASCAL dconn_FDriverConnectProc(
HWND hdlg,
UINT wMsg,
WPARAM wParam,
@ -277,8 +260,7 @@ dconn_FDriverConnectProc(
{
ConnInfo *ci;
switch (wMsg)
{
switch (wMsg) {
case WM_INITDIALOG:
ci = (ConnInfo *) lParam;
@ -293,8 +275,7 @@ dconn_FDriverConnectProc(
ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE);
SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for
* the "OK" */
SetWindowLong(hdlg, DWL_USER, lParam);/* Save the ConnInfo for the "OK" */
SetDlgStuff(hdlg, ci);
@ -313,8 +294,7 @@ dconn_FDriverConnectProc(
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDOK:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
@ -349,14 +329,10 @@ dconn_FDriverConnectProc(
#endif /* WIN32 */
void
dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
{
char *our_connect_string;
char *pair,
*attribute,
*value,
*equals;
char *pair, *attribute, *value, *equals;
char *strtok_arg;
memset(ci, 0, sizeof(ConnInfo));
@ -366,13 +342,14 @@ dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
mylog("our_connect_string = '%s'\n", our_connect_string);
while (1)
{
while(1) {
pair = strtok(strtok_arg, ";");
if (strtok_arg)
if(strtok_arg) {
strtok_arg = 0;
if (!pair)
}
if(!pair) {
break;
}
equals = strchr(pair, '=');
if ( ! equals)
@ -389,8 +366,10 @@ dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
/* Copy the appropriate value to the conninfo */
copyAttributes(ci, attribute, value);
}
free(our_connect_string);
}

View File

@ -1,3 +1,4 @@
/* Module: environ.c
*
* Description: This module contains routines related to
@ -22,16 +23,14 @@
ConnectionClass *conns[MAX_CONNECTIONS];
RETCODE SQL_API
SQLAllocEnv(HENV FAR *phenv)
RETCODE SQL_API SQLAllocEnv(HENV FAR *phenv)
{
static char *func = "SQLAllocEnv";
mylog("**** in SQLAllocEnv ** \n");
*phenv = (HENV) EN_Constructor();
if (!*phenv)
{
if ( ! *phenv) {
*phenv = SQL_NULL_HENV;
EN_log_error(func, "Error allocating environment", NULL);
return SQL_ERROR;
@ -41,16 +40,14 @@ SQLAllocEnv(HENV FAR *phenv)
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLFreeEnv(HENV henv)
RETCODE SQL_API SQLFreeEnv(HENV henv)
{
static char *func = "SQLFreeEnv";
EnvironmentClass *env = (EnvironmentClass *) henv;
mylog("**** in SQLFreeEnv: env = %u ** \n", env);
if (env && EN_Destructor(env))
{
if (env && EN_Destructor(env)) {
mylog(" ok\n");
return SQL_SUCCESS;
}
@ -62,8 +59,7 @@ SQLFreeEnv(HENV henv)
/* Returns the next SQL error information. */
RETCODE SQL_API
SQLError(
RETCODE SQL_API SQLError(
HENV henv,
HDBC hdbc,
HSTMT hstmt,
@ -78,16 +74,13 @@ SQLError(
mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u\n", henv, hdbc, hstmt);
if (SQL_NULL_HSTMT != hstmt)
{
if (SQL_NULL_HSTMT != hstmt) {
/* CC: return an error of a hstmt */
StatementClass *stmt = (StatementClass *) hstmt;
if (SC_get_error(stmt, &status, &msg))
{
if (SC_get_error(stmt, &status, &msg)) {
mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg)
{
if (NULL == msg) {
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
@ -108,8 +101,7 @@ SQLError(
if (NULL != szSqlState)
switch (status)
{
switch (status) {
/* now determine the SQLSTATE to be returned */
case STMT_TRUNCATED:
strcpy(szSqlState, "01004");
@ -161,8 +153,7 @@ SQLError(
break;
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00"); /* == 'driver not
* capable' */
strcpy(szSqlState, "S1C00"); /* == 'driver not capable' */
break;
case STMT_OPTION_OUT_OF_RANGE_ERROR:
strcpy(szSqlState, "S1092");
@ -212,9 +203,8 @@ SQLError(
}
mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
}
else
{
} else {
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
@ -226,17 +216,14 @@ SQLError(
return SQL_NO_DATA_FOUND;
}
return SQL_SUCCESS;
}
else if (SQL_NULL_HDBC != hdbc)
{
} else if (SQL_NULL_HDBC != hdbc) {
ConnectionClass *conn = (ConnectionClass *) hdbc;
mylog("calling CC_get_error\n");
if (CC_get_error(conn, &status, &msg))
{
if (CC_get_error(conn, &status, &msg)) {
mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg)
{
if (NULL == msg) {
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
@ -255,8 +242,7 @@ SQLError(
*pfNativeError = status;
if (NULL != szSqlState)
switch (status)
{
switch(status) {
case STMT_OPTION_VALUE_CHANGED:
case CONN_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02");
@ -295,11 +281,7 @@ SQLError(
break;
case CONN_TRANSACT_IN_PROGRES:
strcpy(szSqlState, "S1010");
/*
* when the user tries to switch commit mode in a
* transaction
*/
/* when the user tries to switch commit mode in a transaction */
/* -> function sequence error */
break;
case CONN_NO_MEMORY_ERROR:
@ -320,9 +302,8 @@ SQLError(
/* general error */
break;
}
}
else
{
} else {
mylog("CC_Get_error returned nothing.\n");
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
@ -334,16 +315,12 @@ SQLError(
return SQL_NO_DATA_FOUND;
}
return SQL_SUCCESS;
}
else if (SQL_NULL_HENV != henv)
{
EnvironmentClass *env = (EnvironmentClass *) henv;
if (EN_get_error(env, &status, &msg))
{
} else if (SQL_NULL_HENV != henv) {
EnvironmentClass *env = (EnvironmentClass *)henv;
if(EN_get_error(env, &status, &msg)) {
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg)
{
if (NULL == msg) {
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
@ -361,10 +338,8 @@ SQLError(
if (NULL != pfNativeError)
*pfNativeError = status;
if (szSqlState)
{
switch (status)
{
if(szSqlState) {
switch(status) {
case ENV_ALLOC_ERROR:
/* memory allocation failure */
strcpy(szSqlState, "S1001");
@ -375,9 +350,7 @@ SQLError(
break;
}
}
}
else
{
} else {
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
@ -410,14 +383,12 @@ SQLError(
EnvironmentClass
*
EN_Constructor(void)
*EN_Constructor(void)
{
EnvironmentClass *rv;
rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass));
if (rv)
{
if( rv) {
rv->errormsg = 0;
rv->errornumber = 0;
}
@ -438,8 +409,7 @@ EN_Destructor(EnvironmentClass *self)
/* the source--they should not be freed */
/* Free any connections belonging to this environment */
for (lf = 0; lf < MAX_CONNECTIONS; lf++)
{
for (lf = 0; lf < MAX_CONNECTIONS; lf++) {
if (conns[lf] && conns[lf]->henv == self)
rv = rv && CC_Destructor(conns[lf]);
}
@ -451,17 +421,16 @@ EN_Destructor(EnvironmentClass *self)
char
EN_get_error(EnvironmentClass *self, int *number, char **message)
{
if (self && self->errormsg && self->errornumber)
{
if(self && self->errormsg && self->errornumber) {
*message = self->errormsg;
*number = self->errornumber;
self->errormsg = 0;
self->errornumber = 0;
return 1;
}
else
} else {
return 0;
}
}
char
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
@ -470,10 +439,8 @@ EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
for (i = 0; i < MAX_CONNECTIONS; i++)
{
if (!conns[i])
{
for (i = 0; i < MAX_CONNECTIONS; i++) {
if ( ! conns[i]) {
conn->henv = self;
conns[i] = conn;
@ -492,8 +459,7 @@ EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
int i;
for (i = 0; i < MAX_CONNECTIONS; i++)
if (conns[i] == conn && conns[i]->status != CONN_EXECUTING)
{
if (conns[i] == conn && conns[i]->status != CONN_EXECUTING) {
conns[i] = NULL;
return TRUE;
}
@ -504,8 +470,9 @@ EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
void
EN_log_error(char *func, char *desc, EnvironmentClass *self)
{
if (self)
if (self) {
qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
}
else
qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}

View File

@ -29,8 +29,7 @@
#define ENV_ALLOC_ERROR 1
/********** Environment Handle *************/
struct EnvironmentClass_
{
struct EnvironmentClass_ {
char *errormsg;
int errornumber;
};

View File

@ -1,3 +1,4 @@
/* Module: execute.c
*
* Description: This module contains routines related to
@ -39,8 +40,7 @@ extern GLOBAL_VALUES globals;
/* Perform a Prepare on the SQL statement */
RETCODE SQL_API
SQLPrepare(HSTMT hstmt,
RETCODE SQL_API SQLPrepare(HSTMT hstmt,
UCHAR FAR *szSqlStr,
SDWORD cbSqlStr)
{
@ -49,30 +49,24 @@ SQLPrepare(HSTMT hstmt,
mylog( "%s: entering...\n", func);
if (!self)
{
if ( ! self) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/*
* According to the ODBC specs it is valid to call SQLPrepare mulitple
* times. In that case, the bound SQL statement is replaced by the new
* one
/* According to the ODBC specs it is valid to call SQLPrepare mulitple times.
In that case, the bound SQL statement is replaced by the new one
*/
switch (self->status)
{
switch(self->status) {
case STMT_PREMATURE:
mylog("**** SQLPrepare: STMT_PREMATURE, recycle\n");
SC_recycle_statement(self); /* recycle the statement, but do
* not remove parameter bindings */
SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */
break;
case STMT_FINISHED:
mylog("**** SQLPrepare: STMT_FINISHED, recycle\n");
SC_recycle_statement(self); /* recycle the statement, but do
* not remove parameter bindings */
SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */
break;
case STMT_ALLOCATED:
@ -104,8 +98,7 @@ SQLPrepare(HSTMT hstmt,
free(self->statement);
self->statement = make_string(szSqlStr, cbSqlStr, NULL);
if (!self->statement)
{
if ( ! self->statement) {
self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "No memory available to store statement";
SC_log_error(func, "", self);
@ -116,8 +109,7 @@ SQLPrepare(HSTMT hstmt,
self->statement_type = statement_type(self->statement);
/* Check if connection is onlyread (only selects are allowed) */
if (CC_is_onlyread(self->hdbc) && STMT_UPDATE(self))
{
if ( CC_is_onlyread(self->hdbc) && STMT_UPDATE(self)) {
self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Connection is readonly, only select statements are allowed.";
SC_log_error(func, "", self);
@ -133,8 +125,7 @@ SQLPrepare(HSTMT hstmt,
/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
RETCODE SQL_API
SQLExecDirect(
RETCODE SQL_API SQLExecDirect(
HSTMT hstmt,
UCHAR FAR *szSqlStr,
SDWORD cbSqlStr)
@ -145,8 +136,7 @@ SQLExecDirect(
mylog( "%s: entering...\n", func);
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
@ -157,8 +147,7 @@ SQLExecDirect(
/* keep a copy of the un-parametrized statement, in case */
/* they try to execute this statement again */
stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
if (!stmt->statement)
{
if ( ! stmt->statement) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "No memory available to store statement";
SC_log_error(func, "", stmt);
@ -178,8 +167,7 @@ SQLExecDirect(
stmt->statement_type = statement_type(stmt->statement);
/* Check if connection is onlyread (only selects are allowed) */
if (CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt))
{
if ( CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt)) {
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Connection is readonly, only select statements are allowed.";
SC_log_error(func, "", stmt);
@ -195,41 +183,34 @@ SQLExecDirect(
}
/* Execute a prepared SQL statement */
RETCODE SQL_API
SQLExecute(
RETCODE SQL_API SQLExecute(
HSTMT hstmt)
{
static char *func="SQLExecute";
StatementClass *stmt = (StatementClass *) hstmt;
ConnectionClass *conn;
int i,
retval;
int i, retval;
mylog("%s: entering...\n", func);
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func);
return SQL_INVALID_HANDLE;
}
/*
* If the statement is premature, it means we already executed it from
* an SQLPrepare/SQLDescribeCol type of scenario. So just return
* success.
/* If the statement is premature, it means we already executed
it from an SQLPrepare/SQLDescribeCol type of scenario. So
just return success.
*/
if (stmt->prepare && stmt->status == STMT_PREMATURE)
{
if ( stmt->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
{
else {
SC_log_error(func, "", stmt);
mylog("%s: premature statement so return SQL_ERROR\n", func);
return SQL_ERROR;
@ -241,8 +222,7 @@ SQLExecute(
SC_clear_error(stmt);
conn = SC_get_conn(stmt);
if (conn->status == CONN_EXECUTING)
{
if (conn->status == CONN_EXECUTING) {
stmt->errormsg = "Connection is already in use.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
@ -250,8 +230,7 @@ SQLExecute(
return SQL_ERROR;
}
if (!stmt->statement)
{
if ( ! stmt->statement) {
stmt->errornumber = STMT_NO_STMTSTRING;
stmt->errormsg = "This handle does not have a SQL statement stored in it";
SC_log_error(func, "", stmt);
@ -259,21 +238,19 @@ SQLExecute(
return SQL_ERROR;
}
/*
* If SQLExecute is being called again, recycle the statement. Note
* this should have been done by the application in a call to
* SQLFreeStmt(SQL_CLOSE) or SQLCancel.
/* If SQLExecute is being called again, recycle the statement.
Note this should have been done by the application in a call
to SQLFreeStmt(SQL_CLOSE) or SQLCancel.
*/
if (stmt->status == STMT_FINISHED)
{
if (stmt->status == STMT_FINISHED) {
mylog("%s: recycling statement (should have been done by app)...\n", func);
SC_recycle_statement(stmt);
}
/* Check if the statement is in the correct state */
if ((stmt->prepare && stmt->status != STMT_READY) ||
(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
{
(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY)) {
stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
SC_log_error(func, "", stmt);
@ -282,16 +259,13 @@ SQLExecute(
}
/*
* The bound parameters could have possibly changed since the last
* execute of this statement? Therefore check for params and re-copy.
/* The bound parameters could have possibly changed since the last execute
of this statement? Therefore check for params and re-copy.
*/
stmt->data_at_exec = -1;
for (i = 0; i < stmt->parameters_allocated; i++)
{
for (i = 0; i < stmt->parameters_allocated; i++) {
/* Check for data at execution parameters */
if (stmt->parameters[i].data_at_exec == TRUE)
{
if ( stmt->parameters[i].data_at_exec == TRUE) {
if (stmt->data_at_exec < 0)
stmt->data_at_exec = 1;
else
@ -299,11 +273,7 @@ SQLExecute(
}
}
/* If there are some data at execution parameters, return need data */
/*
* SQLParamData and SQLPutData will be used to send params and execute
* the statement.
*/
/* SQLParamData and SQLPutData will be used to send params and execute the statement. */
if (stmt->data_at_exec > 0)
return SQL_NEED_DATA;
@ -320,14 +290,14 @@ SQLExecute(
return SC_execute(stmt);
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLTransact(
RETCODE SQL_API SQLTransact(
HENV henv,
HDBC hdbc,
UWORD fType)
@ -336,43 +306,40 @@ SQLTransact(
extern ConnectionClass *conns[];
ConnectionClass *conn;
QResultClass *res;
char ok,
*stmt_string;
char ok, *stmt_string;
int lf;
mylog("entering %s: hdbc=%u, henv=%u\n", func, hdbc, henv);
if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
{
if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/*
* If hdbc is null and henv is valid, it means transact all
* connections on that henv.
/* If hdbc is null and henv is valid,
it means transact all connections on that henv.
*/
if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV)
{
for (lf = 0; lf < MAX_CONNECTIONS; lf++)
{
if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV) {
for (lf=0; lf <MAX_CONNECTIONS; lf++) {
conn = conns[lf];
if (conn && conn->henv == henv)
if ( SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
return SQL_ERROR;
}
return SQL_SUCCESS;
}
conn = (ConnectionClass *) hdbc;
if (fType == SQL_COMMIT)
if (fType == SQL_COMMIT) {
stmt_string = "COMMIT";
else if (fType == SQL_ROLLBACK)
} else if (fType == SQL_ROLLBACK) {
stmt_string = "ROLLBACK";
else
{
} else {
conn->errornumber = CONN_INVALID_ARGUMENT_NO;
conn->errormsg ="SQLTransact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter";
CC_log_error(func, "", conn);
@ -380,15 +347,14 @@ SQLTransact(
}
/* If manual commit and in transaction, then proceed. */
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
{
if ( ! CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) {
mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string);
res = CC_send_query(conn, stmt_string, NULL);
CC_set_no_trans(conn);
if (!res)
{
if ( ! res) {
/* error msg will be in the connection */
CC_log_error(func, "", conn);
return SQL_ERROR;
@ -397,8 +363,7 @@ SQLTransact(
ok = QR_command_successful(res);
QR_Destructor(res);
if (!ok)
{
if (!ok) {
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -408,54 +373,46 @@ SQLTransact(
/* - - - - - - - - - */
RETCODE SQL_API
SQLCancel(
RETCODE SQL_API SQLCancel(
HSTMT hstmt) /* Statement to cancel. */
{
static char *func="SQLCancel";
StatementClass *stmt = (StatementClass *) hstmt;
RETCODE result;
#ifdef WIN32
HMODULE hmodule;
FARPROC addr;
#endif
mylog( "%s: entering...\n", func);
/* Check if this can handle canceling in the middle of a SQLPutData? */
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/*
* Not in the middle of SQLParamData/SQLPutData so cancel like a
* close.
*/
if (stmt->data_at_exec < 0)
{
/* Not in the middle of SQLParamData/SQLPutData so cancel like a close. */
if (stmt->data_at_exec < 0) {
/*
* MAJOR HACK for Windows to reset the driver manager's cursor
* state: Because of what seems like a bug in the Odbc driver
* manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as
* many applications depend on this behavior. So, this brute
* force method calls the driver manager's function on behalf of
* the application.
/* MAJOR HACK for Windows to reset the driver manager's cursor state:
Because of what seems like a bug in the Odbc driver manager,
SQLCancel does not act like a SQLFreeStmt(CLOSE), as many
applications depend on this behavior. So, this
brute force method calls the driver manager's function on
behalf of the application.
*/
#ifdef WIN32
if (globals.cancel_as_freestmt)
{
if (globals.cancel_as_freestmt) {
hmodule = GetModuleHandle("ODBC32");
addr = GetProcAddress(hmodule, "SQLFreeStmt");
result = addr( (char *) (stmt->phstmt) - 96, SQL_CLOSE);
}
else
else {
result = SQLFreeStmt( hstmt, SQL_CLOSE);
}
#else
result = SQLFreeStmt( hstmt, SQL_CLOSE);
#endif
@ -467,11 +424,7 @@ SQLCancel(
}
/* In the middle of SQLParamData/SQLPutData, so cancel that. */
/*
* Note, any previous data-at-exec buffers will be freed in the
* recycle
*/
/* Note, any previous data-at-exec buffers will be freed in the recycle */
/* if they call SQLExecDirect or SQLExecute again. */
stmt->data_at_exec = -1;
@ -479,6 +432,7 @@ SQLCancel(
stmt->put_data = FALSE;
return SQL_SUCCESS;
}
/* - - - - - - - - - */
@ -486,8 +440,7 @@ SQLCancel(
/* Returns the SQL string as modified by the driver. */
/* Currently, just copy the input string without modification */
/* observing buffer limits and truncation. */
RETCODE SQL_API
SQLNativeSql(
RETCODE SQL_API SQLNativeSql(
HDBC hdbc,
UCHAR FAR *szSqlStrIn,
SDWORD cbSqlStrIn,
@ -504,8 +457,7 @@ SQLNativeSql(
mylog( "%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn);
ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL);
if (!ptr)
{
if ( ! ptr) {
conn->errornumber = CONN_NO_MEMORY_ERROR;
conn->errormsg = "No memory available to store native sql string";
CC_log_error(func, "", conn);
@ -515,12 +467,10 @@ SQLNativeSql(
result = SQL_SUCCESS;
len = strlen(ptr);
if (szSqlStr)
{
if (szSqlStr) {
strncpy_null(szSqlStr, ptr, cbSqlStrMax);
if (len >= cbSqlStrMax)
{
if (len >= cbSqlStrMax) {
result = SQL_SUCCESS_WITH_INFO;
conn->errornumber = STMT_TRUNCATED;
conn->errormsg = "The buffer was too small for the result.";
@ -540,36 +490,31 @@ SQLNativeSql(
/* Supplies parameter data at execution time. Used in conjuction with */
/* SQLPutData. */
RETCODE SQL_API
SQLParamData(
RETCODE SQL_API SQLParamData(
HSTMT hstmt,
PTR FAR *prgbValue)
{
static char *func = "SQLParamData";
StatementClass *stmt = (StatementClass *) hstmt;
int i,
retval;
int i, retval;
mylog( "%s: entering...\n", func);
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated);
if (stmt->data_at_exec < 0)
{
if (stmt->data_at_exec < 0) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No execution-time parameters for this statement";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
if (stmt->data_at_exec > stmt->parameters_allocated)
{
if (stmt->data_at_exec > stmt->parameters_allocated) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Too many execution-time parameters were present";
SC_log_error(func, "", stmt);
@ -577,19 +522,16 @@ SQLParamData(
}
/* close the large object */
if (stmt->lobj_fd >= 0)
{
if ( stmt->lobj_fd >= 0) {
lo_close(stmt->hdbc, stmt->lobj_fd);
/* commit transaction if needed */
if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
{
if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) {
QResultClass *res;
char ok;
res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
if (!res)
{
if (!res) {
stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt);
@ -597,8 +539,7 @@ SQLParamData(
}
ok = QR_command_successful(res);
QR_Destructor(res);
if (!ok)
{
if (!ok) {
stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt);
@ -613,8 +554,7 @@ SQLParamData(
/* Done, now copy the params and then execute the statement */
if (stmt->data_at_exec == 0)
{
if (stmt->data_at_exec == 0) {
retval = copy_statement_with_parameters(stmt);
if (retval != SQL_SUCCESS)
return retval;
@ -624,17 +564,14 @@ SQLParamData(
return SC_execute(stmt);
}
/*
* Set beginning param; if first time SQLParamData is called , start
* at 0. Otherwise, start at the last parameter + 1.
/* Set beginning param; if first time SQLParamData is called , start at 0.
Otherwise, start at the last parameter + 1.
*/
i = stmt->current_exec_param >= 0 ? stmt->current_exec_param+1 : 0;
/* At least 1 data at execution parameter, so Fill in the token value */
for (; i < stmt->parameters_allocated; i++)
{
if (stmt->parameters[i].data_at_exec == TRUE)
{
for ( ; i < stmt->parameters_allocated; i++) {
if (stmt->parameters[i].data_at_exec == TRUE) {
stmt->data_at_exec--;
stmt->current_exec_param = i;
stmt->put_data = FALSE;
@ -651,30 +588,26 @@ SQLParamData(
/* Supplies parameter data at execution time. Used in conjunction with */
/* SQLParamData. */
RETCODE SQL_API
SQLPutData(
RETCODE SQL_API SQLPutData(
HSTMT hstmt,
PTR rgbValue,
SDWORD cbValue)
{
static char *func = "SQLPutData";
StatementClass *stmt = (StatementClass *) hstmt;
int old_pos,
retval;
int old_pos, retval;
ParameterInfoClass *current_param;
char *buffer;
mylog( "%s: entering...\n", func);
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (stmt->current_exec_param < 0)
{
if (stmt->current_exec_param < 0) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Previous call was not SQLPutData or SQLParamData";
SC_log_error(func, "", stmt);
@ -683,16 +616,14 @@ SQLPutData(
current_param = &(stmt->parameters[stmt->current_exec_param]);
if (!stmt->put_data)
{ /* first call */
if ( ! stmt->put_data) { /* first call */
mylog("SQLPutData: (1) cbValue = %d\n", cbValue);
stmt->put_data = TRUE;
current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD));
if (!current_param->EXEC_used)
{
if ( ! current_param->EXEC_used) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (1)";
SC_log_error(func, "", stmt);
@ -706,17 +637,15 @@ SQLPutData(
/* Handle Long Var Binary with Large Objects */
if (current_param->SQLType == SQL_LONGVARBINARY)
{
if ( current_param->SQLType == SQL_LONGVARBINARY) {
/* begin transaction if needed */
if (!CC_is_in_trans(stmt->hdbc))
{
if(!CC_is_in_trans(stmt->hdbc)) {
QResultClass *res;
char ok;
res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
if (!res)
{
if (!res) {
stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt);
@ -724,8 +653,7 @@ SQLPutData(
}
ok = QR_command_successful(res);
QR_Destructor(res);
if (!ok)
{
if (!ok) {
stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt);
@ -737,8 +665,7 @@ SQLPutData(
/* store the oid */
current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
if (current_param->lobj_oid == 0)
{
if (current_param->lobj_oid == 0) {
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt create large object.";
SC_log_error(func, "", stmt);
@ -751,8 +678,7 @@ SQLPutData(
/* store the fd */
stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE);
if (stmt->lobj_fd < 0)
{
if ( stmt->lobj_fd < 0) {
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt open large object for writing.";
SC_log_error(func, "", stmt);
@ -761,27 +687,22 @@ SQLPutData(
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
}
else
{ /* for handling text fields and small
* binaries */
if (cbValue == SQL_NTS)
{
}
else { /* for handling text fields and small binaries */
if (cbValue == SQL_NTS) {
current_param->EXEC_buffer = strdup(rgbValue);
if (!current_param->EXEC_buffer)
{
if ( ! current_param->EXEC_buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (2)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
else
{
else {
current_param->EXEC_buffer = malloc(cbValue + 1);
if (!current_param->EXEC_buffer)
{
if ( ! current_param->EXEC_buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (2)";
SC_log_error(func, "", stmt);
@ -793,28 +714,25 @@ SQLPutData(
}
}
else
{ /* calling SQLPutData more than once */
else { /* calling SQLPutData more than once */
mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);
if (current_param->SQLType == SQL_LONGVARBINARY)
{
if (current_param->SQLType == SQL_LONGVARBINARY) {
/* the large object fd is in EXEC_buffer */
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
*current_param->EXEC_used += cbValue;
}
else
{
} else {
buffer = current_param->EXEC_buffer;
if (cbValue == SQL_NTS)
{
if (cbValue == SQL_NTS) {
buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1);
if (!buffer)
{
if ( ! buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (3)";
SC_log_error(func, "", stmt);
@ -828,9 +746,10 @@ SQLPutData(
/* reassign buffer incase realloc moved it */
current_param->EXEC_buffer = buffer;
}
else if (cbValue > 0)
{
else if (cbValue > 0) {
old_pos = *current_param->EXEC_used;
*current_param->EXEC_used += cbValue;
@ -839,8 +758,7 @@ SQLPutData(
/* dont lose the old pointer in case out of memory */
buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
if (!buffer)
{
if ( ! buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (3)";
SC_log_error(func, "", stmt);
@ -852,12 +770,13 @@ SQLPutData(
/* reassign buffer incase realloc moved it */
current_param->EXEC_buffer = buffer;
}
else
{
else {
SC_log_error(func, "bad cbValue", stmt);
return SQL_ERROR;
}
}
}

View File

@ -40,14 +40,10 @@
DWORD
GetPrivateProfileString(char *theSection, /* section name */
char *theKey, /* search key name */
char *theDefault, /* default value if not
* found */
char *theReturnBuffer, /* return value stored
* here */
size_t theReturnBufferLength, /* byte length of return
* buffer */
char *theIniFileName) /* pathname of ini file to
* search */
char *theDefault, /* default value if not found */
char *theReturnBuffer, /* return value stored here */
size_t theReturnBufferLength, /* byte length of return buffer */
char *theIniFileName) /* pathname of ini file to search */
{
char buf[MAXPGPATH];
char* ptr = 0;
@ -78,10 +74,10 @@ GetPrivateProfileString(char *theSection, /* section name */
if( ptr == NULL || *ptr == '\0' )
ptr = "/home";
/*
* This doesn't make it so we find an ini file but allows normal
* processing to continue further on down. The likelihood is that the
* file won't be found and thus the default value will be returned.
/* This doesn't make it so we find an ini file but allows normal
* processing to continue further on down. The likelihood is that
* the file won't be found and thus the default value will be
* returned.
*/
if( MAXPGPATH-1 < strlen(ptr) + j )
{
@ -93,13 +89,11 @@ GetPrivateProfileString(char *theSection, /* section name */
sprintf( buf, "%s/%s",ptr,theIniFileName );
/*
* This code makes it so that a file in the users home dir overrides a
* the "default" file as passed in
/* This code makes it so that a file in the users home dir
* overrides a the "default" file as passed in
*/
aFile = (FILE*)(buf ? fopen(buf, PG_BINARY_R) : NULL);
if (!aFile)
{
if(!aFile) {
sprintf(buf,"%s",theIniFileName);
aFile = (FILE*)(buf ? fopen(buf, PG_BINARY_R) : NULL);
}
@ -110,7 +104,9 @@ GetPrivateProfileString(char *theSection, /* section name */
if(theReturnBufferLength == 0 || theReturnBuffer == NULL)
{
if(aFile)
{
fclose(aFile);
}
return 0;
}
@ -132,7 +128,9 @@ GetPrivateProfileString(char *theSection, /* section name */
aLineLength = strlen(aLine);
/* strip final '\n' */
if(aLineLength > 0 && aLine[aLineLength - 1] == '\n')
{
aLine[aLineLength - 1] = '\0';
}
switch(*aLine)
{
case ' ': /* blank line */
@ -146,17 +144,17 @@ GetPrivateProfileString(char *theSection, /* section name */
{
aStart = aLine + 1;
aString--;
while (isspace((unsigned char) *aStart))
aStart++;
while (isspace((unsigned char) *aString))
aString--;
while (isspace((unsigned char) *aStart)) aStart++;
while (isspace((unsigned char) *aString)) aString--;
*(aString+1) = '\0';
/* accept as matched if NULL key or exact match */
if(!theSection || !strcmp(aStart, theSection))
{
aSectionFound = TRUE;
}
}
break;
@ -176,24 +174,31 @@ GetPrivateProfileString(char *theSection, /* section name */
/* strip leading blanks in value field */
while(*aValue == ' ' && aValue < aLine + sizeof(aLine))
{
*aValue++ = '\0';
}
if(aValue >= aLine + sizeof(aLine))
{
aValue = "";
}
}
else
{
aValue = "";
}
aStart = aLine;
while (isspace((unsigned char) *aStart))
aStart++;
while (isspace((unsigned char) *aStart)) aStart++;
/* strip trailing blanks from key */
if(aString)
{
while(--aString >= aStart && *aString == ' ')
{
*aString = '\0';
}
}
/* see if key is matched */
@ -272,10 +277,11 @@ GetPrivateProfileString(char *theSection, /* section name */
}
if(aFile)
{
fclose(aFile);
}
if (!aKeyFound)
{ /* key wasn't found return default */
if(!aKeyFound) { /* key wasn't found return default */
++aLength; /* room for NULL char */
aLength = theReturnBufferLength < aLength ?
theReturnBufferLength : aLength;
@ -290,8 +296,7 @@ DWORD
WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */
char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to
* write */
char *theIniFileName) /* pathname of ini file to write */
{
return 0;
}
@ -305,8 +310,7 @@ DWORD
WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */
char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to
* write */
char *theIniFileName) /* pathname of ini file to write */
{
char buf[MAXPGPATH];
char* ptr = 0;
@ -324,12 +328,10 @@ WritePrivateProfileString(char *theSection, /* section name */
/* If this isn't correct processing we'll change it later */
if(theSection == NULL || theKey == NULL || theBuffer == NULL ||
theIniFileName == NULL)
return 0;
theIniFileName == NULL) return 0;
aLength = strlen(theBuffer);
if (aLength == 0)
return 0;
if(aLength == 0) return 0;
j = strlen(theIniFileName) + 1;
ptr = (char*)getpwuid(getuid()); /* get user info */
@ -364,12 +366,10 @@ WritePrivateProfileString(char *theSection, /* section name */
/* overrides a the "default" file as passed in */
/* */
aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL);
if (!aFile)
{
if(!aFile) {
sprintf(buf,"%s",theIniFileName);
aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL);
if (!aFile)
return 0;
if(!aFile) return 0;
}
@ -384,7 +384,9 @@ WritePrivateProfileString(char *theSection, /* section name */
aLineLength = strlen(aLine);
/* strip final '\n' */
if(aLineLength > 0 && aLine[aLineLength - 1] == '\n')
{
aLine[aLineLength - 1] = '\0';
}
switch(*aLine)
{
case ' ': /* blank line */
@ -401,8 +403,10 @@ WritePrivateProfileString(char *theSection, /* section name */
/* accept as matched if key exact match */
if(!strcmp(aLine + 1, theSection))
{
aSectionFound = TRUE;
}
}
break;
@ -422,20 +426,28 @@ WritePrivateProfileString(char *theSection, /* section name */
/* strip leading blanks in value field */
while(*aValue == ' ' && aValue < aLine + sizeof(aLine))
{
*aValue++ = '\0';
}
if(aValue >= aLine + sizeof(aLine))
{
aValue = "";
}
}
else
{
aValue = "";
}
/* strip trailing blanks from key */
if(aString)
{
while(--aString >= aLine && *aString == ' ')
{
*aString = '\0';
}
}
/* see if key is matched */
@ -457,14 +469,14 @@ WritePrivateProfileString(char *theSection, /* section name */
}
}
if (!keyFound)
{ /* theKey wasn't in file so */
if(!keyFound) { /* theKey wasn't in file so */
if(aFile)
{
fclose(aFile);
}
return aReturnLength > 0 ? aReturnLength - 1 : 0;
}
#endif

View File

@ -13,30 +13,25 @@
#endif
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
DWORD GetPrivateProfileString(char *theSection, /* section name */
DWORD
GetPrivateProfileString(char *theSection, /* section name */
char *theKey, /* search key name */
char *theDefault, /* default value if not
* found */
char *theReturnBuffer, /* return valuse stored
* here */
size_t theBufferLength, /* byte length of return
* buffer */
char *theIniFileName); /* pathname of ini file
* to search */
char *theDefault, /* default value if not found */
char *theReturnBuffer, /* return valuse stored here */
size_t theBufferLength, /* byte length of return buffer */
char *theIniFileName); /* pathname of ini file to search */
DWORD WritePrivateProfileString(char *theSection, /* section name */
DWORD
WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */
char *theBuffer, /* input buffer */
char *theIniFileName); /* pathname of ini file
* to write */
char *theIniFileName); /* pathname of ini file to write */
#ifdef __cplusplus
}
#endif
#ifndef WIN32

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ typedef signed short RETCODE;
# define SQL_VARCHAR 12
# define SQL_TYPE_MIN SQL_CHAR
#define SQL_TYPE_NUL 0
# define SQL_TYPE_NULL 0
# define SQL_TYPE_MAX SQL_VARCHAR
/* C to SQL datatype mapping */
@ -133,9 +133,11 @@ extern "C"
{
#endif
RETCODE SQL_API SQLAllocConnect(HENV henv, HDBC FAR *phdbc);
RETCODE SQL_API SQLAllocConnect (HENV henv,
HDBC FAR * phdbc);
RETCODE SQL_API SQLAllocEnv (HENV FAR * phenv);
RETCODE SQL_API SQLAllocStmt(HDBC hdbc, HSTMT FAR *phstmt);
RETCODE SQL_API SQLAllocStmt (HDBC hdbc,
HSTMT FAR * phstmt);
RETCODE SQL_API SQLBindCol (HSTMT hstmt,
UWORD icol,
SWORD fCType,
@ -202,17 +204,22 @@ extern "C"
SWORD cbCursorMax,
SWORD FAR * pcbCursor);
RETCODE SQL_API SQLNumResultCols(HSTMT hstmt, SWORD FAR *pccol);
RETCODE SQL_API SQLNumResultCols (HSTMT hstmt,
SWORD FAR * pccol);
RETCODE SQL_API SQLPrepare(HSTMT hstmt, UCHAR FAR *szSqlStr,
RETCODE SQL_API SQLPrepare (HSTMT hstmt,
UCHAR FAR * szSqlStr,
SDWORD cbSqlStr);
RETCODE SQL_API SQLRowCount(HSTMT hstmt, SDWORD FAR *pcrow);
RETCODE SQL_API SQLRowCount (HSTMT hstmt,
SDWORD FAR * pcrow);
RETCODE SQL_API SQLSetCursorName(HSTMT hstmt, UCHAR FAR *szCursor,
RETCODE SQL_API SQLSetCursorName (HSTMT hstmt,
UCHAR FAR * szCursor,
SWORD cbCursor);
RETCODE SQL_API SQLTransact(HENV henv, HDBC hdbc,
RETCODE SQL_API SQLTransact (HENV henv,
HDBC hdbc,
UWORD fType);
RETCODE SQL_API SQLSetParam (HSTMT hstmt,
@ -226,6 +233,5 @@ extern "C"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -362,41 +362,33 @@ typedef long long int ODBCINT64;
typedef unsigned ODBCINT64 SQLUBIGINT;
typedef ODBCINT64 SQLBIGINT;
#else /* Used even on platforms with 64 bit ints
* but not GCC */
#else /* Used even on platforms with 64 bit ints but not GCC */
typedef struct
{
typedef struct {
SQLUINTEGER dwLowWord;
SQLUINTEGER dwHighWord;
} SQLUBIGINT;
typedef struct
{
typedef struct {
SQLUINTEGER dwLowWord;
SQLINTEGER dwHighWord;
} SQLBIGINT;
#endif /* GCC */
typedef struct tagDATE_STRUCT
{
typedef struct tagDATE_STRUCT {
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
} DATE_STRUCT,
SQL_DATE_STRUCT;
} DATE_STRUCT,SQL_DATE_STRUCT;
typedef struct tagTIME_STRUCT
{
typedef struct tagTIME_STRUCT {
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
} TIME_STRUCT,
SQL_TIME_STRUCT;
} TIME_STRUCT,SQL_TIME_STRUCT;
typedef struct tagTIMESTAMP_STRUCT
{
typedef struct tagTIMESTAMP_STRUCT {
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
@ -404,8 +396,7 @@ typedef struct tagTIMESTAMP_STRUCT
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction;
} TIMESTAMP_STRUCT,
SQL_TIMESTAMP_STRUCT;
} TIMESTAMP_STRUCT,SQL_TIMESTAMP_STRUCT;
/* postodbc doesn't use these but what the heck */
/* Don't know what SQL_MAX_NUMERIC_LEN should be so I can't include this. It's
@ -420,16 +411,14 @@ typedef struct tagSQL_NUMERIC_STRUCT {
*/
typedef struct tagSQLGUID
{
typedef struct tagSQLGUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} SQLGUID;
typedef enum
{
typedef enum {
SQL_IS_YEAR = 1,
SQL_IS_MONTH = 2,
SQL_IS_DAY = 3,
@ -445,14 +434,12 @@ typedef enum
SQL_IS_MINUTE_TO_SECOND = 13
} SQLINTERVAL;
typedef struct tagSQL_YEAR_MONTH
{
typedef struct tagSQL_YEAR_MONTH {
SQLUINTEGER year;
SQLUINTEGER month;
} SQL_YEAR_MONTH_STRUCT;
typedef struct tagSQL_DAY_SECOND
{
typedef struct tagSQL_DAY_SECOND {
SQLUINTEGER day;
SQLUINTEGER hour;
SQLUINTEGER minute;
@ -460,12 +447,10 @@ typedef struct tagSQL_DAY_SECOND
SQLUINTEGER fraction;
} SQL_DAY_SECOND_STRUCT;
typedef struct tagSQL_INTERVAL_STRUCT
{
typedef struct tagSQL_INTERVAL_STRUCT {
SQLINTERVAL interval_type;
SQLSMALLINT interval_sign;
union
{
union {
SQL_YEAR_MONTH_STRUCT year_month;
SQL_DAY_SECOND_STRUCT day_second;
} intval;
@ -1333,8 +1318,7 @@ typedef struct tagSQL_INTERVAL_STRUCT
"VALUE,,VARCHAR,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,YEAR"
# ifdef __cplusplus
extern "C"
{
extern "C" {
# endif
RETCODE SQL_API SQLSetConnectOption (HDBC, UWORD, UDWORD);
@ -1550,7 +1534,6 @@ extern "C"
# ifdef __cplusplus
}
# endif
#endif

View File

@ -1,3 +1,4 @@
/* Module: lobj.c
*
* Description: This module contains routines related to manipulating
@ -19,8 +20,7 @@ Oid
lo_creat(ConnectionClass *conn, int mode)
{
LO_ARG argv[1];
int retval,
result_len;
int retval, result_len;
argv[0].isint = 1;
argv[0].len = 4;
@ -63,8 +63,7 @@ int
lo_close(ConnectionClass *conn, int fd)
{
LO_ARG argv[1];
int retval,
result_len;
int retval, result_len;
argv[0].isint = 1;
@ -76,6 +75,7 @@ lo_close(ConnectionClass *conn, int fd)
else
return retval;
}
@ -105,8 +105,7 @@ int
lo_write(ConnectionClass *conn, int fd, char *buf, int len)
{
LO_ARG argv[2];
int retval,
result_len;
int retval, result_len;
if (len <= 0)
@ -131,8 +130,7 @@ int
lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
{
LO_ARG argv[3];
int retval,
result_len;
int retval, result_len;
argv[0].isint = 1;
@ -158,8 +156,7 @@ int
lo_tell(ConnectionClass *conn, int fd)
{
LO_ARG argv[1];
int retval,
result_len;
int retval, result_len;
argv[0].isint = 1;
@ -177,8 +174,7 @@ int
lo_unlink(ConnectionClass *conn, Oid lobjId)
{
LO_ARG argv[1];
int retval,
result_len;
int retval, result_len;
argv[0].isint = 1;
@ -191,3 +187,11 @@ lo_unlink(ConnectionClass *conn, Oid lobjId)
else
return retval;
}

View File

@ -13,8 +13,7 @@
#include "psqlodbc.h"
struct lo_arg
{
struct lo_arg {
int isint;
int len;
union
@ -46,3 +45,4 @@ int lo_tell(ConnectionClass *conn, int fd);
int lo_unlink(ConnectionClass *conn, Oid lobjId);
#endif

View File

@ -1,3 +1,4 @@
/* Module: misc.c
*
* Description: This module contains miscellaneous routines
@ -24,8 +25,7 @@
#include <sys/types.h>
#include <unistd.h>
#else
#include <process.h> /* Byron: is this where Windows keeps def.
* of getpid ? */
#include <process.h> /* Byron: is this where Windows keeps def. of getpid ? */
#endif
extern GLOBAL_VALUES globals;
@ -35,10 +35,8 @@ void
generate_filename(char* dirname,char* prefix,char* filename)
{
int pid = 0;
#ifndef WIN32
struct passwd *ptr = 0;
ptr = getpwuid(getuid());
#endif
pid = getpid();
@ -65,12 +63,10 @@ mylog(char *fmt,...)
char filebuf[80];
FILE* LOGFP = globals.mylogFP;
if (globals.debug)
{
if ( globals.debug) {
va_start(args, fmt);
if (!LOGFP)
{
if (! LOGFP) {
generate_filename(MYLOGDIR,MYLOGFILE,filebuf);
LOGFP = fopen(filebuf, PG_BINARY_W);
globals.mylogFP = LOGFP;
@ -83,7 +79,6 @@ mylog(char *fmt,...)
va_end(args);
}
}
#endif
@ -96,12 +91,10 @@ qlog(char *fmt,...)
char filebuf[80];
FILE* LOGFP = globals.qlogFP;
if (globals.commlog)
{
if ( globals.commlog) {
va_start(args, fmt);
if (!LOGFP)
{
if (! LOGFP) {
generate_filename(QLOGDIR,QLOGFILE,filebuf);
LOGFP = fopen(filebuf, PG_BINARY_W);
globals.qlogFP = LOGFP;
@ -114,7 +107,6 @@ qlog(char *fmt,...)
va_end(args);
}
}
#endif
/* Undefine these because windows.h will redefine and cause a warning */
@ -144,8 +136,7 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
if (dst_len <= 0)
return STRCPY_FAIL;
if (src_len == SQL_NULL_DATA)
{
if (src_len == SQL_NULL_DATA) {
dst[0] = '\0';
return STRCPY_NULL;
}
@ -155,15 +146,12 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
if (src_len <= 0)
return STRCPY_FAIL;
else
{
if (src_len < dst_len)
{
else {
if (src_len < dst_len) {
memcpy(dst, src, src_len);
dst[src_len] = '\0';
}
else
{
else {
memcpy(dst, src, dst_len-1);
dst[dst_len-1] = '\0'; /* truncated */
return STRCPY_TRUNCATED;
@ -177,29 +165,29 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
/* the destination string if src has len characters or more. */
/* instead, I want it to copy up to len-1 characters and always */
/* terminate the destination string. */
char *
strncpy_null(char *dst, const char *src, int len)
char *strncpy_null(char *dst, const char *src, int len)
{
int i;
if (NULL != dst)
{
if (NULL != dst) {
/* Just in case, check for special lengths */
if (len == SQL_NULL_DATA)
{
if (len == SQL_NULL_DATA) {
dst[0] = '\0';
return NULL;
}
else if (len == SQL_NTS)
len = strlen(src) + 1;
for (i = 0; src[i] && i < len - 1; i++)
for(i = 0; src[i] && i < len - 1; i++) {
dst[i] = src[i];
}
if (len > 0)
if(len > 0) {
dst[i] = '\0';
}
}
return dst;
}
@ -212,12 +200,10 @@ make_string(char *s, int len, char *buf)
int length;
char *str;
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
{
if(s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) {
length = (len > 0) ? len : strlen(s);
if (buf)
{
if (buf) {
strncpy_null(buf, s, length+1);
return buf;
}
@ -240,8 +226,8 @@ make_string(char *s, int len, char *buf)
char *
my_strcat(char *buf, char *fmt, char *s, int len)
{
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
{
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) {
int length = (len > 0) ? len : strlen(s);
int pos = strlen(buf);
@ -252,26 +238,24 @@ my_strcat(char *buf, char *fmt, char *s, int len)
return NULL;
}
void
remove_newlines(char *string)
void remove_newlines(char *string)
{
unsigned int i;
for (i = 0; i < strlen(string); i++)
{
for(i=0; i < strlen(string); i++) {
if((string[i] == '\n') ||
(string[i] == '\r'))
(string[i] == '\r')) {
string[i] = ' ';
}
}
}
char *
trim(char *s)
{
int i;
for (i = strlen(s) - 1; i >= 0; i--)
{
for (i = strlen(s) - 1; i >= 0; i--) {
if (s[i] == ' ')
s[i] = '\0';
else

View File

@ -46,7 +46,6 @@
#define MYLOGDIR "c:"
#endif
extern void mylog(char * fmt, ...);
#else
#ifndef WIN32
#define mylog(args...) /* GNU convention for variable arguments */
@ -63,7 +62,6 @@ extern void mylog(char *fmt,...);
#define QLOGDIR "c:"
#endif
extern void qlog(char * fmt, ...);
#else
#ifndef WIN32
#define qlog(args...) /* GNU convention for variable arguments */

View File

@ -1,3 +1,4 @@
/* Module: options.c
*
* Description: This module contains routines for getting/setting
@ -44,8 +45,7 @@ RETCODE set_statement_option(ConnectionClass *conn,
RETCODE
set_statement_option(ConnectionClass *conn,
RETCODE set_statement_option(ConnectionClass *conn,
StatementClass *stmt,
UWORD fOption,
UDWORD vParam)
@ -54,86 +54,70 @@ set_statement_option(ConnectionClass *conn,
char changed = FALSE;
switch (fOption)
{
switch(fOption) {
case SQL_ASYNC_ENABLE:/* ignored */
break;
case SQL_BIND_TYPE:
/* now support multi-column and multi-row binding */
if (conn)
conn->stmtOptions.bind_size = vParam;
if (stmt)
stmt->options.bind_size = vParam;
if (conn) conn->stmtOptions.bind_size = vParam;
if (stmt) stmt->options.bind_size = vParam;
break;
case SQL_CONCURRENCY:
/* positioned update isn't supported so cursor concurrency is read-only */
/*
* positioned update isn't supported so cursor concurrency is
* read-only
*/
if (conn)
conn->stmtOptions.scroll_concurrency = vParam;
if (stmt)
stmt->options.scroll_concurrency = vParam;
if (conn) conn->stmtOptions.scroll_concurrency = vParam;
if (stmt) stmt->options.scroll_concurrency = vParam;
break;
/*
* if (globals.lie) { if (conn)
* conn->stmtOptions.scroll_concurrency = vParam; if (stmt)
* stmt->options.scroll_concurrency = vParam; } else {
*
* if (conn) conn->stmtOptions.scroll_concurrency =
* SQL_CONCUR_READ_ONLY; if (stmt)
* stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
*
* if (vParam != SQL_CONCUR_READ_ONLY) changed = TRUE; } break;
if (globals.lie) {
if (conn) conn->stmtOptions.scroll_concurrency = vParam;
if (stmt) stmt->options.scroll_concurrency = vParam;
}
else {
if (conn) conn->stmtOptions.scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (stmt) stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (vParam != SQL_CONCUR_READ_ONLY)
changed = TRUE;
}
break;
*/
case SQL_CURSOR_TYPE:
/*
* if declare/fetch, then type can only be forward. otherwise,
* it can only be forward or static.
/* if declare/fetch, then type can only be forward.
otherwise, it can only be forward or static.
*/
mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);
if (globals.lie)
{
if (conn)
conn->stmtOptions.cursor_type = vParam;
if (stmt)
stmt->options.cursor_type = vParam;
if (globals.lie) {
if (conn) conn->stmtOptions.cursor_type = vParam;
if (stmt) stmt->options.cursor_type = vParam;
}
else
{
if (globals.use_declarefetch)
{
if (conn)
conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
if (stmt)
stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
else {
if (globals.use_declarefetch) {
if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
if (stmt) stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
if (vParam != SQL_CURSOR_FORWARD_ONLY)
changed = TRUE;
}
else
{
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
{
if (conn)
conn->stmtOptions.cursor_type = vParam; /* valid type */
if (stmt)
stmt->options.cursor_type = vParam; /* valid type */
else {
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC) {
if (conn) conn->stmtOptions.cursor_type = vParam; /* valid type */
if (stmt) stmt->options.cursor_type = vParam; /* valid type */
}
else
{
if (conn)
conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
if (stmt)
stmt->options.cursor_type = SQL_CURSOR_STATIC;
else {
if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
if (stmt) stmt->options.cursor_type = SQL_CURSOR_STATIC;
changed = TRUE;
}
@ -144,34 +128,32 @@ set_statement_option(ConnectionClass *conn,
case SQL_KEYSET_SIZE: /* ignored, but saved and returned */
mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.keyset_size = vParam;
if (stmt)
stmt->options.keyset_size = vParam;
if (conn) conn->stmtOptions.keyset_size = vParam;
if (stmt) stmt->options.keyset_size = vParam;
break;
/*
* if (globals.lie) stmt->keyset_size = vParam; else {
* stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
* stmt->errormsg = "Driver does not support keyset size
* option"; SC_log_error(func, "", stmt); return SQL_ERROR; }
if (globals.lie)
stmt->keyset_size = vParam;
else {
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support keyset size option";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
*/
case SQL_MAX_LENGTH:/* ignored, but saved */
mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.maxLength = vParam;
if (stmt)
stmt->options.maxLength = vParam;
if (conn) conn->stmtOptions.maxLength = vParam;
if (stmt) stmt->options.maxLength = vParam;
break;
case SQL_MAX_ROWS: /* ignored, but saved */
mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.maxRows = vParam;
if (stmt)
stmt->options.maxRows = vParam;
if (conn) conn->stmtOptions.maxRows = vParam;
if (stmt) stmt->options.maxRows = vParam;
break;
case SQL_NOSCAN: /* ignored */
@ -185,47 +167,39 @@ set_statement_option(ConnectionClass *conn,
case SQL_RETRIEVE_DATA: /* ignored, but saved */
mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.retrieve_data = vParam;
if (stmt)
stmt->options.retrieve_data = vParam;
if (conn) conn->stmtOptions.retrieve_data = vParam;
if (stmt) stmt->options.retrieve_data = vParam;
break;
case SQL_ROWSET_SIZE:
mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam);
/*
* Save old rowset size for SQLExtendedFetch purposes If the
* rowset_size is being changed since the last call to fetch
* rows.
/* Save old rowset size for SQLExtendedFetch purposes
If the rowset_size is being changed since the last call
to fetch rows.
*/
if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0 )
stmt->save_rowset_size = stmt->options.rowset_size;
if (vParam < 1)
{
if (vParam < 1) {
vParam = 1;
changed = TRUE;
}
if (conn)
conn->stmtOptions.rowset_size = vParam;
if (stmt)
stmt->options.rowset_size = vParam;
if (conn) conn->stmtOptions.rowset_size = vParam;
if (stmt) stmt->options.rowset_size = vParam;
break;
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
if (stmt)
{
if (stmt) {
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
SC_log_error(func, "", stmt);
}
if (conn)
{
if (conn) {
conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
conn->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
CC_log_error(func, "", conn);
@ -234,25 +208,21 @@ set_statement_option(ConnectionClass *conn,
case SQL_USE_BOOKMARKS:
if (stmt)
stmt->options.use_bookmarks = vParam;
if (conn)
conn->stmtOptions.use_bookmarks = vParam;
if (stmt) stmt->options.use_bookmarks = vParam;
if (conn) conn->stmtOptions.use_bookmarks = vParam;
break;
default:
{
char option[64];
if (stmt)
{
if (stmt) {
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Unknown statement option (Set)";
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
SC_log_error(func, option, stmt);
}
if (conn)
{
if (conn) {
conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
conn->errormsg = "Unknown statement option (Set)";
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
@ -263,15 +233,12 @@ set_statement_option(ConnectionClass *conn,
}
}
if (changed)
{
if (stmt)
{
if (changed) {
if (stmt) {
stmt->errormsg = "Requested value changed.";
stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
}
if (conn)
{
if (conn) {
conn->errormsg = "Requested value changed.";
conn->errornumber = STMT_OPTION_VALUE_CHANGED;
}
@ -284,8 +251,7 @@ set_statement_option(ConnectionClass *conn,
/* Implements only SQL_AUTOCOMMIT */
RETCODE SQL_API
SQLSetConnectOption(
RETCODE SQL_API SQLSetConnectOption(
HDBC hdbc,
UWORD fOption,
UDWORD vParam)
@ -298,19 +264,15 @@ SQLSetConnectOption(
mylog("%s: entering...\n", func);
if (!conn)
{
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch (fOption)
{
/*
* Statement Options (apply to all stmts on the connection and
* become defaults for new stmts)
switch (fOption) {
/* Statement Options
(apply to all stmts on the connection and become defaults for new stmts)
*/
case SQL_ASYNC_ENABLE:
case SQL_BIND_TYPE:
@ -327,16 +289,13 @@ SQLSetConnectOption(
case SQL_USE_BOOKMARKS:
/* Affect all current Statements */
for (i = 0; i < conn->num_stmts; i++)
{
if (conn->stmts[i])
for (i = 0; i < conn->num_stmts; i++) {
if ( conn->stmts[i]) {
set_statement_option(NULL, conn->stmts[i], fOption, vParam);
}
}
/*
* Become the default for all future statements on this
* connection
*/
/* Become the default for all future statements on this connection */
retval = set_statement_option(conn, NULL, fOption, vParam);
if (retval == SQL_SUCCESS_WITH_INFO)
@ -355,8 +314,7 @@ SQLSetConnectOption(
case SQL_AUTOCOMMIT:
if (CC_is_in_trans(conn))
{
if (CC_is_in_trans(conn)) {
conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
conn->errornumber = CONN_TRANSACT_IN_PROGRES;
CC_log_error(func, "", conn);
@ -365,8 +323,7 @@ SQLSetConnectOption(
mylog("SQLSetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);
switch (vParam)
{
switch(vParam) {
case SQL_AUTOCOMMIT_OFF:
CC_set_autocommit_off(conn);
break;
@ -411,17 +368,16 @@ SQLSetConnectOption(
default:
{
char option[64];
conn->errormsg = "Unknown connect option (Set)";
conn->errornumber = CONN_UNSUPPORTED_OPTION;
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
CC_log_error(func, option, conn);
return SQL_ERROR;
}
}
if (changed)
{
if (changed) {
conn->errornumber = CONN_OPTION_VALUE_CHANGED;
conn->errormsg = "Requested value changed.";
return SQL_SUCCESS_WITH_INFO;
@ -433,8 +389,7 @@ SQLSetConnectOption(
/* - - - - - - - - - */
/* This function just can tell you whether you are in Autcommit mode or not */
RETCODE SQL_API
SQLGetConnectOption(
RETCODE SQL_API SQLGetConnectOption(
HDBC hdbc,
UWORD fOption,
PTR pvParam)
@ -444,14 +399,12 @@ SQLGetConnectOption(
mylog("%s: entering...\n", func);
if (!conn)
{
if (! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch (fOption)
{
switch (fOption) {
case SQL_ACCESS_MODE:/* NOT SUPPORTED */
*((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
break;
@ -495,7 +448,6 @@ SQLGetConnectOption(
default:
{
char option[64];
conn->errormsg = "Unknown connect option (Get)";
conn->errornumber = CONN_UNSUPPORTED_OPTION;
sprintf(option, "fOption=%d", fOption);
@ -503,6 +455,7 @@ SQLGetConnectOption(
return SQL_ERROR;
break;
}
}
return SQL_SUCCESS;
@ -510,8 +463,7 @@ SQLGetConnectOption(
/* - - - - - - - - - */
RETCODE SQL_API
SQLSetStmtOption(
RETCODE SQL_API SQLSetStmtOption(
HSTMT hstmt,
UWORD fOption,
UDWORD vParam)
@ -525,8 +477,7 @@ SQLSetStmtOption(
/* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */
/* and expects the driver to reduce it to the real value */
if (!stmt)
{
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
@ -537,8 +488,7 @@ SQLSetStmtOption(
/* - - - - - - - - - */
RETCODE SQL_API
SQLGetStmtOption(
RETCODE SQL_API SQLGetStmtOption(
HSTMT hstmt,
UWORD fOption,
PTR pvParam)
@ -553,35 +503,29 @@ SQLGetStmtOption(
/* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */
/* and expects the driver to reduce it to the real value */
if (!stmt)
{
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch (fOption)
{
switch(fOption) {
case SQL_GET_BOOKMARK:
case SQL_ROW_NUMBER:
res = stmt->result;
if (stmt->manual_result || !globals.use_declarefetch)
{
if ( stmt->manual_result || ! globals.use_declarefetch) {
/* make sure we're positioned on a valid row */
if((stmt->currTuple < 0) ||
(stmt->currTuple >= QR_get_num_tuples(res)))
{
(stmt->currTuple >= QR_get_num_tuples(res))) {
stmt->errormsg = "Not positioned on a valid row.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
else
{
if (stmt->currTuple == -1 || !res || !res->tupleField)
{
else {
if (stmt->currTuple == -1 || ! res || ! res->tupleField) {
stmt->errormsg = "Not positioned on a valid row.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt);
@ -589,8 +533,7 @@ SQLGetStmtOption(
}
}
if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF)
{
if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF) {
stmt->errormsg = "Operation invalid because use bookmarks not enabled.";
stmt->errornumber = STMT_OPERATION_INVALID;
SC_log_error(func, "", stmt);
@ -660,7 +603,6 @@ SQLGetStmtOption(
default:
{
char option[64];
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Unknown statement option (Get)";
sprintf(option, "fOption=%d", fOption);

View File

@ -1,3 +1,4 @@
/* Module: parse.c
*
* Description: This module contains routines related to parsing SQL statements.
@ -46,8 +47,7 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
{
int i = 0;
int out = 0;
char qc,
in_escape = FALSE;
char qc, in_escape = FALSE;
if (smax <= 1)
return NULL;
@ -55,53 +55,43 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
smax--;
/* skip leading delimiters */
while (isspace((unsigned char) s[i]) || s[i] == ',')
{
while (isspace((unsigned char) s[i]) || s[i] == ',') {
/* mylog("skipping '%c'\n", s[i]); */
i++;
}
if (s[0] == '\0')
{
if (s[0] == '\0') {
token[0] = '\0';
return NULL;
}
if (quote)
*quote = FALSE;
if (dquote)
*dquote = FALSE;
if (numeric)
*numeric = FALSE;
if (quote) *quote = FALSE;
if (dquote) *dquote = FALSE;
if (numeric) *numeric = FALSE;
/* get the next token */
while ( ! isspace((unsigned char) s[i]) && s[i] != ',' &&
s[i] != '\0' && out != smax)
{
s[i] != '\0' && out != smax) {
/* Handle quoted stuff */
if (out == 0 && (s[i] == '\"' || s[i] == '\''))
{
if ( out == 0 && (s[i] == '\"' || s[i] == '\'')) {
qc = s[i];
if (qc == '\"')
{
if (dquote)
*dquote = TRUE;
if (qc == '\"') {
if (dquote) *dquote = TRUE;
}
if (qc == '\'')
{
if (quote)
*quote = TRUE;
if (qc == '\'') {
if (quote) *quote = TRUE;
}
i++; /* dont return the quote */
while (s[i] != '\0' && out != smax)
{
if (s[i] == qc && !in_escape)
while (s[i] != '\0' && out != smax) {
if (s[i] == qc && ! in_escape) {
break;
if (s[i] == '\\' && !in_escape)
}
if (s[i] == '\\' && ! in_escape) {
in_escape = TRUE;
else
{
}
else {
in_escape = FALSE;
token[out++] = s[i];
}
@ -113,10 +103,8 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
}
/* Check for numeric literals */
if (out == 0 && isdigit((unsigned char) s[i]))
{
if (numeric)
*numeric = TRUE;
if ( out == 0 && isdigit((unsigned char) s[i])) {
if (numeric) *numeric = TRUE;
token[out++] = s[i++];
while ( isalnum((unsigned char) s[i]) || s[i] == '.')
token[out++] = s[i++];
@ -124,12 +112,10 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
break;
}
if (ispunct((unsigned char) s[i]) && s[i] != '_')
{
if ( ispunct((unsigned char) s[i]) && s[i] != '_') {
mylog("got ispunct: s[%d] = '%c'\n", i, s[i]);
if (out == 0)
{
if (out == 0) {
token[out++] = s[i++];
break;
}
@ -152,25 +138,20 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
i++;
/* return the most priority delimiter */
if (s[i] == ',')
{
if (delim)
*delim = s[i];
if (s[i] == ',') {
if (delim) *delim = s[i];
}
else if (s[i] == '\0')
{
if (delim)
*delim = '\0';
else if (s[i] == '\0') {
if (delim) *delim = '\0';
}
else
{
if (delim)
*delim = ' ';
else {
if (delim) *delim = ' ';
}
/* skip trailing blanks */
while (isspace((unsigned char) s[i]))
while ( isspace((unsigned char) s[i])) {
i++;
}
return &s[i];
}
@ -215,11 +196,9 @@ searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
char *col;
for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
{
for (k = 0; k < QR_get_num_tuples(col_info->result); k++) {
col = QR_get_value_manual(col_info->result, k, 3);
if (!strcmp(col, fi->name))
{
if ( ! strcmp(col, fi->name)) {
getColInfo(col_info, fi, k);
mylog("PARSE: searchColInfo: \n");
@ -236,28 +215,11 @@ parse_statement(StatementClass *stmt)
{
static char *func="parse_statement";
char token[256];
char delim,
quote,
dquote,
numeric,
unquoted;
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 = 0,
n,
blevel = 0;
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 = 0, n, blevel = 0;
FIELD_INFO **fi;
TABLE_INFO **ti;
char parse;
@ -276,38 +238,34 @@ parse_statement(StatementClass *stmt)
stmt->nfld = 0;
stmt->ntab = 0;
while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
{
while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL) {
unquoted = ! ( quote || dquote );
mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr);
if (unquoted && !stricmp(token, "select"))
{
if ( unquoted && ! stricmp(token, "select")) {
in_select = TRUE;
mylog("SELECT\n");
continue;
}
if (unquoted && in_select && !stricmp(token, "distinct"))
{
if ( unquoted && in_select && ! stricmp(token, "distinct")) {
in_distinct = TRUE;
mylog("DISTINCT\n");
continue;
}
if (unquoted && !stricmp(token, "into"))
{
if ( unquoted && ! stricmp(token, "into")) {
in_select = FALSE;
mylog("INTO\n");
continue;
}
if (unquoted && !stricmp(token, "from"))
{
if ( unquoted && ! stricmp(token, "from")) {
in_select = FALSE;
in_from = TRUE;
@ -319,8 +277,8 @@ parse_statement(StatementClass *stmt)
! stricmp(token, "union") ||
! stricmp(token, "order") ||
! stricmp(token, "group") ||
!stricmp(token, "having")))
{
! stricmp(token, "having"))) {
in_select = FALSE;
in_from = FALSE;
in_where = TRUE;
@ -329,20 +287,17 @@ parse_statement(StatementClass *stmt)
break;
}
if (in_select)
{
if (in_distinct)
{
if (in_select) {
if ( in_distinct) {
mylog("in distinct\n");
if (unquoted && !stricmp(token, "on"))
{
if (unquoted && ! stricmp(token, "on")) {
in_on = TRUE;
mylog("got on\n");
continue;
}
if (in_on)
{
if (in_on) {
in_distinct = FALSE;
in_on = FALSE;
continue; /* just skip the unique on field */
@ -351,30 +306,25 @@ parse_statement(StatementClass *stmt)
in_distinct = FALSE;
}
if (in_expr || in_func)
{ /* just eat the expression */
if ( in_expr || in_func) { /* just eat the expression */
mylog("in_expr=%d or func=%d\n", in_expr, in_func);
if (quote || dquote)
continue;
if (in_expr && blevel == 0 && delim == ',')
{
if (in_expr && blevel == 0 && delim == ',') {
mylog("**** in_expr and Got comma\n");
in_expr = FALSE;
in_field = FALSE;
}
else if (token[0] == '(')
{
else if (token[0] == '(') {
blevel++;
mylog("blevel++ = %d\n", blevel);
}
else if (token[0] == ')')
{
else if (token[0] == ')') {
blevel--;
mylog("blevel-- = %d\n", blevel);
if (delim == ',')
{
if (delim==',') {
in_func = FALSE;
in_expr = FALSE;
in_field = FALSE;
@ -383,17 +333,15 @@ parse_statement(StatementClass *stmt)
continue;
}
if (!in_field)
{
if ( ! in_field) {
if ( ! token[0])
continue;
if (!(stmt->nfld % FLD_INCR))
{
if ( ! (stmt->nfld % FLD_INCR)) {
mylog("reallocing at nfld=%d\n", stmt->nfld);
fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *));
if (!fi)
{
if ( ! fi) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
@ -401,8 +349,7 @@ parse_statement(StatementClass *stmt)
}
fi[stmt->nfld] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO));
if (fi[stmt->nfld] == NULL)
{
if (fi[stmt->nfld] == NULL) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
@ -414,18 +361,15 @@ parse_statement(StatementClass *stmt)
if (dquote)
fi[stmt->nfld]->dquote = TRUE;
if (quote)
{
if (quote) {
fi[stmt->nfld++]->quote = TRUE;
continue;
}
else if (numeric)
{
else if (numeric) {
mylog("**** got numeric: nfld = %d\n", stmt->nfld);
fi[stmt->nfld]->numeric = TRUE;
}
else if (token[0] == '(')
{ /* expression */
else if (token[0] == '(') { /* expression */
mylog("got EXPRESSION\n");
fi[stmt->nfld++]->expr = TRUE;
in_expr = TRUE;
@ -433,17 +377,18 @@ parse_statement(StatementClass *stmt)
continue;
}
else
{
else {
strcpy(fi[stmt->nfld]->name, token);
fi[stmt->nfld]->dot[0] = '\0';
}
mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot);
if (delim == ',')
if (delim == ',') {
mylog("comma (1)\n");
else
}
else {
in_field = TRUE;
}
stmt->nfld++;
continue;
}
@ -451,16 +396,14 @@ parse_statement(StatementClass *stmt)
/**************************/
/* We are in a field now */
/**************************/
if (in_dot)
{
if (in_dot) {
stmt->nfld--;
strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name);
strcpy(fi[stmt->nfld]->name, token);
stmt->nfld++;
in_dot = FALSE;
if (delim == ',')
{
if (delim == ',') {
mylog("in_dot: got comma\n");
in_field = FALSE;
}
@ -468,8 +411,7 @@ parse_statement(StatementClass *stmt)
continue;
}
if (in_as)
{
if (in_as) {
stmt->nfld--;
strcpy(fi[stmt->nfld]->alias, token);
mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias);
@ -478,35 +420,29 @@ parse_statement(StatementClass *stmt)
stmt->nfld++;
if (delim == ',')
if (delim == ',') {
mylog("comma(2)\n");
}
continue;
}
/* Function */
if (token[0] == '(')
{
if (token[0] == '(') {
in_func = TRUE;
blevel = 1;
fi[stmt->nfld-1]->func = TRUE;
/*
* name will have the function name -- maybe useful some
* day
*/
/* name will have the function name -- maybe useful some day */
mylog("**** got function = '%s'\n", fi[stmt->nfld-1]->name);
continue;
}
if (token[0] == '.')
{
if (token[0] == '.') {
in_dot = TRUE;
mylog("got dot\n");
continue;
}
if (!stricmp(token, "as"))
{
if ( ! stricmp(token, "as")) {
in_as = TRUE;
mylog("got AS\n");
continue;
@ -517,28 +453,25 @@ parse_statement(StatementClass *stmt)
fi[stmt->nfld-1]->expr = TRUE;
fi[stmt->nfld-1]->name[0] = '\0';
mylog("*** setting expression\n");
}
if (in_from)
{
if (!in_table)
{
if (in_from) {
if ( ! in_table) {
if ( ! token[0])
continue;
if (!(stmt->ntab % TAB_INCR))
{
if ( ! (stmt->ntab % TAB_INCR)) {
ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *));
if (!ti)
{
if ( ! ti) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
stmt->ti = ti;
}
ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO));
if (ti[stmt->ntab] == NULL)
{
if (ti[stmt->ntab] == NULL) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
@ -548,10 +481,12 @@ parse_statement(StatementClass *stmt)
strcpy(ti[stmt->ntab]->name, token);
mylog("got table = '%s'\n", ti[stmt->ntab]->name);
if (delim == ',')
if (delim == ',') {
mylog("more than 1 tables\n");
else
}
else {
in_table = TRUE;
}
stmt->ntab++;
continue;
}
@ -559,10 +494,11 @@ parse_statement(StatementClass *stmt)
strcpy(ti[stmt->ntab-1]->alias, token);
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab-1]->name, ti[stmt->ntab-1]->alias);
in_table = FALSE;
if (delim == ',')
if (delim == ',') {
mylog("more than 1 tables\n");
}
}
}
/*************************************************/
@ -572,18 +508,16 @@ parse_statement(StatementClass *stmt)
parse = TRUE;
/* Resolve field names with tables */
for (i = 0; i < stmt->nfld; i++)
{
if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
{
for (i = 0; i < stmt->nfld; i++) {
if (fi[i]->func || fi[i]->expr || fi[i]->numeric) {
fi[i]->ti = NULL;
fi[i]->type = -1;
parse = FALSE;
continue;
}
else if (fi[i]->quote)
{ /* handle as text */
else if (fi[i]->quote) { /* handle as text */
fi[i]->ti = NULL;
fi[i]->type = PG_TYPE_TEXT;
fi[i]->precision = 0;
@ -591,17 +525,13 @@ parse_statement(StatementClass *stmt)
}
/* it's a dot, resolve to table or alias */
else if (fi[i]->dot[0])
{
for (k = 0; k < stmt->ntab; k++)
{
if (!stricmp(ti[k]->name, fi[i]->dot))
{
else if (fi[i]->dot[0]) {
for (k = 0; k < stmt->ntab; k++) {
if ( ! stricmp(ti[k]->name, fi[i]->dot)) {
fi[i]->ti = ti[k];
break;
}
else if (!stricmp(ti[k]->alias, fi[i]->dot))
{
else if ( ! stricmp(ti[k]->alias, fi[i]->dot)) {
fi[i]->ti = ti[k];
break;
}
@ -614,15 +544,15 @@ parse_statement(StatementClass *stmt)
mylog("--------------------------------------------\n");
mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab);
for (i = 0; i < stmt->nfld; i++)
{
for (i=0; i < stmt->nfld; i++) {
mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot);
if (fi[i]->ti)
mylog(" ----> table_name='%s', table_alias='%s'\n", fi[i]->ti->name, fi[i]->ti->alias);
}
for (i = 0; i < stmt->ntab; i++)
for (i=0; i < stmt->ntab; i++) {
mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);
}
/******************************************************/
@ -631,28 +561,24 @@ parse_statement(StatementClass *stmt)
/* Call SQLColumns for each table and store the result */
for (i = 0; i < stmt->ntab; i++)
{
for (i = 0; i < stmt->ntab; i++) {
/* See if already got it */
char found = FALSE;
for (k = 0; k < conn->ntables; k++)
{
if (!stricmp(conn->col_info[k]->name, ti[i]->name))
{
for (k = 0; k < conn->ntables; k++) {
if ( ! stricmp(conn->col_info[k]->name, ti[i]->name)) {
mylog("FOUND col_info table='%s'\n", ti[i]->name);
found = TRUE;
break;
}
}
if (!found)
{
if ( ! found) {
mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);
result = SQLAllocStmt( stmt->hdbc, &hcol_stmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = "SQLAllocStmt failed in parse_statement for columns.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->parse_status = STMT_PARSE_FATAL;
@ -666,16 +592,14 @@ parse_statement(StatementClass *stmt)
ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0);
mylog(" Past SQLColumns\n");
if (result == SQL_SUCCESS)
{
if (result == SQL_SUCCESS) {
mylog(" Success\n");
if (!(conn->ntables % COL_INCR))
{
if ( ! (conn->ntables % COL_INCR)) {
mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables);
conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *));
if (!conn->col_info)
{
if ( ! conn->col_info) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
@ -683,22 +607,17 @@ parse_statement(StatementClass *stmt)
mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables);
conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO));
if (!conn->col_info[conn->ntables])
{
if ( ! conn->col_info[conn->ntables]) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
/*
* Store the table name and the SQLColumns result
* structure
*/
/* Store the table name and the SQLColumns result structure */
strcpy(conn->col_info[conn->ntables]->name, ti[i]->name);
conn->col_info[conn->ntables]->result = col_stmt->result;
/*
* The connection will now free the result structures, so
* make sure that the statement doesn't free it
/* The connection will now free the result structures, so make
sure that the statement doesn't free it
*/
col_stmt->result = NULL;
@ -707,8 +626,7 @@ parse_statement(StatementClass *stmt)
SQLFreeStmt(hcol_stmt, SQL_DROP);
mylog("Created col_info table='%s', ntables=%d\n", ti[i]->name, conn->ntables);
}
else
{
else {
SQLFreeStmt(hcol_stmt, SQL_DROP);
break;
}
@ -728,39 +646,34 @@ parse_statement(StatementClass *stmt)
for (i = 0; i < stmt->nfld;)
{
for (i = 0; i < stmt->nfld;) {
/* Dont worry about functions or quotes */
if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
{
if (fi[i]->func || fi[i]->quote || fi[i]->numeric) {
i++;
continue;
}
/* Stars get expanded to all fields in the table */
else if (fi[i]->name[0] == '*')
{
else if (fi[i]->name[0] == '*') {
char do_all_tables;
int total_cols,
old_size,
need,
cols;
int total_cols, old_size, need, cols;
mylog("expanding field %d\n", i);
total_cols = 0;
if (fi[i]->ti) /* The star represents only the qualified
* table */
if (fi[i]->ti) /* The star represents only the qualified table */
total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result);
else
{ /* The star represents all tables */
else { /* The star represents all tables */
/* Calculate the total number of columns after expansion */
for (k = 0; k < stmt->ntab; k++)
for (k = 0; k < stmt->ntab; k++) {
total_cols += QR_get_num_tuples(ti[k]->col_info->result);
}
}
total_cols--; /* makes up for the star */
/* Allocate some more field pointers if necessary */
@ -770,27 +683,19 @@ parse_statement(StatementClass *stmt)
mylog("k=%d, total_cols=%d, old_size=%d, need=%d\n", k,total_cols,old_size,need);
if (need > 0)
{
if (need > 0) {
int new_size = need / FLD_INCR * FLD_INCR + FLD_INCR;
mylog("need more cols: new_size = %d\n", new_size);
fi = (FIELD_INFO **) realloc(fi, (old_size + new_size) * sizeof(FIELD_INFO *));
if (!fi)
{
if ( ! fi) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
}
/*------------------------------------------------------------- */
/*
* copy any other fields (if there are any) up past the
* expansion
*/
for (j = stmt->nfld - 1; j > i; j--)
{
/* copy any other fields (if there are any) up past the expansion */
for (j = stmt->nfld - 1; j > i; j--) {
mylog("copying field %d to %d\n", j, total_cols + j);
fi[total_cols + j] = fi[j];
}
@ -808,22 +713,19 @@ parse_statement(StatementClass *stmt)
do_all_tables = (fi[i]->ti ? FALSE : TRUE);
for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)
{
for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++) {
TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
cols = QR_get_num_tuples(the_ti->col_info->result);
for (n = 0; n < cols; n++)
{
for (n = 0; n < cols; n++) {
mylog("creating field info: n=%d\n", n);
/* skip malloc (already did it for the Star) */
if (k > 0 || n > 0)
{
if (k > 0 || n > 0) {
mylog("allocating field info at %d\n", n + i);
fi[n + i] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO));
if (fi[n + i] == NULL)
{
if (fi[n + i] == NULL) {
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
@ -846,13 +748,11 @@ parse_statement(StatementClass *stmt)
/*------------------------------------------------------------- */
}
/*
* We either know which table the field was in because it was
* qualified with a table name or alias -OR- there was only 1
* table.
/* We either know which table the field was in because it was qualified
with a table name or alias -OR- there was only 1 table.
*/
else if (fi[i]->ti)
{
else if (fi[i]->ti) {
if ( ! searchColInfo(fi[i]->ti->col_info, fi[i]))
parse = FALSE;
@ -860,13 +760,10 @@ parse_statement(StatementClass *stmt)
}
/* Don't know the table -- search all tables in "from" list */
else
{
else {
parse = FALSE;
for (k = 0; k < stmt->ntab; k++)
{
if (searchColInfo(ti[k]->col_info, fi[i]))
{
for (k = 0; k < stmt->ntab; k++) {
if ( searchColInfo(ti[k]->col_info, fi[i])) {
fi[i]->ti = ti[k]; /* now know the table */
parse = TRUE;
break;
@ -886,3 +783,4 @@ parse_statement(StatementClass *stmt)
mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
return parse;
}

View File

@ -1,3 +1,4 @@
/* Module: pgtypes.c
*
* Description: This module contains routines for getting information
@ -102,13 +103,12 @@ Int2 sqlTypes[] = {
0
};
Int4
sqltype_to_pgtype(SWORD fSqlType)
Int4 sqltype_to_pgtype(SWORD fSqlType)
{
Int4 pgType;
switch (fSqlType)
{
switch(fSqlType) {
case SQL_BINARY:
pgType = PG_TYPE_BYTEA;
break;
@ -193,189 +193,122 @@ sqltype_to_pgtype(SWORD fSqlType)
know. This allows for supporting
types that are unknown. All other pg routines in here return a suitable default.
*/
Int2
pgtype_to_sqltype(StatementClass *stmt, Int4 type)
{
switch (type)
Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_CHAR:
case PG_TYPE_CHAR2:
case PG_TYPE_CHAR4:
case PG_TYPE_CHAR8:
case PG_TYPE_NAME:
return SQL_CHAR;
case PG_TYPE_NAME: return SQL_CHAR;
case PG_TYPE_BPCHAR:
return SQL_CHAR;
case PG_TYPE_BPCHAR: return SQL_CHAR;
case PG_TYPE_VARCHAR:
return SQL_VARCHAR;
case PG_TYPE_VARCHAR: return SQL_VARCHAR;
case PG_TYPE_TEXT:
return globals.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
case PG_TYPE_TEXT: return globals.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
case PG_TYPE_BYTEA:
return SQL_VARBINARY;
case PG_TYPE_LO:
return SQL_LONGVARBINARY;
case PG_TYPE_BYTEA: return SQL_VARBINARY;
case PG_TYPE_LO: return SQL_LONGVARBINARY;
case PG_TYPE_INT2:
return SQL_SMALLINT;
case PG_TYPE_INT2: return SQL_SMALLINT;
case PG_TYPE_OID:
case PG_TYPE_XID:
case PG_TYPE_INT4:
return SQL_INTEGER;
case PG_TYPE_INT4: return SQL_INTEGER;
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
case PG_TYPE_INT8:
return SQL_CHAR;
case PG_TYPE_INT8: return SQL_CHAR;
case PG_TYPE_NUMERIC:
return SQL_NUMERIC;
case PG_TYPE_NUMERIC: return SQL_NUMERIC;
case PG_TYPE_FLOAT4:
return SQL_REAL;
case PG_TYPE_FLOAT8:
return SQL_FLOAT;
case PG_TYPE_DATE:
return SQL_DATE;
case PG_TYPE_TIME:
return SQL_TIME;
case PG_TYPE_FLOAT4: return SQL_REAL;
case PG_TYPE_FLOAT8: return SQL_FLOAT;
case PG_TYPE_DATE: return SQL_DATE;
case PG_TYPE_TIME: return SQL_TIME;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return SQL_TIMESTAMP;
case PG_TYPE_MONEY:
return SQL_FLOAT;
case PG_TYPE_BOOL:
return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
case PG_TYPE_TIMESTAMP: return SQL_TIMESTAMP;
case PG_TYPE_MONEY: return SQL_FLOAT;
case PG_TYPE_BOOL: return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
default:
/*
* first, check to see if 'type' is in list. If not, look up
* with query. Add oid, name to list. If it's already in
* list, just return.
/* first, check to see if 'type' is in list. If not, look up with query.
Add oid, name to list. If it's already in list, just return.
*/
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */
return SQL_LONGVARBINARY;
return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
}
}
Int2
pgtype_to_ctype(StatementClass *stmt, Int4 type)
Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_INT8:
return SQL_C_CHAR;
case PG_TYPE_NUMERIC:
return SQL_C_CHAR;
case PG_TYPE_INT2:
return SQL_C_SSHORT;
switch(type) {
case PG_TYPE_INT8: return SQL_C_CHAR;
case PG_TYPE_NUMERIC: return SQL_C_CHAR;
case PG_TYPE_INT2: return SQL_C_SSHORT;
case PG_TYPE_OID:
case PG_TYPE_XID:
case PG_TYPE_INT4:
return SQL_C_SLONG;
case PG_TYPE_FLOAT4:
return SQL_C_FLOAT;
case PG_TYPE_FLOAT8:
return SQL_C_DOUBLE;
case PG_TYPE_DATE:
return SQL_C_DATE;
case PG_TYPE_TIME:
return SQL_C_TIME;
case PG_TYPE_INT4: return SQL_C_SLONG;
case PG_TYPE_FLOAT4: return SQL_C_FLOAT;
case PG_TYPE_FLOAT8: return SQL_C_DOUBLE;
case PG_TYPE_DATE: return SQL_C_DATE;
case PG_TYPE_TIME: return SQL_C_TIME;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return SQL_C_TIMESTAMP;
case PG_TYPE_MONEY:
return SQL_C_FLOAT;
case PG_TYPE_BOOL:
return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
case PG_TYPE_TIMESTAMP: return SQL_C_TIMESTAMP;
case PG_TYPE_MONEY: return SQL_C_FLOAT;
case PG_TYPE_BOOL: return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
case PG_TYPE_BYTEA:
return SQL_C_BINARY;
case PG_TYPE_LO:
return SQL_C_BINARY;
case PG_TYPE_BYTEA: return SQL_C_BINARY;
case PG_TYPE_LO: return SQL_C_BINARY;
default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */
return SQL_C_BINARY;
return SQL_C_CHAR;
}
}
char *
pgtype_to_name(StatementClass *stmt, Int4 type)
{
switch (type)
char *pgtype_to_name(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_CHAR: return "char";
case PG_TYPE_CHAR2:
return "char2";
case PG_TYPE_CHAR4:
return "char4";
case PG_TYPE_CHAR8:
return "char8";
case PG_TYPE_INT8:
return "int8";
case PG_TYPE_NUMERIC:
return "numeric";
case PG_TYPE_VARCHAR:
return "varchar";
case PG_TYPE_BPCHAR:
return "char";
case PG_TYPE_TEXT:
return "text";
case PG_TYPE_NAME:
return "name";
case PG_TYPE_INT2:
return "int2";
case PG_TYPE_OID:
return "oid";
case PG_TYPE_INT4:
return "int4";
case PG_TYPE_FLOAT4:
return "float4";
case PG_TYPE_FLOAT8:
return "float8";
case PG_TYPE_DATE:
return "date";
case PG_TYPE_TIME:
return "time";
case PG_TYPE_ABSTIME:
return "abstime";
case PG_TYPE_DATETIME:
return "datetime";
case PG_TYPE_TIMESTAMP:
return "timestamp";
case PG_TYPE_MONEY:
return "money";
case PG_TYPE_BOOL:
return "bool";
case PG_TYPE_BYTEA:
return "bytea";
case PG_TYPE_CHAR2: return "char2";
case PG_TYPE_CHAR4: return "char4";
case PG_TYPE_CHAR8: return "char8";
case PG_TYPE_INT8: return "int8";
case PG_TYPE_NUMERIC: return "numeric";
case PG_TYPE_VARCHAR: return "varchar";
case PG_TYPE_BPCHAR: return "char";
case PG_TYPE_TEXT: return "text";
case PG_TYPE_NAME: return "name";
case PG_TYPE_INT2: return "int2";
case PG_TYPE_OID: return "oid";
case PG_TYPE_INT4: return "int4";
case PG_TYPE_FLOAT4: return "float4";
case PG_TYPE_FLOAT8: return "float8";
case PG_TYPE_DATE: return "date";
case PG_TYPE_TIME: return "time";
case PG_TYPE_ABSTIME: return "abstime";
case PG_TYPE_DATETIME: return "datetime";
case PG_TYPE_TIMESTAMP: return "timestamp";
case PG_TYPE_MONEY: return "money";
case PG_TYPE_BOOL: return "bool";
case PG_TYPE_BYTEA: return "bytea";
case PG_TYPE_LO:
return PG_TYPE_LO_NAME;
case PG_TYPE_LO: return PG_TYPE_LO_NAME;
default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */
return PG_TYPE_LO_NAME;
/*
* "unknown" can actually be used in alter table because it is
* a real PG type!
*/
/* "unknown" can actually be used in alter table because it is a real PG type! */
return "unknown";
}
}
@ -394,12 +327,8 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
result = SC_get_Result(stmt);
/*
* Manual Result Sets -- use assigned column width (i.e., from
* set_tuplefield_string)
*/
if (stmt->manual_result)
{
/* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */
if (stmt->manual_result) {
flds = result->fields;
if (flds)
return flds->adtsize[col];
@ -430,12 +359,8 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
result = SC_get_Result(stmt);
/*
* Manual Result Sets -- use assigned column width (i.e., from
* set_tuplefield_string)
*/
if (stmt->manual_result)
{
/* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */
if (stmt->manual_result) {
flds = result->fields;
if (flds)
return flds->adtsize[col];
@ -455,16 +380,14 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
Int4
getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
int p = -1,
maxsize;
int p = -1, maxsize;
QResultClass *result;
ColumnInfoClass *flds;
mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unknown_size_as);
/* Assign Maximum size based on parameters */
switch (type)
{
switch(type) {
case PG_TYPE_TEXT:
if (globals.text_as_longvarchar)
maxsize = globals.max_longvarchar_size;
@ -485,21 +408,16 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
break;
}
/*
* Static Precision (i.e., the Maximum Precision of the datatype) This
* has nothing to do with a result set.
/* Static Precision (i.e., the Maximum Precision of the datatype)
This has nothing to do with a result set.
*/
if (col < 0)
return maxsize;
result = SC_get_Result(stmt);
/*
* Manual Result Sets -- use assigned column width (i.e., from
* set_tuplefield_string)
*/
if (stmt->manual_result)
{
/* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */
if (stmt->manual_result) {
flds = result->fields;
if (flds)
return flds->adtsize[col];
@ -511,8 +429,7 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
if (QR_get_atttypmod(result, col) > -1)
return QR_get_atttypmod(result, col);
if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
{
if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST) {
p = QR_get_display_size(result, col);
mylog("getCharPrecision: LONGEST: p = %d\n", p);
}
@ -529,64 +446,47 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
If col >= 0, then will attempt to get the info from the result set.
This is used for functions SQLDescribeCol and SQLColAttributes.
*/
Int4
pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_CHAR:
return 1;
case PG_TYPE_CHAR2:
return 2;
case PG_TYPE_CHAR4:
return 4;
case PG_TYPE_CHAR8:
return 8;
case PG_TYPE_NAME:
return NAME_FIELD_SIZE;
switch(type) {
case PG_TYPE_INT2:
return 5;
case PG_TYPE_CHAR: return 1;
case PG_TYPE_CHAR2: return 2;
case PG_TYPE_CHAR4: return 4;
case PG_TYPE_CHAR8: return 8;
case PG_TYPE_NAME: return NAME_FIELD_SIZE;
case PG_TYPE_INT2: return 5;
case PG_TYPE_OID:
case PG_TYPE_XID:
case PG_TYPE_INT4:
return 10;
case PG_TYPE_INT4: return 10;
case PG_TYPE_INT8:
return 19; /* signed */
case PG_TYPE_INT8: return 19; /* signed */
case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col);
case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col);
case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY:
return 7;
case PG_TYPE_MONEY: return 7;
case PG_TYPE_FLOAT8:
return 15;
case PG_TYPE_FLOAT8: return 15;
case PG_TYPE_DATE:
return 10;
case PG_TYPE_TIME:
return 8;
case PG_TYPE_DATE: return 10;
case PG_TYPE_TIME: return 8;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return 19;
case PG_TYPE_TIMESTAMP: return 19;
case PG_TYPE_BOOL:
return 1;
case PG_TYPE_BOOL: return 1;
case PG_TYPE_LO:
return SQL_NO_TOTAL;
case PG_TYPE_LO: return SQL_NO_TOTAL;
default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */
return SQL_NO_TOTAL;
/* Handle Character types and unknown types */
@ -594,35 +494,26 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
}
}
Int4
pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_INT2:
return 6;
switch(type) {
case PG_TYPE_INT2: return 6;
case PG_TYPE_OID:
case PG_TYPE_XID:
return 10;
case PG_TYPE_XID: return 10;
case PG_TYPE_INT4:
return 11;
case PG_TYPE_INT4: return 11;
case PG_TYPE_INT8:
return 20; /* signed: 19 digits + sign */
case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */
case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col) + 2;
case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col) + 2;
case PG_TYPE_MONEY:
return 15; /* ($9,999,999.99) */
case PG_TYPE_MONEY: return 15; /* ($9,999,999.99) */
case PG_TYPE_FLOAT4:
return 13;
case PG_TYPE_FLOAT4: return 13;
case PG_TYPE_FLOAT8:
return 22;
case PG_TYPE_FLOAT8: return 22;
/* Character types use regular precision */
default:
@ -633,40 +524,32 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
override this length with the atttypmod length from pg_attribute
*/
Int4
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_INT2:
return 2;
switch(type) {
case PG_TYPE_INT2: return 2;
case PG_TYPE_OID:
case PG_TYPE_XID:
case PG_TYPE_INT4:
return 4;
case PG_TYPE_INT4: return 4;
case PG_TYPE_INT8:
return 20; /* signed: 19 digits + sign */
case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */
case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col) + 2;
case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col) + 2;
case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY:
return 4;
case PG_TYPE_MONEY: return 4;
case PG_TYPE_FLOAT8:
return 8;
case PG_TYPE_FLOAT8: return 8;
case PG_TYPE_DATE:
case PG_TYPE_TIME:
return 6;
case PG_TYPE_TIME: return 6;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return 16;
case PG_TYPE_TIMESTAMP: return 16;
/* Character types (and NUMERIC) use the default precision */
@ -675,11 +558,10 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
}
}
Int2
pgtype_scale(StatementClass *stmt, Int4 type, int col)
{
switch (type)
Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col)
{
switch(type) {
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -690,29 +572,21 @@ pgtype_scale(StatementClass *stmt, Int4 type, int col)
case PG_TYPE_MONEY:
case PG_TYPE_BOOL:
/*
* Number of digits to the right of the decimal point in
* "yyyy-mm=dd hh:mm:ss[.f...]"
*/
/* Number of digits to the right of the decimal point in "yyyy-mm=dd hh:mm:ss[.f...]" */
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return 0;
case PG_TYPE_TIMESTAMP: return 0;
case PG_TYPE_NUMERIC:
return getNumericScale(stmt, type, col);
case PG_TYPE_NUMERIC: return getNumericScale(stmt,type,col);
default:
return -1;
default: return -1;
}
}
Int2
pgtype_radix(StatementClass *stmt, Int4 type)
{
switch (type)
Int2 pgtype_radix(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_INT4:
@ -720,25 +594,21 @@ pgtype_radix(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC:
case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY:
case PG_TYPE_FLOAT8:
return 10;
case PG_TYPE_FLOAT8: return 10;
default:
return -1;
default: return -1;
}
}
Int2
pgtype_nullable(StatementClass *stmt, Int4 type)
Int2 pgtype_nullable(StatementClass *stmt, Int4 type)
{
return SQL_NULLABLE; /* everything should be nullable */
}
Int2
pgtype_auto_increment(StatementClass *stmt, Int4 type)
{
switch (type)
Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -754,19 +624,15 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type)
case PG_TYPE_TIME:
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return FALSE;
case PG_TYPE_TIMESTAMP: return FALSE;
default:
return -1;
default: return -1;
}
}
Int2
pgtype_case_sensitive(StatementClass *stmt, Int4 type)
{
switch (type)
Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_CHAR:
case PG_TYPE_CHAR2:
@ -776,31 +642,23 @@ pgtype_case_sensitive(StatementClass *stmt, Int4 type)
case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR:
case PG_TYPE_TEXT:
case PG_TYPE_NAME:
return TRUE;
case PG_TYPE_NAME: return TRUE;
default:
return FALSE;
default: return FALSE;
}
}
Int2
pgtype_money(StatementClass *stmt, Int4 type)
Int2 pgtype_money(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_MONEY:
return TRUE;
default:
return FALSE;
switch(type) {
case PG_TYPE_MONEY: return TRUE;
default: return FALSE;
}
}
Int2
pgtype_searchable(StatementClass *stmt, Int4 type)
{
switch (type)
Int2 pgtype_searchable(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_CHAR:
case PG_TYPE_CHAR2:
case PG_TYPE_CHAR4:
@ -809,22 +667,17 @@ pgtype_searchable(StatementClass *stmt, Int4 type)
case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR:
case PG_TYPE_TEXT:
case PG_TYPE_NAME:
return SQL_SEARCHABLE;
case PG_TYPE_NAME: return SQL_SEARCHABLE;
default:
return SQL_ALL_EXCEPT_LIKE;
default: return SQL_ALL_EXCEPT_LIKE;
}
}
Int2
pgtype_unsigned(StatementClass *stmt, Int4 type)
{
switch (type)
Int2 pgtype_unsigned(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_OID:
case PG_TYPE_XID:
return TRUE;
case PG_TYPE_XID: return TRUE;
case PG_TYPE_INT2:
case PG_TYPE_INT4:
@ -832,19 +685,16 @@ pgtype_unsigned(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC:
case PG_TYPE_FLOAT4:
case PG_TYPE_FLOAT8:
case PG_TYPE_MONEY:
return FALSE;
case PG_TYPE_MONEY: return FALSE;
default:
return -1;
default: return -1;
}
}
char *
pgtype_literal_prefix(StatementClass *stmt, Int4 type)
{
switch (type)
char *pgtype_literal_prefix(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -855,16 +705,14 @@ pgtype_literal_prefix(StatementClass *stmt, Int4 type)
case PG_TYPE_FLOAT8:
case PG_TYPE_MONEY: return NULL;
default:
return "'";
default: return "'";
}
}
char *
pgtype_literal_suffix(StatementClass *stmt, Int4 type)
{
switch (type)
char *pgtype_literal_suffix(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -875,31 +723,25 @@ pgtype_literal_suffix(StatementClass *stmt, Int4 type)
case PG_TYPE_FLOAT8:
case PG_TYPE_MONEY: return NULL;
default:
return "'";
default: return "'";
}
}
char *
pgtype_create_params(StatementClass *stmt, Int4 type)
{
switch (type)
char *pgtype_create_params(StatementClass *stmt, Int4 type)
{
switch(type) {
case PG_TYPE_CHAR:
case PG_TYPE_VARCHAR: return "max. length";
default:
return NULL;
default: return NULL;
}
}
Int2
sqltype_to_default_ctype(Int2 sqltype)
Int2 sqltype_to_default_ctype(Int2 sqltype)
{
/* from the table on page 623 of ODBC 2.0 Programmer's Reference */
/* (Appendix D) */
switch (sqltype)
{
switch(sqltype) {
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
@ -945,3 +787,4 @@ sqltype_to_default_ctype(Int2 sqltype)
return SQL_C_CHAR;
}
}

View File

@ -95,3 +95,4 @@ char *pgtype_create_params(StatementClass *stmt, Int4 type);
Int2 sqltype_to_default_ctype(Int2 sqltype);
#endif

View File

@ -1,3 +1,4 @@
/* Module: psqlodbc.c
*
* Description: This module contains the main entry point (DllMain) for the library.
@ -38,14 +39,12 @@ RETCODE SQL_API SQLDummyOrdinal(void);
HINSTANCE NEAR s_hModule; /* Saved module handle. */
/* This is where the Driver Manager attaches to this Driver */
BOOL WINAPI
DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
WORD wVersionRequested;
WSADATA wsaData;
switch (ul_reason_for_call)
{
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
s_hModule = hInst; /* Save for dialog boxes */
@ -57,8 +56,8 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
/* Verify that this is the minimum version of WinSock */
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
{
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup();
return FALSE;
}
@ -136,8 +135,8 @@ _fini(void)
Driver Manager do this. Also, the ordinal values of the
functions must match the value of fFunction in SQLGetFunctions()
*/
RETCODE SQL_API
SQLDummyOrdinal(void)
RETCODE SQL_API SQLDummyOrdinal(void)
{
return SQL_SUCCESS;
}

View File

@ -6,7 +6,7 @@
*
* Comments: See "notice.txt" for copyright and license information.
*
* $Id: psqlodbc.h,v 1.36 2001/02/11 13:53:42 momjian Exp $
* $Id: psqlodbc.h,v 1.37 2001/02/14 05:45:46 momjian Exp $
*/
#ifndef __PSQLODBC_H__
@ -25,7 +25,6 @@
#define UInt2 unsigned short
typedef float SFLOAT;
typedef double SDOUBLE;
#else
#define Int4 int
#define UInt4 unsigned int
@ -42,7 +41,7 @@ typedef UInt4 Oid;
#define DRIVERNAME "PostgreSQL ODBC"
#define DBMS_NAME "PostgreSQL"
#define POSTGRESDRIVERVERSION "07.01.0003"
#define POSTGRESDRIVERVERSION "07.01.0002"
#ifdef WIN32
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
@ -55,17 +54,14 @@ typedef UInt4 Oid;
#define BLCKSZ 4096
#endif
#define MAX_MESSAGE_LEN 65536 /* This puts a limit on query size
* but I don't */
#define MAX_MESSAGE_LEN 65536 /* This puts a limit on query size but I don't */
/* see an easy way round this - DJP 24-1-2001 */
#define MAX_CONNECT_STRING 4096
#define ERROR_MSG_LENGTH 4096
#define FETCH_MAX 100 /* default number of rows to cache
* for declare/fetch */
#define FETCH_MAX 100 /* default number of rows to cache for declare/fetch */
#define TUPLE_MALLOC_INC 100
#define SOCK_BUFFER_SIZE 4096 /* default socket buffer size */
#define MAX_CONNECTIONS 128 /* conns per environment
* (arbitrary) */
#define MAX_CONNECTIONS 128 /* conns per environment (arbitrary) */
#define MAX_FIELDS 512
#define BYTELEN 8
#define VARHDRSZ sizeof(Int4)
@ -76,8 +72,7 @@ typedef UInt4 Oid;
/* Registry length limits */
#define LARGE_REGISTRY_LEN 4096 /* used for special cases */
#define MEDIUM_REGISTRY_LEN 256 /* normal size for
* user,database,etc. */
#define MEDIUM_REGISTRY_LEN 256 /* normal size for user,database,etc. */
#define SMALL_REGISTRY_LEN 10 /* for 1/0 settings */
@ -88,17 +83,16 @@ typedef UInt4 Oid;
/* Info limits */
#define MAX_INFO_STRING 128
#define MAX_KEYPARTS 20
#define MAX_KEYLEN 512 /* max key of the form
* "date+outlet+invoice" */
#define MAX_ROW_SIZE 0 /* Unlimited rowsize with the
* Tuple Toaster */
#define MAX_STATEMENT_LEN 0 /* Unlimited statement size with
* 7.0 */
#define MAX_KEYLEN 512 /* max key of the form "date+outlet+invoice" */
#define MAX_ROW_SIZE 0 /* Unlimited rowsize with the Tuple Toaster */
#define MAX_STATEMENT_LEN 0 /* Unlimited statement size with 7.0 */
/* Previously, numerous query strings were defined of length MAX_STATEMENT_LEN */
/* Now that's 0, lets use this instead. DJP 24-1-2001 */
#define STD_STATEMENT_LEN MAX_MESSAGE_LEN
#define PG62 "6.2" /* "Protocol" key setting to force Postgres 6.2 */
#define PG63 "6.3" /* "Protocol" key setting to force postgres 6.3 */
#define PG64 "6.4"
typedef struct ConnectionClass_ ConnectionClass;
@ -128,8 +122,7 @@ typedef struct GlobalValues_
char disable_optimizer;
char ksqo;
char unique_index;
char onlyread; /* readonly is reserved on Digital C++
* compiler */
char onlyread; /* readonly is reserved on Digital C++ compiler */
char use_declarefetch;
char text_as_longvarchar;
char unknowns_as_longvarchar;
@ -139,18 +132,13 @@ typedef struct GlobalValues_
char cancel_as_freestmt;
char extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
char conn_settings[LARGE_REGISTRY_LEN];
/*
* Protocol is not used anymore, but kept in case it is useful in the
* future. bjm 2001-02-10
*/
char protocol[SMALL_REGISTRY_LEN];
FILE* mylogFP;
FILE* qlogFP;
} GLOBAL_VALUES;
typedef struct StatementOptions_
{
typedef struct StatementOptions_ {
int maxRows;
int maxLength;
int rowset_size;
@ -158,33 +146,26 @@ typedef struct StatementOptions_
int cursor_type;
int scroll_concurrency;
int retrieve_data;
int bind_size; /* size of each structure if using Row
* Binding */
int bind_size; /* size of each structure if using Row Binding */
int use_bookmarks;
} StatementOptions;
/* Used to pass extra query info to send_query */
typedef struct QueryInfo_
{
typedef struct QueryInfo_ {
int row_size;
QResultClass *result_in;
char *cursor;
} QueryInfo;
#define PG_TYPE_LO -999 /* hack until permanent
* type available */
#define PG_TYPE_LO -999 /* hack until permanent type available */
#define PG_TYPE_LO_NAME "lo"
#define OID_ATTNUM -2 /* the attnum in pg_index of the
* oid */
#define OID_ATTNUM -2 /* the attnum in pg_index of the oid */
/* sizes */
#define TEXT_FIELD_SIZE 8190 /* size of text fields
* (not including null
* term) */
#define TEXT_FIELD_SIZE 8190 /* size of text fields (not including null term) */
#define NAME_FIELD_SIZE 32 /* size of name fields */
#define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not
* including null term) */
#define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not including null term) */
#define PG_NUMERIC_MAX_PRECISION 1000
#define PG_NUMERIC_MAX_SCALE 1000

View File

@ -133,7 +133,7 @@ BEGIN
PUSHBUTTON "Defaults",IDDEFAULTS,185,205,50,15
END
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 125
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Advanced Options (DataSource)"
FONT 8, "MS Sans Serif"
@ -144,16 +144,23 @@ BEGIN
BS_AUTOCHECKBOX | WS_TABSTOP,130,10,85,10
CONTROL "Show System &Tables",DS_SHOWSYSTEMTABLES,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,25,25,85,10
GROUPBOX "OID Options",IDC_STATIC,39,41,180,25
GROUPBOX "Protocol",IDC_STATIC,15,40,180,25
CONTROL "6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | WS_GROUP,25,
50,35,10
CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
75,50,26,10
CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
130,50,26,10
GROUPBOX "OID Options",IDC_STATIC,15,70,180,25
CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,62,51,59,10
WS_GROUP | WS_TABSTOP,25,81,59,10
CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,151,51,51,10
RTEXT "Connect &Settings:",IDC_STATIC,11,73,35,25
EDITTEXT DS_CONNSETTINGS,49,73,200,20,ES_MULTILINE |
WS_GROUP | WS_TABSTOP,115,81,51,10
RTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25
EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
DEFPUSHBUTTON "OK",IDOK,71,103,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,145,103,50,14
DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14
END
@ -184,7 +191,7 @@ BEGIN
RIGHTMARGIN, 260
VERTGUIDE, 55
TOPMARGIN, 7
BOTTOMMARGIN, 118
BOTTOMMARGIN, 154
END
END
#endif // APSTUDIO_INVOKED
@ -197,8 +204,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 7,1,0,3
PRODUCTVERSION 7,1,0,3
FILEVERSION 7,1,0,2
PRODUCTVERSION 7,1,0,2
FILEFLAGSMASK 0x3L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -216,14 +223,14 @@ BEGIN
VALUE "Comments", "PostgreSQL ODBC driver\0"
VALUE "CompanyName", "Insight Distribution Systems\0"
VALUE "FileDescription", "PostgreSQL Driver\0"
VALUE "FileVersion", " 07.01.0003\0"
VALUE "FileVersion", " 07.01.0002\0"
VALUE "InternalName", "psqlodbc\0"
VALUE "LegalCopyright", "\0"
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
VALUE "OriginalFilename", "psqlodbc.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
VALUE "ProductVersion", " 07.01.0003\0"
VALUE "ProductVersion", " 07.01.0002\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@ -1,3 +1,4 @@
/* Module: qresult.c
*
* Description: This module contains functions related to
@ -83,13 +84,11 @@ QR_Constructor(void)
mylog("in QR_Constructor\n");
rv = (QResultClass *) malloc(sizeof(QResultClass));
if (rv != NULL)
{
if (rv != NULL) {
rv->status = PGRES_EMPTY_QUERY;
/* construct the column info */
if (!(rv->fields = CI_Constructor()))
{
if ( ! (rv->fields = CI_Constructor())) {
free(rv);
return NULL;
}
@ -110,6 +109,7 @@ QR_Constructor(void)
rv->cache_size = globals.fetch_max;
rv->rowset_size = 1;
}
mylog("exit QR_Constructor\n");
@ -151,6 +151,7 @@ QR_Destructor(QResultClass *self)
free(self);
mylog("QResult: exit DESTRUCTOR\n");
}
void
@ -174,23 +175,19 @@ QR_set_notice(QResultClass *self, char *msg)
void
QR_free_memory(QResultClass *self)
{
register int lf,
row;
register int lf, row;
register TupleField *tuple = self->backend_tuples;
int fcount = self->fcount;
int num_fields = self->num_fields;
mylog("QResult: free memory in, fcount=%d\n", fcount);
if (self->backend_tuples)
{
for (row = 0; row < fcount; row++)
{
if ( self->backend_tuples) {
for (row = 0; row < fcount; row++) {
mylog("row = %d, num_fields = %d\n", row, num_fields);
for (lf = 0; lf < num_fields; lf++)
{
if (tuple[lf].value != NULL)
{
for (lf=0; lf < num_fields; lf++) {
if (tuple[lf].value != NULL) {
mylog("free [lf=%d] %u\n", lf, tuple[lf].value);
free(tuple[lf].value);
}
@ -218,8 +215,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
/* and read the tuples. If conn is NULL, */
/* it implies that we are being called from next_tuple(), */
/* like to get more rows so don't call next_tuple again! */
if (conn != NULL)
{
if (conn != NULL) {
self->conn = conn;
mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor==NULL)?"":cursor, self->cursor);
@ -227,10 +223,8 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
if (self->cursor)
free(self->cursor);
if (globals.use_declarefetch)
{
if (!cursor || cursor[0] == '\0')
{
if ( globals.use_declarefetch) {
if (! cursor || cursor[0] == '\0') {
self->status = PGRES_INTERNAL_ERROR;
QR_set_message(self, "Internal Error -- no cursor for fetch");
return FALSE;
@ -240,13 +234,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
/* Read the field attributes. */
/* $$$$ Should do some error control HERE! $$$$ */
if (CI_read_fields(self->fields, self->conn))
{
if ( CI_read_fields(self->fields, self->conn)) {
self->status = PGRES_FIELDS_OK;
self->num_fields = CI_get_num_fields(self->fields);
}
else
{
else {
self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Error reading field information");
return FALSE;
@ -262,8 +254,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
/* allocate memory for the tuple cache */
mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
if (!self->backend_tuples)
{
if ( ! self->backend_tuples) {
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Could not get memory for tuple cache.");
return FALSE;
@ -279,13 +270,12 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
return QR_next_tuple(self);
}
else
{
else {
/* Always have to read the field attributes. */
/* But we dont have to reallocate memory for them! */
if (!CI_read_fields(NULL, self->conn))
{
if ( ! CI_read_fields(NULL, self->conn)) {
self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Error reading field information");
return FALSE;
@ -301,8 +291,7 @@ QR_close(QResultClass *self)
{
QResultClass *res;
if (globals.use_declarefetch && self->conn && self->cursor)
{
if (globals.use_declarefetch && self->conn && self->cursor) {
char buf[64];
sprintf(buf, "close %s", self->cursor);
@ -316,29 +305,27 @@ QR_close(QResultClass *self)
free(self->cursor);
self->cursor = NULL;
if (res == NULL)
{
if (res == NULL) {
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error closing cursor.");
return FALSE;
}
/* End the transaction if there are no cursors left on this conn */
if (CC_cursor_count(self->conn) == 0)
{
if (CC_cursor_count(self->conn) == 0) {
mylog("QResult: END transaction on conn=%u\n", self->conn);
res = CC_send_query(self->conn, "END", NULL);
CC_set_no_trans(self->conn);
if (res == NULL)
{
if (res == NULL) {
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error ending transaction.");
return FALSE;
}
}
}
return TRUE;
@ -351,59 +338,49 @@ QR_next_tuple(QResultClass *self)
int id;
QResultClass *res;
SocketClass *sock;
/* Speed up access */
int fetch_count = self->fetch_count;
int fcount = self->fcount;
int fetch_size,
offset = 0;
int fetch_size, offset= 0;
int end_tuple = self->rowset_size + self->base;
char corrected = FALSE;
TupleField *the_tuples = self->backend_tuples;
static char msgbuffer[MAX_MESSAGE_LEN+1];
char cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
* this string so dont
* need static */
char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont need static */
char fetch[128];
QueryInfo qi;
if (fetch_count < fcount)
{ /* return a row from cache */
if (fetch_count < fcount) { /* return a row from cache */
mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount);
self->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */
self->fetch_count++;
return TRUE;
}
else if (self->fcount < self->cache_size)
{ /* last row from cache */
else if (self->fcount < self->cache_size) { /* last row from cache */
/* We are done because we didn't even get CACHE_SIZE tuples */
mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count);
self->tupleField = NULL;
self->status = PGRES_END_TUPLES;
return -1; /* end of tuples */
}
else
{
/*
* See if we need to fetch another group of rows. We may be being
* called from send_query(), and if so, don't send another fetch,
* just fall through and read the tuples.
else {
/* See if we need to fetch another group of rows.
We may be being called from send_query(), and
if so, don't send another fetch, just fall through
and read the tuples.
*/
self->tupleField = NULL;
if (!self->inTuples)
{
if (!globals.use_declarefetch)
{
if ( ! self->inTuples) {
if ( ! globals.use_declarefetch) {
mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
self->tupleField = NULL;
self->status = PGRES_END_TUPLES;
return -1; /* end of tuples */
}
if (self->base == fcount)
{ /* not a correction */
if (self->base == fcount) { /* not a correction */
/* Determine the optimum cache size. */
if (globals.fetch_max % self->rowset_size == 0)
@ -416,8 +393,7 @@ QR_next_tuple(QResultClass *self)
self->cache_size = fetch_size;
self->fetch_count = 1;
}
else
{ /* need to correct */
else { /* need to correct */
corrected = TRUE;
@ -427,12 +403,12 @@ QR_next_tuple(QResultClass *self)
offset = self->fetch_count;
self->fetch_count++;
}
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
if (!self->backend_tuples)
{
if ( ! self->backend_tuples) {
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples.");
return FALSE;
@ -446,29 +422,24 @@ QR_next_tuple(QResultClass *self)
qi.result_in = self;
qi.cursor = NULL;
res = CC_send_query(self->conn, fetch, &qi);
if (res == NULL)
{
if (res == NULL) {
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error fetching next group.");
return FALSE;
}
self->inTuples = TRUE;
}
else
{
else {
mylog("next_tuple: inTuples = true, falling through: fcount = %d, fetch_count = %d\n", self->fcount, self->fetch_count);
/*
* This is a pre-fetch (fetching rows right after query but
* before any real SQLFetch() calls. This is done so the
* field attributes are available.
/* This is a pre-fetch (fetching rows right after query
but before any real SQLFetch() calls. This is done
so the field attributes are available.
*/
self->fetch_count = 0;
}
}
if (!corrected)
{
if ( ! corrected) {
self->base = 0;
self->fcount = 0;
}
@ -477,12 +448,11 @@ QR_next_tuple(QResultClass *self)
sock = CC_get_socket(self->conn);
self->tupleField = NULL;
for (;;)
{
for ( ; ;) {
id = SOCK_get_char(sock);
switch (id)
{
switch (id) {
case 'T': /* Tuples within tuples cannot be handled */
self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Tuples within tuples cannot be handled");
@ -490,23 +460,19 @@ QR_next_tuple(QResultClass *self)
case 'B': /* Tuples in binary format */
case 'D': /* Tuples in ASCII format */
if (!globals.use_declarefetch && self->fcount > 0 && !(self->fcount % TUPLE_MALLOC_INC))
{
if ( ! globals.use_declarefetch && self->fcount > 0 && ! (self->fcount % TUPLE_MALLOC_INC)) {
size_t old_size = self->fcount * self->num_fields * sizeof(TupleField);
mylog("REALLOC: old_size = %d\n", old_size);
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, old_size + (self->num_fields * sizeof(TupleField) * TUPLE_MALLOC_INC));
if (!self->backend_tuples)
{
if ( ! self->backend_tuples) {
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples.");
return FALSE;
}
}
if (!QR_read_tuple(self, (char) (id == 0)))
{
if ( ! QR_read_tuple(self, (char) (id == 0))) {
self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Error reading the tuple");
return FALSE;
@ -523,8 +489,8 @@ QR_next_tuple(QResultClass *self)
mylog("end of tuple list -- setting inUse to false: this = %u\n", self);
self->inTuples = FALSE;
if (self->fcount > 0)
{
if (self->fcount > 0) {
qlog(" [ fetched %d rows ]\n", self->fcount);
mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount);
@ -532,9 +498,7 @@ QR_next_tuple(QResultClass *self)
self->tupleField = self->backend_tuples + (offset * self->num_fields);
return TRUE;
}
else
{ /* We are surely done here (we read 0
* tuples) */
else { /* We are surely done here (we read 0 tuples) */
qlog(" [ fetched 0 rows ]\n");
mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
return -1; /* end of tuples */
@ -559,8 +523,7 @@ QR_next_tuple(QResultClass *self)
qlog("NOTICE from backend in next_tuple: '%s'\n", msgbuffer);
continue;
default: /* this should only happen if the backend
* dumped core */
default: /* this should only happen if the backend dumped core */
mylog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id);
qlog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id);
QR_set_message(self, "Unexpected result from backend. It probably crashed");
@ -577,8 +540,7 @@ QR_read_tuple(QResultClass *self, char binary)
{
Int2 field_lf;
TupleField *this_tuplefield;
char bmp,
bitmap[MAX_FIELDS]; /* Max. len of the bitmap */
char bmp, bitmap[MAX_FIELDS]; /* Max. len of the bitmap */
Int2 bitmaplen; /* len of the bitmap in bytes */
Int2 bitmap_pos;
Int2 bitcnt;
@ -597,8 +559,8 @@ QR_read_tuple(QResultClass *self, char binary)
bitmaplen++;
/*
* At first the server sends a bitmap that indicates which database
* fields are null
At first the server sends a bitmap that indicates which
database fields are null
*/
SOCK_get_n_char(sock, bitmap, bitmaplen);
@ -606,21 +568,16 @@ QR_read_tuple(QResultClass *self, char binary)
bitcnt = 0;
bmp = bitmap[bitmap_pos];
for (field_lf = 0; field_lf < num_fields; field_lf++)
{
for(field_lf = 0; field_lf < num_fields; field_lf++) {
/* Check if the current field is NULL */
if (!(bmp & 0200))
{
if(!(bmp & 0200)) {
/* YES, it is NULL ! */
this_tuplefield[field_lf].len = 0;
this_tuplefield[field_lf].value = 0;
}
else
{
} else {
/*
* NO, the field is not null. so get at first the length of
* the field (four bytes)
NO, the field is not null. so get at first the
length of the field (four bytes)
*/
len = SOCK_get_int(sock, VARHDRSZ);
if (!binary)
@ -635,31 +592,27 @@ QR_read_tuple(QResultClass *self, char binary)
this_tuplefield[field_lf].len = len;
this_tuplefield[field_lf].value = buffer;
/*
* This can be used to set the longest length of the column
* for any row in the tuple cache. It would not be accurate
* for varchar and text fields to use this since a tuple cache
* is only 100 rows. Bpchar can be handled since the strlen of
* all rows is fixed, assuming there are not 100 nulls in a
* row!
/* This can be used to set the longest length of the column for any
row in the tuple cache. It would not be accurate for varchar and
text fields to use this since a tuple cache is only 100 rows.
Bpchar can be handled since the strlen of all rows is fixed,
assuming there are not 100 nulls in a row!
*/
flds = self->fields;
if (flds->display_size[field_lf] < len)
flds->display_size[field_lf] = len;
}
/*
* Now adjust for the next bit to be scanned in the next loop.
Now adjust for the next bit to be scanned in the
next loop.
*/
bitcnt++;
if (BYTELEN == bitcnt)
{
if (BYTELEN == bitcnt) {
bitmap_pos++;
bmp = bitmap[bitmap_pos];
bitcnt = 0;
}
else
} else
bmp <<= 1;
}
self->currTuple++;

View File

@ -17,8 +17,7 @@
#include "psqlodbc.h"
#include "tuple.h"
enum QueryResultCode_
{
enum QueryResultCode_ {
PGRES_EMPTY_QUERY = 0,
PGRES_COMMAND_OK, /* a query command that doesn't return */
/* anything was executed properly by the backend */
@ -27,24 +26,20 @@ enum QueryResultCode_
/* contains the resulttuples */
PGRES_COPY_OUT,
PGRES_COPY_IN,
PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from
* the backend */
PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the backend */
PGRES_NONFATAL_ERROR,
PGRES_FATAL_ERROR,
PGRES_FIELDS_OK, /* field information from a query was
* successful */
PGRES_FIELDS_OK, /* field information from a query was successful */
PGRES_END_TUPLES,
PGRES_INTERNAL_ERROR
};
typedef enum QueryResultCode_ QueryResultCode;
struct QResultClass_
{
struct QResultClass_ {
ColumnInfoClass *fields; /* the Column information */
TupleListClass *manual_tuples; /* manual result tuple list */
ConnectionClass *conn; /* the connection this result is using
* (backend) */
ConnectionClass *conn; /* the connection this result is using (backend) */
/* Stuff for declare/fetch tuples */
int fetch_count; /* logical rows read so far */
@ -59,16 +54,14 @@ struct QResultClass_
QueryResultCode status;
char *message;
char *cursor; /* The name of the cursor for select
* statements */
char *cursor; /* The name of the cursor for select statements */
char *command;
char *notice;
TupleField *backend_tuples; /* data from the backend (the tuple cache) */
TupleField *tupleField; /* current backend tuple being retrieved */
char inTuples; /* is a fetch of rows from the backend in
* progress? */
char inTuples; /* is a fetch of rows from the backend in progress? */
};
#define QR_get_fields(self) (self->fields)

View File

@ -1,7 +1,7 @@
/* {{NO_DEPENDENCIES}} */
/* Microsoft Developer Studio generated include file. */
/* Used by psqlodbc.rc */
/* */
#define IDS_BADDSN 1
#define IDS_MSGTITLE 2
#define DLG_OPTIONS_DRV 102
@ -19,6 +19,7 @@
#define DS_SHOWOIDCOLUMN 1012
#define DS_FAKEOIDINDEX 1013
#define DRV_COMMLOG 1014
#define DS_PG62 1016
#define IDC_DATASOURCE 1018
#define DRV_OPTIMIZER 1019
#define DS_CONNSETTINGS 1020
@ -47,9 +48,10 @@
#define IDC_OPTIONS 1054
#define DRV_KSQO 1055
#define DS_PG64 1057
#define DS_PG63 1058
/* Next default values for new objects */
/* */
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
/* Module: setup.c
*
* Description: This module contains the setup functions for
@ -42,14 +43,14 @@ extern GLOBAL_VALUES globals;
/* Globals ----------------------------------------------------------------- */
/* NOTE: All these are used by the dialog procedures */
typedef struct tagSETUPDLG
{
typedef struct tagSETUPDLG {
HWND hwndParent; /* Parent window handle */
LPCSTR lpszDrvr; /* Driver description */
ConnInfo ci;
char szDSN[MAXDSNAME]; /* Original data source name */
BOOL fNewDSN; /* New data source flag */
BOOL fDefault; /* Default data source flag */
} SETUPDLG, FAR *LPSETUPDLG;
@ -72,8 +73,7 @@ BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
Output : TRUE success, FALSE otherwise
--------------------------------------------------------------------------*/
BOOL CALLBACK
ConfigDSN(HWND hwnd,
BOOL CALLBACK ConfigDSN (HWND hwnd,
WORD fRequest,
LPCSTR lpszDriver,
LPCSTR lpszAttributes)
@ -100,8 +100,7 @@ ConfigDSN(HWND hwnd,
lpsetupdlg->szDSN[0] = '\0';
/* Remove data source */
if (ODBC_REMOVE_DSN == fRequest)
{
if (ODBC_REMOVE_DSN == fRequest) {
/* Fail if no data source name was supplied */
if (!lpsetupdlg->ci.dsn[0])
fSuccess = FALSE;
@ -112,20 +111,15 @@ ConfigDSN(HWND hwnd,
}
/* Add or Configure data source */
else
{
else {
/* Save passed variables for global access (e.g., dialog access) */
lpsetupdlg->hwndParent = hwnd;
lpsetupdlg->lpszDrvr = lpszDriver;
lpsetupdlg->fNewDSN = (ODBC_ADD_DSN == fRequest);
lpsetupdlg->fDefault = !lstrcmpi(lpsetupdlg->ci.dsn, INI_DSN);
/*
* Display the appropriate dialog (if parent window handle
* supplied)
*/
if (hwnd)
{
/* Display the appropriate dialog (if parent window handle supplied) */
if (hwnd) {
/* Display dialog(s) */
fSuccess = (IDOK == DialogBoxParam(s_hModule,
MAKEINTRESOURCE(DLG_CONFIG),
@ -152,15 +146,11 @@ ConfigDSN(HWND hwnd,
Input : hdlg -- Dialog window handle
Output : None
--------------------------------------------------------------------------*/
void INTFUNC
CenterDialog(HWND hdlg)
void INTFUNC CenterDialog(HWND hdlg)
{
HWND hwndFrame;
RECT rcDlg,
rcScr,
rcFrame;
int cx,
cy;
RECT rcDlg, rcScr, rcFrame;
int cx, cy;
hwndFrame = GetParent(hdlg);
@ -188,10 +178,8 @@ CenterDialog(HWND hdlg)
rcDlg.left = rcDlg.right - cx;
}
if (rcDlg.left < 0)
rcDlg.left = 0;
if (rcDlg.top < 0)
rcDlg.top = 0;
if (rcDlg.left < 0) rcDlg.left = 0;
if (rcDlg.top < 0) rcDlg.top = 0;
MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE);
return;
@ -207,14 +195,13 @@ CenterDialog(HWND hdlg)
--------------------------------------------------------------------------*/
int CALLBACK
ConfigDlgProc(HWND hdlg,
int CALLBACK ConfigDlgProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (wMsg)
{
switch (wMsg) {
/* Initialize the dialog */
case WM_INITDIALOG:
{
@ -227,10 +214,7 @@ ConfigDlgProc(HWND hdlg,
SetWindowLong(hdlg, DWL_USER, lParam);
CenterDialog(hdlg); /* Center dialog */
/*
* NOTE: Values supplied in the attribute string will
* always
*/
/* NOTE: Values supplied in the attribute string will always */
/* override settings in ODBC.INI */
/* Get the rest of the common attributes */
@ -244,8 +228,7 @@ ConfigDlgProc(HWND hdlg,
SetDlgStuff(hdlg, ci);
if (lpsetupdlg->fDefault)
{
if (lpsetupdlg->fDefault) {
EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
}
@ -262,13 +245,8 @@ ConfigDlgProc(HWND hdlg,
/* Process buttons */
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
/*
* Ensure the OK button is enabled only when a data
* source name
*/
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
/* Ensure the OK button is enabled only when a data source name */
/* is entered */
case IDC_DSNAME:
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
@ -342,8 +320,7 @@ ConfigDlgProc(HWND hdlg,
Input : lpszAttributes - Pointer to attribute string
Output : None (global aAttr normally updated)
--------------------------------------------------------------------------*/
void INTFUNC
ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
{
LPCSTR lpsz;
LPCSTR lpszStart;
@ -354,8 +331,7 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
for (lpsz=lpszAttributes; *lpsz; lpsz++)
{ /* Extract key name (e.g., DSN), it must
* be terminated by an equals */
{ /* Extract key name (e.g., DSN), it must be terminated by an equals */
lpszStart = lpsz;
for (;; lpsz++)
{
@ -368,6 +344,7 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
cbKey = lpsz - lpszStart;
if (cbKey < sizeof(aszKey))
{
_fmemcpy(aszKey, lpszStart, cbKey);
aszKey[cbKey] = '\0';
}
@ -395,8 +372,7 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
Output : TRUE if successful, FALSE otherwise
--------------------------------------------------------------------------*/
BOOL INTFUNC
SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
BOOL INTFUNC SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
{
LPCSTR lpszDSN; /* Pointer to data source name */
@ -429,6 +405,8 @@ SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
/* If the data source name has changed, remove the old name */
if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
{
SQLRemoveDSNFromIni(lpsetupdlg->szDSN);
}
return TRUE;
}

View File

@ -1,3 +1,4 @@
/* Module: socket.c
*
* Description: This module contains functions for low level socket
@ -49,8 +50,7 @@ SOCK_Constructor()
rv = (SocketClass *) malloc(sizeof(SocketClass));
if (rv != NULL)
{
if (rv != NULL) {
rv->socket = (SOCKETFD) -1;
rv->buffer_filled_in = 0;
rv->buffer_filled_out = 0;
@ -70,13 +70,13 @@ SOCK_Constructor()
rv->reverse = FALSE;
}
return rv;
}
void
SOCK_Destructor(SocketClass *self)
{
if (self->socket != -1)
{
if (self->socket != -1) {
SOCK_put_char(self, 'X');
SOCK_flush_output(self);
closesocket(self->socket);
@ -89,6 +89,7 @@ SOCK_Destructor(SocketClass *self)
free(self->buffer_out);
free(self);
}
@ -99,8 +100,7 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
struct sockaddr_in sadr;
unsigned long iaddr;
if (self->socket != -1)
{
if (self->socket != -1) {
self->errornumber = SOCKET_ALREADY_CONNECTED;
self->errormsg = "Socket is already connected";
return 0;
@ -108,15 +108,13 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
memset((char *)&sadr, 0, sizeof(sadr));
/*
* If it is a valid IP address, use it. Otherwise use hostname lookup.
/* If it is a valid IP address, use it.
Otherwise use hostname lookup.
*/
iaddr = inet_addr(hostname);
if (iaddr == INADDR_NONE)
{
if (iaddr == INADDR_NONE) {
host = gethostbyname(hostname);
if (host == NULL)
{
if (host == NULL) {
self->errornumber = SOCKET_HOST_NOT_FOUND;
self->errormsg = "Could not resolve hostname.";
return 0;
@ -130,16 +128,15 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
sadr.sin_port = htons(port);
self->socket = socket(AF_INET, SOCK_STREAM, 0);
if (self->socket == -1)
{
if (self->socket == -1) {
self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
self->errormsg = "Could not create Socket.";
return 0;
}
if ( connect(self->socket, (struct sockaddr *)&(sadr),
sizeof(sadr)) < 0)
{
sizeof(sadr)) < 0) {
self->errornumber = SOCKET_COULD_NOT_CONNECT;
self->errormsg = "Could not connect to remote socket.";
closesocket(self->socket);
@ -155,8 +152,7 @@ SOCK_get_n_char(SocketClass *self, char *buffer, int len)
{
int lf;
if (!buffer)
{
if ( ! buffer) {
self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
self->errormsg = "get_n_char was called with NULL-Pointer";
return;
@ -172,8 +168,7 @@ SOCK_put_n_char(SocketClass *self, char *buffer, int len)
{
int lf;
if (!buffer)
{
if ( ! buffer) {
self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
self->errormsg = "put_n_char was called with NULL-Pointer";
return;
@ -218,8 +213,7 @@ SOCK_get_int(SocketClass *self, short len)
{
char buf[4];
switch (len)
{
switch (len) {
case 2:
SOCK_get_n_char(self, buf, len);
if (self->reverse)
@ -247,8 +241,7 @@ SOCK_put_int(SocketClass *self, int value, short len)
{
unsigned int rv;
switch (len)
{
switch (len) {
case 2:
rv = self->reverse ? value : htons( (unsigned short) value);
SOCK_put_n_char(self, (char *) &rv, 2);
@ -273,8 +266,7 @@ SOCK_flush_output(SocketClass *self)
int written;
written = send(self->socket, (char *)self->buffer_out, self->buffer_filled_out, 0);
if (written != self->buffer_filled_out)
{
if (written != self->buffer_filled_out) {
self->errornumber = SOCKET_WRITE_ERROR;
self->errormsg = "Could not flush socket buffer.";
}
@ -284,27 +276,23 @@ SOCK_flush_output(SocketClass *self)
unsigned char
SOCK_get_next_byte(SocketClass *self)
{
if (self->buffer_read_in >= self->buffer_filled_in)
{
/* there are no more bytes left in the buffer, so */
if (self->buffer_read_in >= self->buffer_filled_in) {
/* there are no more bytes left in the buffer so */
/* reload the buffer */
self->buffer_read_in = 0;
self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in,
globals.socket_buffersize, 0);
self->buffer_filled_in = recv(self->socket, (char *)self->buffer_in, globals.socket_buffersize, 0);
mylog("read %d, global_socket_buffersize=%d\n",
self->buffer_filled_in, globals.socket_buffersize);
mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize);
if (self->buffer_filled_in < 0)
{
if (self->buffer_filled_in < 0) {
self->errornumber = SOCKET_READ_ERROR;
self->errormsg = "Error while reading from the socket.";
self->buffer_filled_in = 0;
return 0;
}
if (self->buffer_filled_in == 0)
{
if (self->buffer_filled_in == 0) {
self->errornumber = SOCKET_CLOSED;
self->errormsg = "Socket has been closed.";
self->buffer_filled_in = 0;
@ -321,12 +309,10 @@ SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
self->buffer_out[self->buffer_filled_out++] = next_byte;
if (self->buffer_filled_out == globals.socket_buffersize)
{
if (self->buffer_filled_out == globals.socket_buffersize) {
/* buffer is full, so write it out */
bytes_sent = send(self->socket, (char *)self->buffer_out, globals.socket_buffersize, 0);
if (bytes_sent != globals.socket_buffersize)
{
if (bytes_sent != globals.socket_buffersize) {
self->errornumber = SOCKET_WRITE_ERROR;
self->errormsg = "Error while writing to the socket.";
}

View File

@ -29,7 +29,6 @@
#ifndef _IN_ADDR_T
#define _IN_ADDR_T
typedef unsigned int in_addr_t;
#endif
#define INADDR_NONE ((in_addr_t)-1)
#endif
@ -53,8 +52,7 @@ typedef unsigned int in_addr_t;
#define SOCKET_CLOSED 10
struct SocketClass_
{
struct SocketClass_ {
int buffer_filled_in;
int buffer_filled_out;
@ -67,8 +65,7 @@ struct SocketClass_
char *errormsg;
int errornumber;
char reverse; /* used to handle Postgres 6.2 protocol
* (reverse byte order) */
char reverse; /* used to handle Postgres 6.2 protocol (reverse byte order) */
};

View File

@ -1,3 +1,4 @@
/* Module: statement.c
*
* Description: This module contains functions related to creating
@ -45,48 +46,24 @@ extern GLOBAL_VALUES globals;
#define PRN_NULLCHECK
/* Map sql commands to statement types */
static struct
{
static struct {
int type;
char *s;
} Statement_Type[] =
{
{
STMT_TYPE_SELECT, "SELECT"
},
{
STMT_TYPE_INSERT, "INSERT"
},
{
STMT_TYPE_UPDATE, "UPDATE"
},
{
STMT_TYPE_DELETE, "DELETE"
},
{
STMT_TYPE_CREATE, "CREATE"
},
{
STMT_TYPE_ALTER, "ALTER"
},
{
STMT_TYPE_DROP, "DROP"
},
{
STMT_TYPE_GRANT, "GRANT"
},
{
STMT_TYPE_REVOKE, "REVOKE"
},
{
0, NULL
}
} Statement_Type[] = {
{ STMT_TYPE_SELECT, "SELECT" },
{ STMT_TYPE_INSERT, "INSERT" },
{ STMT_TYPE_UPDATE, "UPDATE" },
{ STMT_TYPE_DELETE, "DELETE" },
{ STMT_TYPE_CREATE, "CREATE" },
{ STMT_TYPE_ALTER, "ALTER" },
{ STMT_TYPE_DROP, "DROP" },
{ STMT_TYPE_GRANT, "GRANT" },
{ STMT_TYPE_REVOKE, "REVOKE" },
{ 0, NULL }
};
RETCODE SQL_API
SQLAllocStmt(HDBC hdbc,
RETCODE SQL_API SQLAllocStmt(HDBC hdbc,
HSTMT FAR *phstmt)
{
static char *func="SQLAllocStmt";
@ -95,8 +72,7 @@ SQLAllocStmt(HDBC hdbc,
mylog("%s: entering...\n", func);
if (!conn)
{
if( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
@ -105,8 +81,7 @@ SQLAllocStmt(HDBC hdbc,
mylog("**** SQLAllocStmt: hdbc = %u, stmt = %u\n", hdbc, stmt);
if (!stmt)
{
if ( ! stmt) {
conn->errornumber = CONN_STMT_ALLOC_ERROR;
conn->errormsg = "No more memory to allocate a further SQL-statement";
*phstmt = SQL_NULL_HSTMT;
@ -114,8 +89,7 @@ SQLAllocStmt(HDBC hdbc,
return SQL_ERROR;
}
if (!CC_add_statement(conn, stmt))
{
if ( ! CC_add_statement(conn, stmt)) {
conn->errormsg = "Maximum number of connections exceeded.";
conn->errornumber = CONN_STMT_ALLOC_ERROR;
CC_log_error(func, "", conn);
@ -126,8 +100,7 @@ SQLAllocStmt(HDBC hdbc,
*phstmt = (HSTMT) stmt;
/*
* Copy default statement options based from Connection options
/* Copy default statement options based from Connection options
*/
stmt->options = conn->stmtOptions;
@ -139,8 +112,7 @@ SQLAllocStmt(HDBC hdbc,
}
RETCODE SQL_API
SQLFreeStmt(HSTMT hstmt,
RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
UWORD fOption)
{
static char *func="SQLFreeStmt";
@ -148,31 +120,25 @@ SQLFreeStmt(HSTMT hstmt,
mylog("%s: entering...hstmt=%u, fOption=%d\n", func, hstmt, fOption);
if (!stmt)
{
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (fOption == SQL_DROP)
{
if (fOption == SQL_DROP) {
ConnectionClass *conn = stmt->hdbc;
/* Remove the statement from the connection's statement list */
if (conn)
{
if (!CC_remove_statement(conn, stmt))
{
if ( conn) {
if ( ! CC_remove_statement(conn, stmt)) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Statement is currently executing a transaction.";
SC_log_error(func, "", stmt);
return SQL_ERROR; /* stmt may be executing a
* transaction */
return SQL_ERROR; /* stmt may be executing a transaction */
}
/* Free any cursors and discard any result info */
if (stmt->result)
{
if (stmt->result) {
QR_Destructor(stmt->result);
stmt->result = NULL;
}
@ -180,24 +146,23 @@ SQLFreeStmt(HSTMT hstmt,
/* Destroy the statement and free any results, cursors, etc. */
SC_Destructor(stmt);
}
else if (fOption == SQL_UNBIND)
} else if (fOption == SQL_UNBIND) {
SC_unbind_cols(stmt);
else if (fOption == SQL_CLOSE)
{
} else if (fOption == SQL_CLOSE) {
/* this should discard all the results, but leave the statement */
/* itself in place (it can be executed again) */
if (!SC_recycle_statement(stmt))
{
if (!SC_recycle_statement(stmt)) {
/* errormsg passed in above */
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
else if (fOption == SQL_RESET_PARAMS)
} else if(fOption == SQL_RESET_PARAMS) {
SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
else
{
} else {
stmt->errormsg = "Invalid option passed to SQLFreeStmt.";
stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR;
SC_log_error(func, "", stmt);
@ -232,8 +197,7 @@ SC_Constructor(void)
StatementClass *rv;
rv = (StatementClass *) malloc(sizeof(StatementClass));
if (rv)
{
if (rv) {
rv->hdbc = NULL; /* no connection associated yet */
rv->phstmt = NULL;
rv->result = NULL;
@ -290,16 +254,15 @@ SC_Constructor(void)
char
SC_Destructor(StatementClass *self)
{
mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc);
if (STMT_EXECUTING == self->status)
{
if (STMT_EXECUTING == self->status) {
self->errornumber = STMT_SEQUENCE_ERROR;
self->errormsg = "Statement is currently executing a transaction.";
return FALSE;
}
if (self->result)
{
if (self->result) {
if ( ! self->hdbc)
self->result->conn = NULL; /* prevent any dbase activity */
@ -311,38 +274,29 @@ SC_Destructor(StatementClass *self)
SC_free_params(self, STMT_FREE_PARAMS_ALL);
/*
* the memory pointed to by the bindings is not deallocated by the
* driver
*/
/*
* by by the application that uses that driver, so we don't have to
* care
*/
/* the memory pointed to by the bindings is not deallocated by the driver */
/* by by the application that uses that driver, so we don't have to care */
/* about that here. */
if (self->bindings)
free(self->bindings);
/* Free the parsed table information */
if (self->ti)
{
if (self->ti) {
int i;
for (i = 0; i < self->ntab; i++)
for (i = 0; i < self->ntab; i++) {
free(self->ti[i]);
}
free(self->ti);
}
/* Free the parsed field information */
if (self->fi)
{
if (self->fi) {
int i;
for (i = 0; i < self->nfld; i++)
for (i = 0; i < self->nfld; i++) {
free(self->fi[i]);
}
free(self->fi);
}
@ -367,18 +321,15 @@ SC_free_params(StatementClass *self, char option)
if( ! self->parameters)
return;
for (i = 0; i < self->parameters_allocated; i++)
{
if (self->parameters[i].data_at_exec == TRUE)
{
if (self->parameters[i].EXEC_used)
{
for (i = 0; i < self->parameters_allocated; i++) {
if (self->parameters[i].data_at_exec == TRUE) {
if (self->parameters[i].EXEC_used) {
free(self->parameters[i].EXEC_used);
self->parameters[i].EXEC_used = NULL;
}
if (self->parameters[i].EXEC_buffer)
{
if (self->parameters[i].EXEC_buffer) {
if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
free(self->parameters[i].EXEC_buffer);
self->parameters[i].EXEC_buffer = NULL;
@ -389,8 +340,7 @@ SC_free_params(StatementClass *self, char option)
self->current_exec_param = -1;
self->put_data = FALSE;
if (option == STMT_FREE_PARAMS_ALL)
{
if (option == STMT_FREE_PARAMS_ALL) {
free(self->parameters);
self->parameters = NULL;
self->parameters_allocated = 0;
@ -429,8 +379,7 @@ SC_recycle_statement(StatementClass *self)
mylog("recycle statement: self= %u\n", self);
/* This would not happen */
if (self->status == STMT_EXECUTING)
{
if (self->status == STMT_EXECUTING) {
self->errornumber = STMT_SEQUENCE_ERROR;
self->errormsg = "Statement is currently executing a transaction.";
return FALSE;
@ -440,8 +389,7 @@ SC_recycle_statement(StatementClass *self)
self->errornumber = 0;
self->errormsg_created = FALSE;
switch (self->status)
{
switch (self->status) {
case STMT_ALLOCATED:
/* this statement does not need to be recycled */
return TRUE;
@ -450,15 +398,12 @@ SC_recycle_statement(StatementClass *self)
break;
case STMT_PREMATURE:
/*
* Premature execution of the statement might have caused the
* start of a transaction. If so, we have to rollback that
* transaction.
/* Premature execution of the statement might have caused the start of a transaction.
If so, we have to rollback that transaction.
*/
conn = SC_get_conn(self);
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
{
if ( ! CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) {
CC_send_query(conn, "ABORT", NULL);
CC_set_no_trans(conn);
}
@ -474,12 +419,11 @@ SC_recycle_statement(StatementClass *self)
}
/* Free the parsed table information */
if (self->ti)
{
if (self->ti) {
int i;
for (i = 0; i < self->ntab; i++)
for (i = 0; i < self->ntab; i++) {
free(self->ti[i]);
}
free(self->ti);
self->ti = NULL;
@ -487,12 +431,11 @@ SC_recycle_statement(StatementClass *self)
}
/* Free the parsed field information */
if (self->fi)
{
if (self->fi) {
int i;
for (i = 0; i < self->nfld; i++)
for (i = 0; i < self->nfld; i++) {
free(self->fi[i]);
}
free(self->fi);
self->fi = NULL;
self->nfld = 0;
@ -500,8 +443,7 @@ SC_recycle_statement(StatementClass *self)
self->parse_status = STMT_PARSE_NONE;
/* Free any cursors */
if (self->result)
{
if (self->result) {
QR_Destructor(self->result);
self->result = NULL;
}
@ -537,16 +479,15 @@ SC_recycle_statement(StatementClass *self)
void
SC_pre_execute(StatementClass *self)
{
mylog("SC_pre_execute: status = %d\n", self->status);
if (self->status == STMT_READY)
{
if (self->status == STMT_READY) {
mylog(" preprocess: status = READY\n");
SQLExecute(self);
if (self->status == STMT_FINISHED)
{
if (self->status == STMT_FINISHED) {
mylog(" preprocess: after status = FINISHED, so set PREMATURE\n");
self->status = STMT_PREMATURE;
}
@ -559,8 +500,7 @@ SC_unbind_cols(StatementClass *self)
{
Int2 lf;
for (lf = 0; lf < self->bindings_allocated; lf++)
{
for(lf = 0; lf < self->bindings_allocated; lf++) {
self->bindings[lf].data_left = -1;
self->bindings[lf].buflen = 0;
self->bindings[lf].buffer = NULL;
@ -601,18 +541,15 @@ SC_create_errormsg(StatementClass *self)
else if (self->errormsg)
strcpy(msg, self->errormsg);
if (conn)
{
if (conn) {
SocketClass *sock = conn->sock;
if (conn->errormsg && conn->errormsg[0] != '\0')
{
if (conn->errormsg && conn->errormsg[0] != '\0') {
pos = strlen(msg);
sprintf(&msg[pos], ";\n%s", conn->errormsg);
}
if (sock && sock->errormsg && sock->errormsg[0] != '\0')
{
if (sock && sock->errormsg && sock->errormsg[0] != '\0') {
pos = strlen(msg);
sprintf(&msg[pos], ";\n%s", sock->errormsg);
}
@ -627,14 +564,12 @@ SC_get_error(StatementClass *self, int *number, char **message)
char rv;
/* Create a very informative errormsg if it hasn't been done yet. */
if (!self->errormsg_created)
{
if ( ! self->errormsg_created) {
self->errormsg = SC_create_errormsg(self);
self->errormsg_created = TRUE;
}
if (self->errornumber)
{
if ( self->errornumber) {
*number = self->errornumber;
*message = self->errormsg;
self->errormsg = NULL;
@ -661,14 +596,11 @@ SC_fetch(StatementClass *self)
{
static char *func = "SC_fetch";
QResultClass *res = self->result;
int retval,
result;
Int2 num_cols,
lf;
int retval, result;
Int2 num_cols, lf;
Oid type;
char *value;
ColumnInfoClass *ci;
/* TupleField *tupleField; */
self->last_fetch_count = 0;
@ -676,15 +608,13 @@ SC_fetch(StatementClass *self)
mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, globals.use_declarefetch);
if (self->manual_result || !globals.use_declarefetch)
{
if (self->currTuple >= QR_get_num_tuples(res) - 1 ||
(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
{
if ( self->manual_result || ! globals.use_declarefetch) {
/*
* if at the end of the tuples, return "no data found" and set
* the cursor past the end of the result set
if (self->currTuple >= QR_get_num_tuples(res) -1 ||
(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) {
/* if at the end of the tuples, return "no data found"
and set the cursor past the end of the result set
*/
self->currTuple = QR_get_num_tuples(res);
return SQL_NO_DATA_FOUND;
@ -693,20 +623,18 @@ SC_fetch(StatementClass *self)
mylog("**** SQLFetch: manual_result\n");
(self->currTuple)++;
}
else
{
else {
/* read from the cache or the physical next tuple */
retval = QR_next_tuple(res);
if (retval < 0)
{
if (retval < 0) {
mylog("**** SQLFetch: end_tuples\n");
return SQL_NO_DATA_FOUND;
}
else if (retval > 0)
(self->currTuple)++; /* all is well */
else
{
else {
mylog("SQLFetch: error\n");
self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Error fetching next row";
@ -720,14 +648,12 @@ SC_fetch(StatementClass *self)
result = SQL_SUCCESS;
self->last_fetch_count = 1;
/*
* If the bookmark column was bound then return a bookmark. Since this
* is used with SQLExtendedFetch, and the rowset size may be greater
* than 1, and an application can use row or column wise binding, use
* the code in copy_and_convert_field() to handle that.
/* If the bookmark column was bound then return a bookmark.
Since this is used with SQLExtendedFetch, and the rowset size
may be greater than 1, and an application can use row or column wise
binding, use the code in copy_and_convert_field() to handle that.
*/
if (self->bookmark.buffer)
{
if (self->bookmark.buffer) {
char buf[32];
sprintf(buf, "%ld", SC_get_bookmark(self));
@ -735,15 +661,14 @@ SC_fetch(StatementClass *self)
SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used);
}
for (lf = 0; lf < num_cols; lf++)
{
for (lf=0; lf < num_cols; lf++) {
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
/* reset for SQLGetData */
self->bindings[lf].data_left = -1;
if (self->bindings[lf].buffer != NULL)
{
if (self->bindings[lf].buffer != NULL) {
/* this column has a binding */
/* type = QR_get_field_type(res, lf); */
@ -751,15 +676,15 @@ SC_fetch(StatementClass *self)
mylog("type = %d\n", type);
if (self->manual_result)
{
if (self->manual_result) {
value = QR_get_value_manual(res, self->currTuple, lf);
mylog("manual_result\n");
}
else if (globals.use_declarefetch)
value = QR_get_value_backend(res, lf);
else
else {
value = QR_get_value_backend_row(res, self->currTuple, lf);
}
mylog("value = '%s'\n", (value==NULL)?"<NULL>":value);
@ -767,8 +692,7 @@ SC_fetch(StatementClass *self)
mylog("copy_and_convert: retval = %d\n", retval);
switch (retval)
{
switch(retval) {
case COPY_OK:
break; /* OK, do next bound column */
@ -792,8 +716,7 @@ SC_fetch(StatementClass *self)
result = SQL_SUCCESS_WITH_INFO;
break;
case COPY_GENERAL_ERROR: /* error msg already
* filled in */
case COPY_GENERAL_ERROR: /* error msg already filled in */
SC_log_error(func, "", self);
result = SQL_ERROR;
break;
@ -816,39 +739,35 @@ SC_fetch(StatementClass *self)
}
RETCODE
SC_execute(StatementClass *self)
RETCODE SC_execute(StatementClass *self)
{
static char *func="SC_execute";
ConnectionClass *conn;
QResultClass *res;
char ok,
was_ok,
was_nonfatal;
Int2 oldstatus,
numcols;
char ok, was_ok, was_nonfatal;
Int2 oldstatus, numcols;
QueryInfo qi;
conn = SC_get_conn(self);
/* Begin a transaction if one is not already in progress */
/*
* Basically we don't have to begin a transaction in autocommit mode
* because Postgres backend runs in autocomit mode. We issue "BEGIN"
* in the following cases. 1) we use declare/fetch and the statement
* is SELECT (because declare/fetch must be called in a transaction).
* 2) we are not in autocommit state and the statement is of type
* UPDATE.
Basically we don't have to begin a transaction in
autocommit mode because Postgres backend runs in
autocomit mode.
We issue "BEGIN" in the following cases.
1) we use declare/fetch and the statement is SELECT
(because declare/fetch must be called in a transaction).
2) we are not in autocommit state and the statement
is of type UPDATE.
*/
if ( ! self->internal && ! CC_is_in_trans(conn) &&
((globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || (!CC_is_in_autocommit(conn) && STMT_UPDATE(self))))
{
((globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || (! CC_is_in_autocommit(conn) && STMT_UPDATE(self)))) {
mylog(" about to begin a transaction on statement = %u\n", self);
res = CC_send_query(conn, "BEGIN", NULL);
if (!res)
{
if ( ! res) {
self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self);
@ -861,8 +780,7 @@ SC_execute(StatementClass *self)
QR_Destructor(res);
if (!ok)
{
if (!ok) {
self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self);
@ -872,20 +790,18 @@ SC_execute(StatementClass *self)
CC_set_in_trans(conn);
}
oldstatus = conn->status;
conn->status = CONN_EXECUTING;
self->status = STMT_EXECUTING;
/* If it's a SELECT statement, use a cursor. */
/*
* Note that the declare cursor has already been prepended to the
* statement
*/
/* Note that the declare cursor has already been prepended to the statement */
/* in copy_statement... */
if (self->statement_type == STMT_TYPE_SELECT)
{
if (self->statement_type == STMT_TYPE_SELECT) {
char fetch[128];
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
@ -895,61 +811,55 @@ SC_execute(StatementClass *self)
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
if (globals.use_declarefetch && self->result != NULL &&
QR_command_successful(self->result))
{
QR_command_successful(self->result)) {
QR_Destructor(self->result);
/*
* That worked, so now send the fetch to start getting data
* back
*/
/* That worked, so now send the fetch to start getting data back */
qi.result_in = NULL;
qi.cursor = self->cursor_name;
qi.row_size = globals.fetch_max;
/*
* Most likely the rowset size will not be set by the
* application until after the statement is executed, so might
* as well use the cache size. The qr_next_tuple() function
* will correct for any discrepancies in sizes and adjust the
* cache accordingly.
/* Most likely the rowset size will not be set by the application until
after the statement is executed, so might as well use the cache size.
The qr_next_tuple() function will correct for any discrepancies in
sizes and adjust the cache accordingly.
*/
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
self->result = CC_send_query( conn, fetch, &qi);
}
mylog(" done sending the query:\n");
}
else
{ /* not a SELECT statement so don't use a
* cursor */
else { /* not a SELECT statement so don't use a cursor */
mylog(" it's NOT a select statement: stmt=%u\n", self);
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
/*
* We shouldn't send COMMIT. Postgres backend does the autocommit
* if neccessary. (Zoltan, 04/26/2000)
/* We shouldn't send COMMIT. Postgres backend does the
autocommit if neccessary. (Zoltan, 04/26/2000)
*/
/*
* Even in case of autocommit, started transactions must be
* committed. (Hiroshi, 09/02/2001)
/* Even in case of autocommit, started transactions
must be committed. (Hiroshi, 09/02/2001)
*/
if (!self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn) && STMT_UPDATE(self))
{
if ( ! self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn) && STMT_UPDATE(self)) {
res = CC_send_query(conn, "COMMIT", NULL);
QR_Destructor(res);
CC_set_no_trans(conn);
}
}
conn->status = oldstatus;
self->status = STMT_FINISHED;
/* Check the status of the result */
if (self->result)
{
if (self->result) {
was_ok = QR_command_successful(self->result);
was_nonfatal = QR_command_nonfatal(self->result);
@ -958,8 +868,7 @@ SC_execute(StatementClass *self)
else
self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;
self->currTuple = -1; /* set cursor before the first tuple in
* the list */
self->currTuple = -1; /* set cursor before the first tuple in the list */
self->current_col = -1;
self->rowset_start = -1;
@ -967,11 +876,9 @@ SC_execute(StatementClass *self)
numcols = QR_NumResultCols(self->result);
/* now allocate the array to hold the binding info */
if (numcols > 0)
{
if (numcols > 0) {
extend_bindings(self, numcols);
if (self->bindings == NULL)
{
if (self->bindings == NULL) {
self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "Could not get enough free memory to store the binding information";
SC_log_error(func, "", self);
@ -981,25 +888,18 @@ SC_execute(StatementClass *self)
/* in autocommit mode declare/fetch error must be aborted */
if ( ! was_ok && ! self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
CC_abort(conn);
}
else
{ /* Bad Error -- The error message will be
* in the Connection */
} else { /* Bad Error -- The error message will be in the Connection */
if (self->statement_type == STMT_TYPE_CREATE)
{
if (self->statement_type == STMT_TYPE_CREATE) {
self->errornumber = STMT_CREATE_TABLE_ERROR;
self->errormsg = "Error creating the table";
/*
* This would allow the table to already exists, thus
* appending rows to it. BUT, if the table didn't have the
* same attributes, it would fail. return
* SQL_SUCCESS_WITH_INFO;
/* This would allow the table to already exists, thus appending
rows to it. BUT, if the table didn't have the same attributes,
it would fail.
return SQL_SUCCESS_WITH_INFO;
*/
}
else
{
else {
self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Error while executing the query";
}
@ -1011,8 +911,7 @@ SC_execute(StatementClass *self)
if (self->errornumber == STMT_OK)
return SQL_SUCCESS;
else
{
else {
/* Modified, 2000-04-29, Zoltan */
if (self->errornumber == STMT_INFO_ONLY)
self->errormsg = "Error while executing the query (non-fatal)";
@ -1029,8 +928,7 @@ SC_log_error(char *func, char *desc, StatementClass *self)
#ifdef PRN_NULLCHECK
#define nullcheck(a) (a ? a : "(NULL)")
#endif
if (self)
{
if (self) {
qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
qlog(" ------------------------------------------------------------\n");
@ -1047,10 +945,8 @@ SC_log_error(char *func, char *desc, StatementClass *self)
qlog(" ----------------QResult Info -------------------------------\n");
if (self->result)
{
if (self->result) {
QResultClass *res = self->result;
qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);
qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor));
qlog(" message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice));
@ -1064,3 +960,4 @@ SC_log_error(char *func, char *desc, StatementClass *self)
qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
#undef PRN_NULLCHECK
}

View File

@ -33,28 +33,21 @@
#define TRUE (BOOL)1
#endif
typedef enum
{
STMT_ALLOCATED, /* The statement handle is allocated, but
* not used so far */
typedef enum {
STMT_ALLOCATED, /* The statement handle is allocated, but not used so far */
STMT_READY, /* the statement is waiting to be executed */
STMT_PREMATURE, /* ODBC states that it is legal to call
* e.g. SQLDescribeCol before a call to
* SQLExecute, but after SQLPrepare. To
* get all the necessary information in
* such a case, we simply execute the
* query _before_ the actual call to
* SQLExecute, so that statement is
* considered to be "premature". */
STMT_PREMATURE, /* ODBC states that it is legal to call e.g. SQLDescribeCol before
a call to SQLExecute, but after SQLPrepare. To get all the necessary
information in such a case, we simply execute the query _before_ the
actual call to SQLExecute, so that statement is considered to be "premature".
*/
STMT_FINISHED, /* statement execution has finished */
STMT_EXECUTING /* statement execution is still going on */
} STMT_Status;
#define STMT_TRUNCATED (-2)
#define STMT_INFO_ONLY (-1) /* not an error message, just a
* notification to be returned by SQLError */
#define STMT_OK 0 /* will be interpreted as "no error
* pending" */
#define STMT_TRUNCATED -2
#define STMT_INFO_ONLY -1 /* not an error message, just a notification to be returned by SQLError */
#define STMT_OK 0 /* will be interpreted as "no error pending" */
#define STMT_EXEC_ERROR 1
#define STMT_STATUS_ERROR 2
#define STMT_SEQUENCE_ERROR 3
@ -84,8 +77,7 @@ typedef enum
#define STMT_BAD_ERROR 27
/* statement types */
enum
{
enum {
STMT_TYPE_UNKNOWN = -2,
STMT_TYPE_OTHER = -1,
STMT_TYPE_SELECT = 0,
@ -103,8 +95,7 @@ enum
/* Parsing status */
enum
{
enum {
STMT_PARSE_NONE = 0,
STMT_PARSE_COMPLETE,
STMT_PARSE_INCOMPLETE,
@ -112,22 +103,19 @@ enum
};
/* Result style */
enum
{
enum {
STMT_FETCH_NONE = 0,
STMT_FETCH_NORMAL,
STMT_FETCH_EXTENDED,
};
typedef struct
{
typedef struct {
COL_INFO *col_info; /* cached SQLColumns info for this table */
char name[MAX_TABLE_LEN+1];
char alias[MAX_TABLE_LEN+1];
} TABLE_INFO;
typedef struct
{
typedef struct {
TABLE_INFO *ti; /* resolve to explicit table names */
int precision;
int display_size;
@ -146,10 +134,8 @@ typedef struct
/******** Statement Handle ***********/
struct StatementClass_
{
ConnectionClass *hdbc; /* pointer to ConnectionClass this
* statement belongs to */
struct StatementClass_ {
ConnectionClass *hdbc; /* pointer to ConnectionClass this statement belongs to */
QResultClass *result; /* result of the current statement */
HSTMT FAR *phstmt;
StatementOptions options;
@ -167,22 +153,15 @@ struct StatementClass_
int parameters_allocated;
ParameterInfoClass *parameters;
Int4 currTuple; /* current absolute row number (GetData,
* SetPos, SQLFetch) */
int save_rowset_size; /* saved rowset size in case of
* change/FETCH_NEXT */
int rowset_start; /* start of rowset (an absolute row
* number) */
int bind_row; /* current offset for Multiple row/column
* binding */
int last_fetch_count; /* number of rows retrieved in
* last fetch/extended fetch */
int current_col; /* current column for GetData -- used to
* handle multiple calls */
Int4 currTuple; /* current absolute row number (GetData, SetPos, SQLFetch) */
int save_rowset_size; /* saved rowset size in case of change/FETCH_NEXT */
int rowset_start; /* start of rowset (an absolute row number) */
int bind_row; /* current offset for Multiple row/column binding */
int last_fetch_count; /* number of rows retrieved in last fetch/extended fetch */
int current_col; /* current column for GetData -- used to handle multiple calls */
int lobj_fd; /* fd of the current large object */
char *statement; /* if non--null pointer to the SQL
* statement that has been executed */
char *statement; /* if non--null pointer to the SQL statement that has been executed */
TABLE_INFO **ti;
FIELD_INFO **fi;
@ -193,25 +172,19 @@ struct StatementClass_
int statement_type; /* According to the defines above */
int data_at_exec; /* Number of params needing SQLPutData */
int current_exec_param; /* The current parameter for
* SQLPutData */
int current_exec_param; /* The current parameter for SQLPutData */
char put_data; /* Has SQLPutData been called yet? */
char errormsg_created; /* has an informative error msg
* been created? */
char errormsg_created; /* has an informative error msg been created? */
char manual_result; /* Is the statement result manually built? */
char prepare; /* is this statement a prepared statement
* or direct */
char prepare; /* is this statement a prepared statement or direct */
char internal; /* Is this statement being called
* internally? */
char internal; /* Is this statement being called internally? */
char cursor_name[MAX_CURSOR_LEN+1];
char stmt_with_params[STD_STATEMENT_LEN]; /* statement after
* parameter
* substitution */
char stmt_with_params[STD_STATEMENT_LEN]; /* statement after parameter substitution */
};

View File

@ -1,3 +1,4 @@
/* Module: tuple.c
*
* Description: This module contains functions for setting the data for individual
@ -18,15 +19,13 @@
#include <string.h>
#include <stdlib.h>
void
set_tuplefield_null(TupleField *tuple_field)
void set_tuplefield_null(TupleField *tuple_field)
{
tuple_field->len = 0;
tuple_field->value = NULL; /* strdup(""); */
}
void
set_tuplefield_string(TupleField *tuple_field, char *string)
void set_tuplefield_string(TupleField *tuple_field, char *string)
{
tuple_field->len = strlen(string);
tuple_field->value = malloc(strlen(string)+1);
@ -34,8 +33,7 @@ set_tuplefield_string(TupleField *tuple_field, char *string)
}
void
set_tuplefield_int2(TupleField *tuple_field, Int2 value)
void set_tuplefield_int2(TupleField *tuple_field, Int2 value)
{
char buffer[10];
@ -47,8 +45,7 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
tuple_field->value = strdup(buffer);
}
void
set_tuplefield_int4(TupleField *tuple_field, Int4 value)
void set_tuplefield_int4(TupleField *tuple_field, Int4 value)
{
char buffer[15];

View File

@ -17,17 +17,14 @@
#include "psqlodbc.h"
/* Used by backend data AND manual result sets */
struct TupleField_
{
struct TupleField_ {
Int4 len; /* length of the current Tuple */
void *value; /* an array representing the value */
};
/* Used ONLY for manual result sets */
struct TupleNode_
{
struct TupleNode_ *prev,
*next;
struct TupleNode_ {
struct TupleNode_ *prev, *next;
TupleField tuple[1];
};

View File

@ -1,3 +1,4 @@
/* Module: tuplelist.c
*
* Description: This module contains functions for creating a manual result set
@ -23,8 +24,8 @@ TL_Constructor(UInt4 fieldcnt)
mylog("in TL_Constructor\n");
rv = (TupleListClass *) malloc(sizeof(TupleListClass));
if (rv)
{
if (rv) {
rv->num_fields = fieldcnt;
rv->num_tuples = 0;
rv->list_start = NULL;
@ -42,17 +43,16 @@ void
TL_Destructor(TupleListClass *self)
{
int lf;
TupleNode *node,
*tp;
TupleNode *node, *tp;
mylog("TupleList: in DESTRUCTOR\n");
node = self->list_start;
while (node != NULL)
{
while(node != NULL) {
for (lf=0; lf < self->num_fields; lf++)
if (node->tuple[lf].value != NULL)
if (node->tuple[lf].value != NULL) {
free(node->tuple[lf].value);
}
tp = node->next;
free(node);
node = tp;
@ -68,10 +68,8 @@ void *
TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
{
Int4 lf;
Int4 delta,
from_end;
char end_is_closer,
start_is_closer;
Int4 delta, from_end;
char end_is_closer, start_is_closer;
TupleNode *rv;
if (self->last_indexed == -1)
@ -87,10 +85,9 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
/* illegel field number range */
return NULL;
/*
* check if we are accessing the same tuple that was used in the last
* fetch (e.g: for fetching all the fields one after another. Do this
* to speed things up
/* check if we are accessing the same tuple that was used in
the last fetch (e.g: for fetching all the fields one after
another. Do this to speed things up
*/
if (tupleno == self->last_indexed)
return self->lastref->tuple[fieldno].value;
@ -98,76 +95,56 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
/* now for the tricky part... */
/*
* Since random access is quite inefficient for linked lists we use
* the lastref pointer that points to the last element referenced by a
* get_fieldval() call in conjunction with the its index number that
* is stored in last_indexed. (So we use some locality of reference
* principle to speed things up)
Since random access is quite inefficient for linked lists we use
the lastref pointer that points to the last element referenced
by a get_fieldval() call in conjunction with the its index number
that is stored in last_indexed. (So we use some locality of
reference principle to speed things up)
*/
delta = tupleno - self->last_indexed;
/* if delta is positive, we have to go forward */
/*
* now check if we are closer to the start or the end of the list than
* to our last_indexed pointer
/* now check if we are closer to the start or the end of the list
than to our last_indexed pointer
*/
from_end = (self->num_tuples - 1) - tupleno;
start_is_closer = labs(delta) > tupleno;
/*
* true if we are closer to the start of the list than to the
* last_indexed pointer
/* true if we are closer to the start of the list than to the
last_indexed pointer
*/
end_is_closer = labs(delta) > from_end;
/* true if we are closer at the end of the list */
if (end_is_closer)
{
if (end_is_closer) {
/* scanning from the end is the shortest way. so we do that... */
rv = self->list_end;
for (lf=0; lf < from_end; lf++)
rv = rv->prev;
}
else if (start_is_closer)
{
/*
* the shortest way is to start the search from the head of the
* list
*/
} else if (start_is_closer) {
/* the shortest way is to start the search from the head of the list */
rv = self->list_start;
for (lf=0; lf < tupleno; lf++)
rv = rv->next;
}
else
{
} else {
/* the closest way is starting from our lastref - pointer */
rv = self->lastref;
/*
* at first determine whether we have to search forward or
* backwards
*/
if (delta < 0)
{
/* at first determine whether we have to search forward or backwards */
if (delta < 0) {
/* we have to search backwards */
for(lf=0; lf < (-1)*delta; lf++)
rv = rv->prev;
}
else
{
} else {
/* ok, we have to search forward... */
for (lf=0; lf < delta; lf++)
rv = rv->next;
}
}
/*
* now we have got our return pointer, so update the lastref and the
* last_indexed values
/* now we have got our return pointer, so update the lastref
and the last_indexed values
*/
self->lastref = rv;
self->last_indexed = tupleno;
@ -180,29 +157,22 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
char
TL_add_tuple(TupleListClass *self, TupleNode *new_field)
{
/*
* we append the tuple at the end of the doubly linked list of the
* tuples we have already read in
/* we append the tuple at the end of the doubly linked list
of the tuples we have already read in
*/
new_field->prev = NULL;
new_field->next = NULL;
if (self->list_start == NULL)
{
if (self->list_start == NULL) {
/* the list is empty, we have to add the first tuple */
self->list_start = new_field;
self->list_end = new_field;
self->lastref = new_field;
self->last_indexed = 0;
}
else
{
/*
* there is already an element in the list, so add the new one at
* the end of the list
} else {
/* there is already an element in the list, so add the new
one at the end of the list
*/
self->list_end->next = new_field;
new_field->prev = self->list_end;
@ -213,3 +183,5 @@ TL_add_tuple(TupleListClass *self, TupleNode *new_field)
/* this method of building a list cannot fail, so we return 1 */
return 1;
}

View File

@ -15,13 +15,10 @@
#include "psqlodbc.h"
struct TupleListClass_
{
struct TupleListClass_ {
Int4 num_fields;
Int4 num_tuples;
TupleNode *list_start,
*list_end,
*lastref;
TupleNode *list_start, *list_end, *lastref;
Int4 last_indexed;
};