ODBC source code cleanup patch. Should match rest of PostgreSQL code better.

This commit is contained in:
Bruce Momjian 2001-05-08 17:06:18 +00:00
parent 062a79a990
commit 296e7ba2ba
24 changed files with 990 additions and 1182 deletions

View File

@ -1,4 +1,5 @@
/* Module: bind.c
/*-------
* Module: bind.c
*
* Description: This module contains routines related to binding
* columns and parameters.
@ -9,7 +10,7 @@
* SQLParamOptions(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#ifdef HAVE_CONFIG_H
@ -33,8 +34,8 @@
#include "sqlext.h"
#endif
/* Bind parameters on a statement handle */
/* Bind parameters on a statement handle */
RETCODE SQL_API
SQLBindParameter(
HSTMT hstmt,
@ -112,8 +113,8 @@ SQLBindParameter(
}
}
ipar--; /* use zero based column numbers for the
* below part */
/* use zero based column numbers for the below part */
ipar--;
/* store the given info */
stmt->parameters[ipar].buflen = cbValueMax;
@ -158,9 +159,8 @@ SQLBindParameter(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* Associate a user-supplied buffer with a database column. */
/* Associate a user-supplied buffer with a database column. */
RETCODE SQL_API
SQLBindCol(
HSTMT hstmt,
@ -197,7 +197,6 @@ SQLBindCol(
/* If the bookmark column is being bound, then just save it */
if (icol == 0)
{
if (rgbValue == NULL)
{
stmt->bookmark.buffer = NULL;
@ -220,10 +219,12 @@ SQLBindCol(
return SQL_SUCCESS;
}
/* allocate enough bindings if not already done */
/* Most likely, execution of a statement would have setup the */
/* necessary bindings. But some apps call BindCol before any */
/* statement is executed. */
/*
* Allocate enough bindings if not already done.
* Most likely, execution of a statement would have setup the
* necessary bindings. But some apps call BindCol before any
* statement is executed.
*/
if (icol > stmt->bindings_allocated)
extend_bindings(stmt, icol);
@ -236,8 +237,8 @@ SQLBindCol(
return SQL_ERROR;
}
icol--; /* use zero based col numbers from here
* out */
/* use zero based col numbers from here out */
icol--;
/* Reset for SQLGetData */
stmt->bindings[icol].data_left = -1;
@ -264,15 +265,15 @@ SQLBindCol(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* Returns the description of a parameter marker. */
/* This function is listed as not being supported by SQLGetFunctions() because it is */
/* used to describe "parameter markers" (not bound parameters), in which case, */
/* the dbms should return info on the markers. Since Postgres doesn't support that, */
/* it is best to say this function is not supported and let the application assume a */
/* data type (most likely varchar). */
/*
* Returns the description of a parameter marker.
* This function is listed as not being supported by SQLGetFunctions() because it is
* used to describe "parameter markers" (not bound parameters), in which case,
* the dbms should return info on the markers. Since Postgres doesn't support that,
* it is best to say this function is not supported and let the application assume a
* data type (most likely varchar).
*/
RETCODE SQL_API
SQLDescribeParam(
HSTMT hstmt,
@ -323,10 +324,8 @@ SQLDescribeParam(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* Sets multiple values (arrays) for the set of parameter markers. */
/* Sets multiple values (arrays) for the set of parameter markers. */
RETCODE SQL_API
SQLParamOptions(
HSTMT hstmt,
@ -341,15 +340,16 @@ SQLParamOptions(
return SQL_ERROR;
}
/* - - - - - - - - - */
/* This function should really talk to the dbms to determine the number of */
/* "parameter markers" (not bound parameters) in the statement. But, since */
/* Postgres doesn't support that, the driver should just count the number of markers */
/* and return that. The reason the driver just can't say this function is unsupported */
/* like it does for SQLDescribeParam is that some applications don't care and try */
/* to call it anyway. */
/* If the statement does not have parameters, it should just return 0. */
/*
* This function should really talk to the dbms to determine the number of
* "parameter markers" (not bound parameters) in the statement. But, since
* Postgres doesn't support that, the driver should just count the number of markers
* and return that. The reason the driver just can't say this function is unsupported
* like it does for SQLDescribeParam is that some applications don't care and try
* to call it anyway.
* If the statement does not have parameters, it should just return 0.
*/
RETCODE SQL_API
SQLNumParams(
HSTMT hstmt,
@ -387,10 +387,8 @@ SQLNumParams(
}
else
{
for (i = 0; i < strlen(stmt->statement); i++)
{
if (stmt->statement[i] == '?' && !in_quote)
(*pcpar)++;
else
@ -399,12 +397,12 @@ SQLNumParams(
in_quote = (in_quote ? FALSE : TRUE);
}
}
return SQL_SUCCESS;
}
}
/********************************************************************
/*
* Bindings Implementation
*/
BindInfoClass *
@ -428,6 +426,7 @@ create_empty_bindings(int num_columns)
return new_bindings;
}
void
extend_bindings(StatementClass *stmt, int num_columns)
{
@ -437,11 +436,12 @@ extend_bindings(StatementClass *stmt, int num_columns)
mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns);
/* if we have too few, allocate room for more, and copy the old */
/* entries into the new structure */
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (stmt->bindings_allocated < num_columns)
{
new_bindings = create_empty_bindings(num_columns);
if (!new_bindings)
{
@ -466,11 +466,12 @@ 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, */
/* let it worry about it by unbinding those columns. */
/*
* There is no reason to zero out extra bindings if there are
* more than needed. If an app has allocated extra bindings,
* let it worry about it by unbinding those columns.
*/
/* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */
/* SQLExecDirect(...) # returns 5 cols */

View File

@ -1,4 +1,5 @@
/* Module: columninfo.c
/*-------
* Module: columninfo.c
*
* Description: This module contains routines related to
* reading and storing the field information from a query.
@ -8,7 +9,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#include "columninfo.h"
@ -37,6 +38,7 @@ CI_Constructor()
return rv;
}
void
CI_Destructor(ColumnInfoClass *self)
{
@ -45,10 +47,12 @@ CI_Destructor(ColumnInfoClass *self)
free(self);
}
/* Read in field descriptions.
If self is not null, then also store the information.
If self is null, then just read, don't store.
*/
/*
* Read in field descriptions.
* If self is not null, then also store the information.
* If self is null, then just read, don't store.
*/
char
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
{
@ -71,14 +75,12 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
mylog("num_fields = %d\n", new_num_fields);
if (self)
{ /* according to that allocate memory */
/* according to that allocate memory */
CI_set_num_fields(self, new_num_fields);
}
/* now read in the descriptions */
for (lf = 0; lf < new_num_fields; lf++)
{
SOCK_get_string(sock, new_field_name, 2 * MAX_COLUMN_LEN);
new_adtid = (Oid) SOCK_get_int(sock, 4);
new_adtsize = (Int2) SOCK_get_int(sock, 2);
@ -86,7 +88,6 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
/* If 6.4 protocol, then read the atttypmod field */
if (PG_VERSION_GE(conn, 6.4))
{
mylog("READING ATTTYPMOD\n");
new_atttypmod = (Int4) SOCK_get_int(sock, 4);
@ -107,7 +108,6 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
}
void
CI_free_memory(ColumnInfoClass *self)
{
@ -143,6 +143,7 @@ CI_free_memory(ColumnInfoClass *self)
self->atttypmod = NULL;
}
void
CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
{
@ -158,11 +159,11 @@ CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields);
}
void
CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod)
{
/* check bounds */
if ((field_num < 0) || (field_num >= self->num_fields))
return;

View File

@ -1,4 +1,5 @@
/* Module: connection.c
/*------
* Module: connection.c
*
* Description: This module contains routines related to
* connecting to and disconnecting from the Postgres DBMS.
@ -9,7 +10,7 @@
* SQLBrowseConnect(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
@ -83,8 +84,6 @@ SQLAllocConnect(
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLConnect(
HDBC hdbc,
@ -140,7 +139,6 @@ SQLConnect(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLBrowseConnect(
@ -158,7 +156,6 @@ SQLBrowseConnect(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* Drop any hstmts open on hdbc and disconnect from database */
RETCODE SQL_API
@ -199,8 +196,6 @@ SQLDisconnect(
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLFreeConnect(
HDBC hdbc)
@ -235,11 +230,8 @@ SQLFreeConnect(
/*
*
* IMPLEMENTATION CONNECTION CLASS
*
*/
* IMPLEMENTATION CONNECTION CLASS
*/
ConnectionClass *
CC_Constructor()
{
@ -249,7 +241,6 @@ CC_Constructor()
if (rv != NULL)
{
rv->henv = NULL; /* not yet associated with an environment */
rv->errormsg = NULL;
@ -301,7 +292,6 @@ CC_Constructor()
char
CC_Destructor(ConnectionClass *self)
{
mylog("enter CC_Destructor, self=%u\n", self);
if (self->status == CONN_EXECUTING)
@ -343,6 +333,7 @@ CC_Destructor(ConnectionClass *self)
return 1;
}
/* Return how many cursors are opened on this connection */
int
CC_cursor_count(ConnectionClass *self)
@ -365,6 +356,7 @@ CC_cursor_count(ConnectionClass *self)
return count;
}
void
CC_clear_error(ConnectionClass *self)
{
@ -373,8 +365,11 @@ CC_clear_error(ConnectionClass *self)
self->errormsg_created = FALSE;
}
/* Used to cancel a transaction */
/* We are almost always in the middle of a transaction. */
/*
* Used to cancel a transaction.
* We are almost always in the middle of a transaction.
*/
char
CC_abort(ConnectionClass *self)
{
@ -399,6 +394,7 @@ CC_abort(ConnectionClass *self)
return TRUE;
}
/* This is called by SQLDisconnect also */
char
CC_cleanup(ConnectionClass *self)
@ -434,7 +430,6 @@ CC_cleanup(ConnectionClass *self)
stmt = self->stmts[i];
if (stmt)
{
stmt->hdbc = NULL; /* prevent any more dbase interactions */
SC_Destructor(stmt);
@ -456,6 +451,7 @@ CC_cleanup(ConnectionClass *self)
return TRUE;
}
int
CC_set_translation(ConnectionClass *self)
{
@ -499,6 +495,7 @@ CC_set_translation(ConnectionClass *self)
return TRUE;
}
char
CC_connect(ConnectionClass *self, char do_password)
{
@ -521,7 +518,6 @@ CC_connect(ConnectionClass *self, char do_password)
else
{
qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
POSTGRESDRIVERVERSION,
globals.fetch_max,
@ -646,14 +642,13 @@ CC_connect(ConnectionClass *self, char do_password)
mylog("gonna do authentication\n");
/* *************************************************** */
/* Now get the authentication request from backend */
/* *************************************************** */
/*
* Now get the authentication request from backend
*/
if (!PROTOCOL_62(ci))
do
{
if (do_password)
beresp = 'R';
else
@ -743,8 +738,10 @@ CC_connect(ConnectionClass *self, char do_password)
CC_clear_error(self); /* clear any password error */
/* send an empty query in order to find out whether the specified */
/* database really exists on the server machine */
/*
* send an empty query in order to find out whether the specified
* database really exists on the server machine
*/
mylog("sending an empty query...\n");
res = CC_send_query(self, " ", NULL);
@ -764,9 +761,9 @@ CC_connect(ConnectionClass *self, char do_password)
CC_set_translation(self);
/**********************************************/
/******* Send any initial settings *********/
/**********************************************/
/*
* Send any initial settings
*/
/*
* Since these functions allocate statements, and since the connection
@ -789,6 +786,7 @@ CC_connect(ConnectionClass *self, char do_password)
}
char
CC_add_statement(ConnectionClass *self, StatementClass *stmt)
{
@ -821,6 +819,7 @@ CC_add_statement(ConnectionClass *self, StatementClass *stmt)
return TRUE;
}
char
CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
{
@ -838,9 +837,11 @@ CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
return FALSE;
}
/* Create a more informative error message by concatenating the connection
error message with its socket error message.
*/
/*
* Create a more informative error message by concatenating the connection
* error message with its socket error message.
*/
char *
CC_create_errormsg(ConnectionClass *self)
{
@ -897,14 +898,15 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
}
/* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
the same existing QResultClass (this occurs when the tuple cache is depleted and
needs to be re-filled).
The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
(i.e., C3326857) for SQL select statements. This cursor is then used in future
'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/
/*
* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
* the same existing QResultClass (this occurs when the tuple cache is depleted and
* needs to be re-filled).
*
* The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
* (i.e., C3326857) for SQL select statements. This cursor is then used in future
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/
QResultClass *
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
{
@ -915,10 +917,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
SocketClass *sock = self->sock;
/* ERROR_MSG_LENGTH is suffcient */
static char msgbuffer[ERROR_MSG_LENGTH + 1];
char cmdbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups
* this string so dont
* need static */
/* QR_set_command() dups this string so doesn't need static */
char cmdbuffer[ERROR_MSG_LENGTH + 1];
mylog("send_query(): conn=%u, query='%s'\n", self, query);
qlog("conn=%u, query='%s'\n", self, query);
@ -1004,7 +1004,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
}
else
{
char clear = 0;
mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
@ -1203,6 +1202,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
}
}
int
CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
{
@ -1241,7 +1241,6 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
for (i = 0; i < nargs; ++i)
{
mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
SOCK_put_int(sock, args[i].len, 4);
@ -1373,9 +1372,10 @@ CC_send_settings(ConnectionClass *self)
mylog("%s: entering...\n", func);
/* This function must use the local odbc API functions since the odbc state
has not transitioned to "connected" yet.
*/
/*
* This function must use the local odbc API functions since the odbc state
* has not transitioned to "connected" yet.
*/
result = SQLAllocStmt(self, &hstmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@ -1457,10 +1457,12 @@ CC_send_settings(ConnectionClass *self)
return status;
}
/* This function is just a hack to get the oid of our Large Object oid type.
If a real Large Object oid type is made part of Postgres, this function
will go away and the define 'PG_TYPE_LO' will be updated.
*/
/*
* This function is just a hack to get the oid of our Large Object oid type.
* If a real Large Object oid type is made part of Postgres, this function
* will go away and the define 'PG_TYPE_LO' will be updated.
*/
void
CC_lookup_lo(ConnectionClass *self)
{
@ -1471,9 +1473,10 @@ CC_lookup_lo(ConnectionClass *self)
mylog("%s: entering...\n", func);
/* This function must use the local odbc API functions since the odbc state
has not transitioned to "connected" yet.
*/
/*
* This function must use the local odbc API functions since the odbc state
* has not transitioned to "connected" yet.
*/
result = SQLAllocStmt(self, &hstmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
return;
@ -1506,10 +1509,12 @@ CC_lookup_lo(ConnectionClass *self)
result = SQLFreeStmt(hstmt, SQL_DROP);
}
/* This function initializes the version of PostgreSQL from
connInfo.protocol that we're connected to.
h-inoue 01-2-2001
*/
/*
* This function initializes the version of PostgreSQL from
* connInfo.protocol that we're connected to.
* h-inoue 01-2-2001
*/
void
CC_initialize_pg_version(ConnectionClass *self)
{
@ -1534,10 +1539,12 @@ CC_initialize_pg_version(ConnectionClass *self)
}
}
/* This function gets the version of PostgreSQL that we're connected to.
This is used to return the correct info in SQLGetInfo
DJP - 25-1-2001
*/
/*
* This function gets the version of PostgreSQL that we're connected to.
* This is used to return the correct info in SQLGetInfo
* DJP - 25-1-2001
*/
void
CC_lookup_pg_version(ConnectionClass *self)
{
@ -1551,9 +1558,10 @@ CC_lookup_pg_version(ConnectionClass *self)
mylog("%s: entering...\n", func);
/* This function must use the local odbc API functions since the odbc state
has not transitioned to "connected" yet.
*/
/*
* This function must use the local odbc API functions since the odbc state
* has not transitioned to "connected" yet.
*/
result = SQLAllocStmt(self, &hstmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
return;
@ -1581,8 +1589,10 @@ CC_lookup_pg_version(ConnectionClass *self)
return;
}
/* Extract the Major and Minor numbers from the string. */
/* This assumes the string starts 'Postgresql X.X' */
/*
* Extract the Major and Minor numbers from the string.
* This assumes the string starts 'Postgresql X.X'
*/
strcpy(szVersion, "0.0");
if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
{
@ -1600,6 +1610,7 @@ CC_lookup_pg_version(ConnectionClass *self)
result = SQLFreeStmt(hstmt, SQL_DROP);
}
void
CC_log_error(char *func, char *desc, ConnectionClass *self)
{

View File

@ -1,4 +1,5 @@
/* Module: convert.c
/*-------
* Module: convert.c
*
* Description: This module contains routines related to
* converting parameters and columns into requested data types.
@ -12,7 +13,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
@ -64,11 +65,11 @@ typedef signed char SCHAR;
extern GLOBAL_VALUES globals;
/* How to map ODBC scalar functions {fn func(args)} to Postgres
* This is just a simple substitution
* List augmented from
* http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
* - thomas 2000-04-03
/*
* How to map ODBC scalar functions {fn func(args)} to Postgres.
* This is just a simple substitution. List augmented from:
* http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
* - thomas 2000-04-03
*/
char *mapFuncs[][2] = {
/* { "ASCII", "ascii" }, */
@ -141,21 +142,24 @@ unsigned int conv_from_octal(unsigned char *s);
unsigned int conv_from_hex(unsigned char *s);
char *conv_to_octal(unsigned char val);
/******** A Guide for date/time/timestamp conversions **************
/*---------
* A Guide for date/time/timestamp conversions
*
* field_type fCType Output
* ---------- ------ ----------
* PG_TYPE_DATE SQL_C_DEFAULT SQL_C_DATE
* PG_TYPE_DATE SQL_C_DATE SQL_C_DATE
* PG_TYPE_DATE SQL_C_TIMESTAMP SQL_C_TIMESTAMP (time = 0 (midnight))
* PG_TYPE_TIME SQL_C_DEFAULT SQL_C_TIME
* PG_TYPE_TIME SQL_C_TIME SQL_C_TIME
* PG_TYPE_TIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP (date = current date)
* PG_TYPE_ABSTIME SQL_C_DEFAULT SQL_C_TIMESTAMP
* PG_TYPE_ABSTIME SQL_C_DATE SQL_C_DATE (time is truncated)
* PG_TYPE_ABSTIME SQL_C_TIME SQL_C_TIME (date is truncated)
* PG_TYPE_ABSTIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP
*---------
*/
field_type fCType Output
---------- ------ ----------
PG_TYPE_DATE SQL_C_DEFAULT SQL_C_DATE
PG_TYPE_DATE SQL_C_DATE SQL_C_DATE
PG_TYPE_DATE SQL_C_TIMESTAMP SQL_C_TIMESTAMP (time = 0 (midnight))
PG_TYPE_TIME SQL_C_DEFAULT SQL_C_TIME
PG_TYPE_TIME SQL_C_TIME SQL_C_TIME
PG_TYPE_TIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP (date = current date)
PG_TYPE_ABSTIME SQL_C_DEFAULT SQL_C_TIMESTAMP
PG_TYPE_ABSTIME SQL_C_DATE SQL_C_DATE (time is truncated)
PG_TYPE_ABSTIME SQL_C_TIME SQL_C_TIME (date is truncated)
PG_TYPE_ABSTIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP
******************************************************************************/
/* This is called by SQLFetch() */
@ -168,6 +172,7 @@ copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *val
(SDWORD) bic->buflen, (SDWORD *) bic->used);
}
/* This is called by SQLGetData() */
int
copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
@ -187,17 +192,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
int result = COPY_OK;
char tempBuf[TEXT_FIELD_SIZE + 5];
/* rgbValueOffset is *ONLY* for character and binary data */
/* pcbValueOffset is for computing any pcbValue location */
/*---------
* rgbValueOffset is *ONLY* for character and binary data.
* pcbValueOffset is for computing any pcbValue location
*---------
*/
if (bind_size > 0)
{
pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
}
else
{
pcbValueOffset = bind_row * sizeof(SDWORD);
rgbValueOffset = bind_row * cbValueMax;
@ -215,14 +221,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if (!value)
{
/* handle a null just by returning SQL_NULL_DATA in pcbValue, */
/* and doing nothing to the buffer. */
/*
* handle a null just by returning SQL_NULL_DATA in pcbValue,
* and doing nothing to the buffer.
*/
if (pcbValue)
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
return COPY_OK;
}
if (stmt->hdbc->DataSourceToDriver != NULL)
{
int length = strlen(value);
@ -234,21 +241,19 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
NULL, 0, NULL);
}
/********************************************************************
First convert any specific postgres types into more
useable data.
NOTE: Conversions from PG char/varchar of a date/time/timestamp
value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*********************************************************************/
/*
* First convert any specific postgres types into more
* useable data.
*
* NOTE: Conversions from PG char/varchar of a date/time/timestamp
* value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*/
switch (field_type)
{
/*
* $$$ need to add parsing for date/time/timestamp strings in
* PG_TYPE_CHAR,VARCHAR $$$
*/
/*
* $$$ need to add parsing for date/time/timestamp strings in
* PG_TYPE_CHAR,VARCHAR $$$
*/
case PG_TYPE_DATE:
sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
break;
@ -261,13 +266,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
if (strnicmp(value, "invalid", 7) != 0)
{
sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
}
else
{ /* The timestamp is invalid so set
* something conspicuous, like the epoch */
{
/*
* The timestamp is invalid so set
* something conspicuous, like the epoch
*/
t = 0;
tim = localtime(&t);
st.m = tim->tm_mon + 1;
@ -290,7 +295,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
}
break;
/* This is for internal use by SQLStatistics() */
/* This is for internal use by SQLStatistics() */
case PG_TYPE_INT2VECTOR:
{
int nval,
@ -369,15 +374,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
}
rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
if (fCType == SQL_C_CHAR)
{
/* Special character formatting as required */
/*
* These really should return error if cbValueMax is not big
* enough.
@ -456,7 +457,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if (cbValueMax > 0)
{
copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
/* Copy the data */
@ -483,7 +483,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
}
else
{
/*
* for SQL_C_CHAR, it's probably ok to leave currency symbols in.
* But to convert to numeric types, it is necessary to get rid of
@ -633,7 +632,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if (stmt->current_col >= 0)
{
/* No more data left for this column */
if (stmt->bindings[stmt->current_col].data_left == 0)
return COPY_NO_DATA_FOUND;
@ -690,10 +688,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
}
/* This function inserts parameters into an SQL statements.
It will also modify a SELECT statement for use with declare/fetch cursors.
This function no longer does any dynamic memory allocation!
*/
/*
* This function inserts parameters into an SQL statements.
* It will also modify a SELECT statement for use with declare/fetch cursors.
* This function no longer does any dynamic memory allocation!
*/
int
copy_statement_with_parameters(StatementClass *stmt)
{
@ -760,7 +759,6 @@ copy_statement_with_parameters(StatementClass *stmt)
for (opos = 0; opos < oldstmtlen; opos++)
{
/* Squeeze carriage-return/linefeed pairs to linefeed only */
if (old_statement[opos] == '\r' && opos + 1 < oldstmtlen &&
old_statement[opos + 1] == '\n')
@ -782,10 +780,8 @@ copy_statement_with_parameters(StatementClass *stmt)
#ifdef MULTIBYTE
char *end = multibyte_strchr(begin, '}');
#else
char *end = strchr(begin, '}');
#endif
if (!end)
@ -807,12 +803,9 @@ copy_statement_with_parameters(StatementClass *stmt)
}
opos += end - begin + 1;
*end = '}';
continue;
}
/*
* Can you have parameter markers inside of quotes? I dont think
* so. All the queries I've seen expect the driver to put quotes
@ -829,12 +822,9 @@ copy_statement_with_parameters(StatementClass *stmt)
continue;
}
/****************************************************/
/* Its a '?' parameter alright */
/****************************************************/
/*
* Its a '?' parameter alright
*/
param_number++;
if (param_number >= stmt->parameters_allocated)
@ -906,7 +896,6 @@ copy_statement_with_parameters(StatementClass *stmt)
param_string[0] = '\0';
cbuf[0] = '\0';
/* Convert input C type to a neutral format */
switch (param_ctype)
{
@ -1113,13 +1102,10 @@ copy_statement_with_parameters(StatementClass *stmt)
if (stmt->parameters[param_number].data_at_exec)
{
lobj_oid = stmt->parameters[param_number].lobj_oid;
}
else
{
/* begin transaction if needed */
if (!CC_is_in_trans(stmt->hdbc))
{
@ -1264,15 +1250,12 @@ copy_statement_with_parameters(StatementClass *stmt)
new_statement[npos++] = '\''; /* Close Quote */
break;
}
} /* end, for */
/* make sure new_statement is always null-terminated */
new_statement[npos] = '\0';
if (stmt->hdbc->DriverToDataSource != NULL)
{
int length = strlen(new_statement);
@ -1284,10 +1267,10 @@ copy_statement_with_parameters(StatementClass *stmt)
NULL, 0, NULL);
}
return SQL_SUCCESS;
}
char *
mapFunction(char *func)
{
@ -1300,7 +1283,10 @@ mapFunction(char *func)
return NULL;
}
/* convert_escape()
/*
* convert_escape()
*
* This function returns a pointer to static memory!
*/
char *
@ -1330,7 +1316,6 @@ convert_escape(char *value)
}
else if (strcmp(key, "fn") == 0)
{
/*
* Function invocation Separate off the func name, skipping
* trailing whitespace.
@ -1381,7 +1366,6 @@ convert_escape(char *value)
}
return escape;
}
@ -1405,9 +1389,10 @@ convert_money(char *s)
}
/* This function parses a character string for date/time info and fills in SIMPLE_TIME */
/* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value */
/*
* This function parses a character string for date/time info and fills in SIMPLE_TIME
* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
*/
char
parse_datetime(char *buf, SIMPLE_TIME *st)
{
@ -1465,6 +1450,7 @@ parse_datetime(char *buf, SIMPLE_TIME *st)
return FALSE;
}
/* Change linefeed to carriage-return/linefeed */
int
convert_linefeeds(char *si, char *dst, size_t max)
@ -1493,9 +1479,11 @@ convert_linefeeds(char *si, char *dst, size_t max)
return out;
}
/* Change carriage-return/linefeed to just linefeed
Plus, escape any special characters.
*/
/*
* Change carriage-return/linefeed to just linefeed
* Plus, escape any special characters.
*/
char *
convert_special_chars(char *si, char *dst, int used)
{
@ -1537,6 +1525,7 @@ convert_special_chars(char *si, char *dst, int used)
return p;
}
/* !!! Need to implement this function !!! */
int
convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
@ -1547,6 +1536,7 @@ convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
return 0;
}
unsigned int
conv_from_octal(unsigned char *s)
{
@ -1560,6 +1550,7 @@ conv_from_octal(unsigned char *s)
}
unsigned int
conv_from_hex(unsigned char *s)
{
@ -1569,7 +1560,6 @@ conv_from_hex(unsigned char *s)
for (i = 1; i <= 2; i++)
{
if (s[i] >= 'a' && s[i] <= 'f')
val = s[i] - 'a' + 10;
else if (s[i] >= 'A' && s[i] <= 'F')
@ -1583,6 +1573,7 @@ conv_from_hex(unsigned char *s)
return y;
}
/* convert octal escapes to bytes */
int
convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
@ -1629,6 +1620,7 @@ conv_to_octal(unsigned char val)
return x;
}
/* convert non-ascii bytes to octal escape sequences */
int
convert_to_pgbinary(unsigned char *in, char *out, int len)
@ -1636,7 +1628,6 @@ convert_to_pgbinary(unsigned char *in, char *out, int len)
int i,
o = 0;
for (i = 0; i < len; i++)
{
mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
@ -1647,7 +1638,6 @@ convert_to_pgbinary(unsigned char *in, char *out, int len)
strcpy(&out[o], conv_to_octal(in[i]));
o += 5;
}
}
mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);
@ -1705,21 +1695,22 @@ decode(char *in, char *out)
}
/* 1. get oid (from 'value')
2. open the large object
3. read from the large object (handle multiple GetData)
4. close when read less than requested? -OR-
lseek/read each time
handle case where application receives truncated and
decides not to continue reading.
CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
data type currently mapped to a PG_TYPE_LO. But, if any other types
are desired to map to a large object (PG_TYPE_LO), then that would
need to be handled here. For example, LONGVARCHAR could possibly be
mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
*/
/*-------
* 1. get oid (from 'value')
* 2. open the large object
* 3. read from the large object (handle multiple GetData)
* 4. close when read less than requested? -OR-
* lseek/read each time
* handle case where application receives truncated and
* decides not to continue reading.
*
* CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
* data type currently mapped to a PG_TYPE_LO. But, if any other types
* are desired to map to a large object (PG_TYPE_LO), then that would
* need to be handled here. For example, LONGVARCHAR could possibly be
* mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
*-------
*/
int
convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
SDWORD cbValueMax, SDWORD *pcbValue)
@ -1731,7 +1722,7 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
BindInfoClass *bindInfo = NULL;
/* If using SQLGetData, then current_col will be set */
/* If using SQLGetData, then current_col will be set */
if (stmt->current_col >= 0)
{
bindInfo = &stmt->bindings[stmt->current_col];
@ -1745,7 +1736,6 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
if (!bindInfo || bindInfo->data_left == -1)
{
/* begin transaction if needed */
if (!CC_is_in_trans(stmt->hdbc))
{
@ -1784,7 +1774,6 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END);
if (retval >= 0)
{
left = lo_tell(stmt->hdbc, stmt->lobj_fd);
if (bindInfo)
bindInfo->data_left = left;
@ -1849,11 +1838,9 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
if (pcbValue)
*pcbValue = left < 0 ? SQL_NO_TOTAL : left;
if (bindInfo && bindInfo->data_left > 0)
bindInfo->data_left -= retval;
if (!bindInfo || bindInfo->data_left == 0)
{
lo_close(stmt->hdbc, stmt->lobj_fd);
@ -1886,7 +1873,5 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
stmt->lobj_fd = -1; /* prevent further reading */
}
return result;
}

View File

@ -1,4 +1,5 @@
/* Module: dlg_specific.c
/*-------
* Module: dlg_specific.c
*
* Description: This module contains any specific code for handling
* dialog boxes such as driver/datasource options. Both the
@ -12,7 +13,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
@ -50,11 +51,11 @@
extern GLOBAL_VALUES globals;
#ifdef WIN32
void
SetDlgStuff(HWND hdlg, ConnInfo *ci)
{
/*
* If driver attribute NOT present, then set the datasource name and
* description
@ -72,6 +73,7 @@ SetDlgStuff(HWND hdlg, ConnInfo *ci)
SetDlgItemText(hdlg, IDC_PORT, ci->port);
}
void
GetDlgStuff(HWND hdlg, ConnInfo *ci)
{
@ -85,7 +87,6 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci)
}
int CALLBACK
driver_optionsProc(HWND hdlg,
WORD wMsg,
@ -141,7 +142,6 @@ driver_optionsProc(HWND hdlg,
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
globals.disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER);
globals.ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO);
@ -228,12 +228,12 @@ driver_optionsProc(HWND hdlg,
break;
}
}
return FALSE;
}
int CALLBACK
ds_optionsProc(HWND hdlg,
WORD wMsg,
@ -267,11 +267,9 @@ ds_optionsProc(HWND hdlg,
else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
CheckDlgButton(hdlg, DS_PG63, 1);
else
/* latest */
/* latest */
CheckDlgButton(hdlg, DS_PG64, 1);
CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
@ -283,7 +281,6 @@ ds_optionsProc(HWND hdlg,
SetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
@ -292,9 +289,7 @@ ds_optionsProc(HWND hdlg,
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
return TRUE;
case IDOK:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
mylog("IDOK: got ci = %u\n", ci);
@ -307,7 +302,7 @@ ds_optionsProc(HWND hdlg,
else if (IsDlgButtonChecked(hdlg, DS_PG63))
strcpy(ci->protocol, PG63);
else
/* latest */
/* latest */
strcpy(ci->protocol, PG64);
sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
@ -321,7 +316,6 @@ ds_optionsProc(HWND hdlg,
/* Datasource Connection Settings */
GetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings, sizeof(ci->conn_settings));
/* fall through */
case IDCANCEL:
@ -335,6 +329,7 @@ ds_optionsProc(HWND hdlg,
#endif /* WIN32 */
void
makeConnectString(char *connect_string, ConnInfo *ci)
{
@ -365,10 +360,10 @@ makeConnectString(char *connect_string, ConnInfo *ci)
encoded_conn_settings);
}
void
copyAttributes(ConnInfo *ci, char *attribute, char *value)
{
if (stricmp(attribute, "DSN") == 0)
strcpy(ci->dsn, value);
@ -415,9 +410,9 @@ copyAttributes(ConnInfo *ci, char *attribute, char *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
getDSNdefaults(ConnInfo *ci)
{
@ -450,8 +445,10 @@ getDSNinfo(ConnInfo *ci, char overwrite)
char *DSN = ci->dsn;
char encoded_conn_settings[LARGE_REGISTRY_LEN];
/* If a driver keyword was present, then dont use a DSN and return. */
/* If DSN is null and no driver, then use the default datasource. */
/*
* If a driver keyword was present, then dont use a DSN and return.
* If DSN is null and no driver, then use the default datasource.
*/
if (DSN[0] == '\0')
{
if (ci->driver[0] != '\0')
@ -514,11 +511,9 @@ getDSNinfo(ConnInfo *ci, char overwrite)
if (ci->translation_option[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
/* Allow override of odbcinst.ini parameters here */
getGlobalDefaults(DSN, ODBC_INI, TRUE);
qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
DSN,
ci->server,
@ -546,7 +541,6 @@ getDSNinfo(ConnInfo *ci, char overwrite)
qlog(" translation_dll='%s',translation_option='%s'\n",
ci->translation_dll,
ci->translation_option);
}
@ -626,15 +620,15 @@ writeDSNinfo(ConnInfo *ci)
}
/* This function reads the ODBCINST.INI portion of
the registry and gets any driver defaults.
*/
/*
* This function reads the ODBCINST.INI portion of
* the registry and gets any driver defaults.
*/
void
getGlobalDefaults(char *section, char *filename, char override)
{
char temp[256];
/* Fetch Count is stored in driver section */
SQLGetPrivateProfileString(section, INI_FETCH, "",
temp, sizeof(temp), filename);
@ -648,7 +642,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else if (!override)
globals.fetch_max = FETCH_MAX;
/* Socket Buffersize is stored in driver section */
SQLGetPrivateProfileString(section, INI_SOCKET, "",
temp, sizeof(temp), filename);
@ -657,7 +650,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else if (!override)
globals.socket_buffersize = SOCK_BUFFER_SIZE;
/* Debug is stored in the driver section */
SQLGetPrivateProfileString(section, INI_DEBUG, "",
temp, sizeof(temp), filename);
@ -666,7 +658,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else if (!override)
globals.debug = DEFAULT_DEBUG;
/* CommLog is stored in the driver section */
SQLGetPrivateProfileString(section, INI_COMMLOG, "",
temp, sizeof(temp), filename);
@ -675,7 +666,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else if (!override)
globals.commlog = DEFAULT_COMMLOG;
/* Optimizer is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
temp, sizeof(temp), filename);
@ -734,8 +724,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else if (!override)
globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
/* UseDeclareFetch is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
temp, sizeof(temp), filename);
@ -744,7 +732,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else if (!override)
globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
/* Max Varchar Size */
SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
temp, sizeof(temp), filename);
@ -804,7 +791,6 @@ getGlobalDefaults(char *section, char *filename, char override)
/* Dont allow override of an override! */
if (!override)
{
/*
* ConnSettings is stored in the driver section and per datasource
* for override
@ -831,14 +817,14 @@ getGlobalDefaults(char *section, char *filename, char override)
strcpy(globals.protocol, temp);
else
strcpy(globals.protocol, DEFAULT_PROTOCOL);
}
}
/* This function writes any global parameters (that can be manipulated)
to the ODBCINST.INI portion of the registry
*/
/*
* This function writes any global parameters (that can be manipulated)
* to the ODBCINST.INI portion of the registry
*/
void
updateGlobals(void)
{

View File

@ -1,4 +1,5 @@
/* Module: drvconn.c
/*-------
* Module: drvconn.c
*
* Description: This module contains only routines related to
* implementing SQLDriverConnect.
@ -8,7 +9,7 @@
* API functions: SQLDriverConnect
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#ifdef HAVE_CONFIG_H
@ -110,9 +111,11 @@ SQLDriverConnect(
/* Parse the connect string and fill in conninfo for this hdbc. */
dconn_get_connect_attributes(connStrIn, ci);
/* If the ConnInfo in the hdbc is missing anything, */
/* this function will fill them in from the registry (assuming */
/* of course there is a DSN given -- if not, it does nothing!) */
/*
* If the ConnInfo in the hdbc is missing anything,
* this function will fill them in from the registry (assuming
* of course there is a DSN given -- if not, it does nothing!)
*/
getDSNinfo(ci, CONN_DONT_OVERWRITE);
/* Fill in any default parameters if they are not there. */
@ -147,7 +150,6 @@ dialog:
ci->port[0] == '\0' ||
password_required)
{
dialog_result = dconn_DoDialog(hwnd, ci);
if (dialog_result != SQL_SUCCESS)
return dialog_result;
@ -173,12 +175,11 @@ dialog:
ci->database[0] == '\0' ||
ci->port[0] == '\0')
{
/* (password_required && ci->password[0] == '\0')) */
/* (password_required && ci->password[0] == '\0')) */
return SQL_NO_DATA_FOUND;
}
/* do the actual connect */
retval = CC_connect(conn, password_required);
if (retval < 0)
@ -206,9 +207,9 @@ dialog:
return SQL_ERROR;
}
/*********************************************/
/* Create the Output Connection String */
/*********************************************/
/*
* Create the Output Connection String
*/
result = SQL_SUCCESS;
makeConnectString(connStrOut, ci);
@ -216,7 +217,6 @@ dialog:
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,
@ -247,6 +247,7 @@ dialog:
return result;
}
#ifdef WIN32
RETCODE
dconn_DoDialog(HWND hwnd, ConnInfo *ci)
@ -296,7 +297,6 @@ dconn_FDriverConnectProc(
SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for
* the "OK" */
SetDlgStuff(hdlg, ci);
if (ci->database[0] == '\0')
@ -309,38 +309,29 @@ dconn_FDriverConnectProc(
SetFocus(GetDlgItem(hdlg, IDC_USER));
else if (ci->focus_password)
SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
GetDlgStuff(hdlg, ci);
case IDCANCEL:
EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
return TRUE;
case IDC_DRIVER:
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
hdlg, driver_optionsProc, (LPARAM) NULL);
break;
case IDC_DATASOURCE:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
hdlg, ds_optionsProc, (LPARAM) ci);
break;
}
}
@ -350,6 +341,7 @@ dconn_FDriverConnectProc(
#endif /* WIN32 */
void
dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
{
@ -393,6 +385,5 @@ dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
}
free(our_connect_string);
}

View File

@ -1,4 +1,5 @@
/* Module: environ.c
/*-------
* Module: environ.c
*
* Description: This module contains routines related to
* the environment, such as storing connection handles,
@ -9,7 +10,7 @@
* API functions: SQLAllocEnv, SQLFreeEnv, SQLError
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#include "environ.h"
@ -54,6 +55,7 @@ SQLAllocEnv(HENV FAR *phenv)
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLFreeEnv(HENV henv)
{
@ -73,8 +75,8 @@ SQLFreeEnv(HENV henv)
return SQL_ERROR;
}
/* Returns the next SQL error information. */
/* Returns the next SQL error information. */
RETCODE SQL_API
SQLError(
HENV henv,
@ -208,24 +210,19 @@ SQLError(
case STMT_INVALID_CURSOR_POSITION:
strcpy(szSqlState, "S1109");
break;
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
case STMT_OPERATION_INVALID:
strcpy(szSqlState, "S1011");
break;
case STMT_EXEC_ERROR:
default:
strcpy(szSqlState, "S1000");
/* also a general error */
break;
}
mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
}
else
{
@ -237,10 +234,11 @@ SQLError(
szErrorMsg[0] = '\0';
mylog(" returning NO_DATA_FOUND\n");
return SQL_NO_DATA_FOUND;
}
return SQL_SUCCESS;
return SQL_SUCCESS;
}
else if (SQL_NULL_HDBC != hdbc)
{
@ -310,7 +308,6 @@ SQLError(
break;
case CONN_TRANSACT_IN_PROGRES:
strcpy(szSqlState, "S1010");
/*
* when the user tries to switch commit mode in a
* transaction
@ -324,18 +321,15 @@ SQLError(
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00");
break;
case CONN_VALUE_OUT_OF_RANGE:
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
}
}
else
{
@ -349,8 +343,8 @@ SQLError(
return SQL_NO_DATA_FOUND;
}
return SQL_SUCCESS;
return SQL_SUCCESS;
}
else if (SQL_NULL_HENV != henv)
{
@ -419,15 +413,10 @@ SQLError(
}
/*********************************************************************/
/*
* EnvironmentClass implementation
*/
EnvironmentClass
*
EnvironmentClass *
EN_Constructor(void)
{
EnvironmentClass *rv;
@ -451,8 +440,10 @@ EN_Destructor(EnvironmentClass *self)
mylog("in EN_Destructor, self=%u\n", self);
/* the error messages are static strings distributed throughout */
/* the source--they should not be freed */
/*
* the error messages are static strings distributed throughout
* the source--they should not be freed
*/
/* Free any connections belonging to this environment */
for (lf = 0; lf < MAX_CONNECTIONS; lf++)
@ -466,6 +457,7 @@ EN_Destructor(EnvironmentClass *self)
return rv;
}
char
EN_get_error(EnvironmentClass *self, int *number, char **message)
{
@ -481,6 +473,7 @@ EN_get_error(EnvironmentClass *self, int *number, char **message)
return 0;
}
char
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
{
@ -504,6 +497,7 @@ EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
return FALSE;
}
char
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
{
@ -519,6 +513,7 @@ EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
return FALSE;
}
void
EN_log_error(char *func, char *desc, EnvironmentClass *self)
{

View File

@ -1,4 +1,5 @@
/* Module: execute.c
/*-------
* Module: execute.c
*
* Description: This module contains routines related to
* preparing and executing an SQL statement.
@ -9,7 +10,7 @@
* SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#ifdef HAVE_CONFIG_H
@ -126,14 +127,10 @@ SQLPrepare(HSTMT hstmt,
}
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
RETCODE SQL_API
SQLExecDirect(
HSTMT hstmt,
@ -155,8 +152,10 @@ SQLExecDirect(
if (stmt->statement)
free(stmt->statement);
/* keep a copy of the un-parametrized statement, in case */
/* they try to execute this statement again */
/*
* 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)
{
@ -170,9 +169,11 @@ SQLExecDirect(
stmt->prepare = FALSE;
/* If an SQLPrepare was performed prior to this, but was left in */
/* the premature state because an error occurred prior to SQLExecute */
/* then set the statement to finished so it can be recycled. */
/*
* If an SQLPrepare was performed prior to this, but was left in
* the premature state because an error occurred prior to SQLExecute
* then set the statement to finished so it can be recycled.
*/
if (stmt->status == STMT_PREMATURE)
stmt->status = STMT_FINISHED;
@ -195,7 +196,8 @@ SQLExecDirect(
return result;
}
/* Execute a prepared SQL statement */
/* Execute a prepared SQL statement */
RETCODE SQL_API
SQLExecute(
HSTMT hstmt)
@ -206,7 +208,6 @@ SQLExecute(
int i,
retval;
mylog("%s: entering...\n", func);
if (!stmt)
@ -280,7 +281,6 @@ SQLExecute(
if ((stmt->prepare && stmt->status != STMT_READY) ||
(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
{
stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
SC_log_error(func, "", stmt);
@ -288,7 +288,6 @@ SQLExecute(
return SQL_ERROR;
}
/* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
if (!stmt->pre_executing)
{
@ -336,15 +335,10 @@ SQLExecute(
mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params);
return SC_execute(stmt);
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLTransact(
HENV henv,
@ -380,7 +374,6 @@ SQLTransact(
if (conn && conn->henv == henv)
if (SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
return SQL_ERROR;
}
return SQL_SUCCESS;
}
@ -388,15 +381,9 @@ SQLTransact(
conn = (ConnectionClass *) hdbc;
if (fType == SQL_COMMIT)
{
stmt_string = "COMMIT";
}
else if (fType == SQL_ROLLBACK)
{
stmt_string = "ROLLBACK";
}
else
{
conn->errornumber = CONN_INVALID_ARGUMENT_NO;
@ -408,7 +395,6 @@ SQLTransact(
/* If manual commit and in transaction, then proceed. */
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);
@ -433,7 +419,6 @@ SQLTransact(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLCancel(
@ -464,8 +449,6 @@ SQLCancel(
*/
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
@ -507,14 +490,14 @@ SQLCancel(
stmt->put_data = FALSE;
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* Returns the SQL string as modified by the driver. */
/* Currently, just copy the input string without modification */
/* observing buffer limits and truncation. */
/*
* 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(
HDBC hdbc,
@ -564,11 +547,11 @@ SQLNativeSql(
return result;
}
/* - - - - - - - - - */
/* Supplies parameter data at execution time. Used in conjuction with */
/* SQLPutData. */
/*
* Supplies parameter data at execution time.
* Used in conjuction with SQLPutData.
*/
RETCODE SQL_API
SQLParamData(
HSTMT hstmt,
@ -636,11 +619,9 @@ SQLParamData(
CC_set_no_trans(stmt->hdbc);
}
stmt->lobj_fd = -1;
}
/* Done, now copy the params and then execute the statement */
if (stmt->data_at_exec == 0)
{
@ -675,11 +656,11 @@ SQLParamData(
return SQL_NEED_DATA;
}
/* - - - - - - - - - */
/* Supplies parameter data at execution time. Used in conjunction with */
/* SQLParamData. */
/*
* Supplies parameter data at execution time.
* Used in conjunction with SQLParamData.
*/
RETCODE SQL_API
SQLPutData(
HSTMT hstmt,
@ -701,7 +682,6 @@ SQLPutData(
return SQL_INVALID_HANDLE;
}
if (stmt->current_exec_param < 0)
{
stmt->errornumber = STMT_SEQUENCE_ERROR;
@ -714,7 +694,6 @@ SQLPutData(
if (!stmt->put_data)
{ /* first call */
mylog("SQLPutData: (1) cbValue = %d\n", cbValue);
stmt->put_data = TRUE;
@ -733,11 +712,9 @@ SQLPutData(
if (cbValue == SQL_NULL_DATA)
return SQL_SUCCESS;
/* Handle Long Var Binary with Large Objects */
if (current_param->SQLType == SQL_LONGVARBINARY)
{
/* begin transaction if needed */
if (!CC_is_in_trans(stmt->hdbc))
{
@ -775,8 +752,10 @@ SQLPutData(
return SQL_ERROR;
}
/* major hack -- to allow convert to see somethings there */
/* have to modify convert to handle this better */
/*
* major hack -- to allow convert to see somethings there
* have to modify convert to handle this better
*/
current_param->EXEC_buffer = (char *) &current_param->lobj_oid;
/* store the fd */
@ -791,11 +770,10 @@ 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 fields */
{
/* for handling fields */
if (cbValue == SQL_NTS)
{
current_param->EXEC_buffer = strdup(rgbValue);
@ -841,25 +819,21 @@ SQLPutData(
}
}
}
else
{ /* calling SQLPutData more than once */
{
/* calling SQLPutData more than once */
mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);
if (current_param->SQLType == SQL_LONGVARBINARY)
{
/* the large object fd is in EXEC_buffer */
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
*current_param->EXEC_used += cbValue;
}
else
{
buffer = current_param->EXEC_buffer;
if (cbValue == SQL_NTS)
@ -880,11 +854,9 @@ SQLPutData(
/* reassign buffer incase realloc moved it */
current_param->EXEC_buffer = buffer;
}
else if (cbValue > 0)
{
old_pos = *current_param->EXEC_used;
*current_param->EXEC_used += cbValue;
@ -906,17 +878,14 @@ SQLPutData(
/* reassign buffer incase realloc moved it */
current_param->EXEC_buffer = buffer;
}
else
{
SC_log_error(func, "bad cbValue", stmt);
return SQL_ERROR;
}
}
}
return SQL_SUCCESS;
}

View File

@ -1,4 +1,5 @@
/* GetPrivateProfileString()
/*-------
* GetPrivateProfileString()
*
* approximate implementation of
* Windows NT System Services version of GetPrivateProfileString()
@ -15,6 +16,7 @@
* are allowed (that is an anachronism anyway)
* Added code to search for ODBC_INI file in users home directory on
* Unix
*-------
*/
#ifndef WIN32
@ -46,7 +48,7 @@
DWORD
GetPrivateProfileString(char *theSection, /* section name */
char *theKey, /* search key name */
char *theKey, /* search key name */
char *theDefault, /* default value if not
* found */
char *theReturnBuffer, /* return value stored
@ -110,7 +112,6 @@ GetPrivateProfileString(char *theSection, /* section name */
aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
}
aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
if (theReturnBufferLength == 0 || theReturnBuffer == NULL)
@ -123,7 +124,6 @@ GetPrivateProfileString(char *theSection, /* section name */
if (aFile == NULL)
{
/* no ini file specified, return the default */
++aLength; /* room for NULL char */
aLength = theReturnBufferLength < aLength ?
theReturnBufferLength : aLength;
@ -132,7 +132,6 @@ GetPrivateProfileString(char *theSection, /* section name */
return aLength - 1;
}
while (fgets(aLine, sizeof(aLine), aFile) != NULL)
{
aLineLength = strlen(aLine);
@ -147,7 +146,6 @@ GetPrivateProfileString(char *theSection, /* section name */
break;
case '[': /* section marker */
if ((aString = strchr(aLine, ']')))
{
aStart = aLine + 1;
@ -159,30 +157,25 @@ GetPrivateProfileString(char *theSection, /* section name */
*(aString + 1) = '\0';
/* accept as matched if NULL key or exact match */
if (!theSection || !strcmp(aStart, theSection))
aSectionFound = TRUE;
else
aSectionFound = FALSE;
}
break;
default:
/* try to match value keys if in proper section */
if (aSectionFound)
{
/* try to match requested key */
if ((aString = aValue = strchr(aLine, '=')))
{
*aValue = '\0';
++aValue;
/* strip leading blanks in value field */
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
*aValue++ = '\0';
if (aValue >= aLine + sizeof(aLine))
@ -196,7 +189,6 @@ GetPrivateProfileString(char *theSection, /* section name */
aStart++;
/* strip trailing blanks from key */
if (aString)
{
while (--aString >= aStart && *aString == ' ')
@ -204,16 +196,13 @@ GetPrivateProfileString(char *theSection, /* section name */
}
/* see if key is matched */
if (theKey == NULL || !strcmp(theKey, aStart))
{
/* matched -- first, terminate value part */
aKeyFound = TRUE;
aLength = strlen(aValue);
/* remove trailing blanks from aValue if any */
aString = aValue + aLength - 1;
while (--aString > aValue && *aString == ' ')
@ -223,7 +212,6 @@ GetPrivateProfileString(char *theSection, /* section name */
}
/* unquote value if quoted */
if (aLength >= 2 && aValue[0] == '"' &&
aValue[aLength - 1] == '"')
{
@ -236,7 +224,6 @@ GetPrivateProfileString(char *theSection, /* section name */
else
{
/* single quotes allowed also... */
if (aLength >= 2 && aValue[0] == '\'' &&
aValue[aLength - 1] == '\'')
{
@ -247,13 +234,11 @@ GetPrivateProfileString(char *theSection, /* section name */
}
/* compute maximum length copyable */
aLineLength = (aLength <
theReturnBufferLength - aReturnLength) ? aLength :
theReturnBufferLength - aReturnLength;
/* do the copy to return buffer */
if (aLineLength)
{
strncpy(&theReturnBuffer[aReturnLength],
@ -270,11 +255,9 @@ GetPrivateProfileString(char *theSection, /* section name */
fclose(aFile);
aFile = NULL;
}
return aReturnLength > 0 ? aReturnLength - 1 : 0;
}
}
break;
}
}
@ -283,7 +266,8 @@ GetPrivateProfileString(char *theSection, /* section name */
fclose(aFile);
if (!aKeyFound)
{ /* key wasn't found return default */
{
/* key wasn't found return default */
++aLength; /* room for NULL char */
aLength = theReturnBufferLength < aLength ?
theReturnBufferLength : aLength;
@ -294,9 +278,10 @@ GetPrivateProfileString(char *theSection, /* section name */
return aReturnLength > 0 ? aReturnLength - 1 : 0;
}
DWORD
WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */
char *theKey, /* write key name */
char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to
* write */
@ -304,14 +289,16 @@ WritePrivateProfileString(char *theSection, /* section name */
return 0;
}
#if 0
/* Ok. What the hell's the default behaviour for a null input buffer, and null
/*
* Ok. What the hell's the default behaviour for a null input buffer, and null
* section name. For now if either are null I ignore the request, until
* I find out different.
*/
DWORD
WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */
char *theKey, /* write key name */
char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to
* write */
@ -353,11 +340,12 @@ WritePrivateProfileString(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)
{
if (MAXPGPATH - 1 < strlen(ptr))
@ -368,9 +356,10 @@ WritePrivateProfileString(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, "r+") : NULL);
if (!aFile)
{
@ -380,13 +369,13 @@ WritePrivateProfileString(char *theSection, /* section name */
return 0;
}
aLength = strlen(theBuffer);
/* We have to search for theKey, because if it already */
/* exists we have to overwrite it. If it doesn't exist */
/* we just write a new line to the file. */
/* */
/*
* We have to search for theKey, because if it already
* exists we have to overwrite it. If it doesn't exist
* we just write a new line to the file.
*/
while (fgets(aLine, sizeof(aLine), aFile) != NULL)
{
aLineLength = strlen(aLine);
@ -401,7 +390,6 @@ WritePrivateProfileString(char *theSection, /* section name */
break;
case '[': /* section marker */
if ((aString = strchr(aLine, ']')))
{
*aString = '\0';
@ -411,13 +399,10 @@ WritePrivateProfileString(char *theSection, /* section name */
if (!strcmp(aLine + 1, theSection))
aSectionFound = TRUE;
}
break;
default:
/* try to match value keys if in proper section */
if (aSectionFound)
{
/* try to match requested key */
@ -428,7 +413,6 @@ WritePrivateProfileString(char *theSection, /* section name */
++aValue;
/* strip leading blanks in value field */
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
*aValue++ = '\0';
if (aValue >= aLine + sizeof(aLine))
@ -438,7 +422,6 @@ WritePrivateProfileString(char *theSection, /* section name */
aValue = "";
/* strip trailing blanks from key */
if (aString)
{
while (--aString >= aLine && *aString == ' ')
@ -446,7 +429,6 @@ WritePrivateProfileString(char *theSection, /* section name */
}
/* see if key is matched */
if (!strcmp(theKey, aLine))
{
keyFound = TRUE;
@ -460,7 +442,6 @@ WritePrivateProfileString(char *theSection, /* section name */
}
}
}
break;
}
}

View File

@ -1,4 +1,5 @@
/* Module: info.c
/*--------
* Module: info.c
*
* Description: This module contains routines related to
* ODBC informational functions.
@ -12,7 +13,7 @@
* SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
#ifdef HAVE_CONFIG_H
@ -56,8 +57,6 @@
extern GLOBAL_VALUES globals;
/* - - - - - - - - - */
RETCODE SQL_API
SQLGetInfo(
HDBC hdbc,
@ -154,7 +153,6 @@ SQLGetInfo(
break;
case SQL_CORRELATION_NAME: /* ODBC 1.0 */
/*
* Saying no correlation name makes Query not work right.
* value = SQL_CN_NONE;
@ -182,11 +180,10 @@ SQLGetInfo(
break;
case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */
/*
* Returning the database name causes problems in MS Query. It
* generates query like: "SELECT DISTINCT a FROM byronncrap3
* crap3"
* generates query like: "SELECT DISTINCT a FROM byronnbad3
* bad3"
*
* p = CC_get_database(conn);
*/
@ -198,7 +195,6 @@ SQLGetInfo(
break;
case SQL_DBMS_VER: /* ODBC 1.0 */
/*
* The ODBC spec wants ##.##.#### ...whatever... so prepend
* the driver
@ -256,7 +252,6 @@ SQLGetInfo(
break;
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
/*
* are identifiers case-sensitive (yes, but only when quoted.
* If not quoted, they default to lowercase)
@ -275,7 +270,6 @@ SQLGetInfo(
break;
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
/*
* is there a character that escapes '%' and '_' in a LIKE
* clause? not as far as I can tell
@ -356,18 +350,18 @@ SQLGetInfo(
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
len = 4;
if (PG_VERSION_GE(conn, 7.1))
{ /* Large Rowa in 7.1+ */
{
/* Large Rowa in 7.1+ */
value = MAX_ROW_SIZE;
}
else
{ /* Without the Toaster we're limited to
* the blocksize */
{
/* Without the Toaster we're limited to the blocksize */
value = BLCKSZ;
}
break;
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
/*
* does the preceding value include LONGVARCHAR and
* LONGVARBINARY fields? Well, it does include longvarchar,
@ -379,15 +373,14 @@ SQLGetInfo(
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
/* maybe this should be 0? */
len = 4;
/* Long Queries in 7.0+ */
if (PG_VERSION_GE(conn, 7.0))
{ /* Long Queries in 7.0+ */
value = MAX_STATEMENT_LEN;
}
else if (PG_VERSION_GE(conn, 6.5)) /* Prior to 7.0 we used
* 2*BLCKSZ */
/* Prior to 7.0 we used 2*BLCKSZ */
else if (PG_VERSION_GE(conn, 6.5))
value = (2 * BLCKSZ);
else
/* Prior to 6.5 we used BLCKSZ */
/* Prior to 6.5 we used BLCKSZ */
value = BLCKSZ;
break;
@ -417,9 +410,8 @@ SQLGetInfo(
break;
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
/*
* Dont need the length, SQLPutData can handle any size and
* Don't need the length, SQLPutData can handle any size and
* multiple calls
*/
p = "N";
@ -463,7 +455,8 @@ SQLGetInfo(
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
len = 4;
if (PG_VERSION_GE(conn, 7.1))
{ /* OJs in 7.1+ */
{
/* OJs in 7.1+ */
value = (SQL_OJ_LEFT |
SQL_OJ_RIGHT |
SQL_OJ_FULL |
@ -473,9 +466,8 @@ SQLGetInfo(
SQL_OJ_ALL_COMPARISON_OPS);
}
else
{ /* OJs not in <7.1 */
/* OJs not in <7.1 */
value = 0;
}
break;
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
@ -484,13 +476,11 @@ SQLGetInfo(
case SQL_OUTER_JOINS: /* ODBC 1.0 */
if (PG_VERSION_GE(conn, 7.1))
{ /* OJs in 7.1+ */
/* OJs in 7.1+ */
p = "Y";
}
else
{ /* OJs not in <7.1 */
/* OJs not in <7.1 */
p = "N";
}
break;
case SQL_OWNER_TERM: /* ODBC 1.0 */
@ -547,7 +537,6 @@ SQLGetInfo(
break;
case SQL_ROW_UPDATES: /* ODBC 1.0 */
/*
* Driver doesn't support keyset-driven or mixed cursors, so
* not much point in saying row updates are supported
@ -635,7 +624,6 @@ SQLGetInfo(
break;
case SQL_TXN_CAPABLE: /* ODBC 1.0 */
/*
* Postgres can deal with create or drop table statements in a
* transaction
@ -677,7 +665,8 @@ SQLGetInfo(
* what length would be required if a real buffer had been passed in.
*/
if (p)
{ /* char/binary data */
{
/* char/binary data */
len = strlen(p);
if (rgbInfoValue)
@ -692,13 +681,11 @@ SQLGetInfo(
}
}
}
else
{ /* numeric data */
{
/* numeric data */
if (rgbInfoValue)
{
if (len == 2)
*((WORD *) rgbInfoValue) = (WORD) value;
else if (len == 4)
@ -712,8 +699,6 @@ SQLGetInfo(
return result;
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLGetTypeInfo(
@ -725,7 +710,7 @@ SQLGetTypeInfo(
TupleNode *row;
int i;
/* Int4 type; */
/* Int4 type; */
Int4 pgType;
Int2 sqlType;
@ -737,7 +722,6 @@ SQLGetTypeInfo(
return SQL_INVALID_HANDLE;
}
stmt->manual_result = TRUE;
stmt->result = QR_Constructor();
if (!stmt->result)
@ -801,7 +785,6 @@ SQLGetTypeInfo(
}
}
stmt->status = STMT_FINISHED;
stmt->currTuple = -1;
stmt->rowset_start = -1;
@ -810,7 +793,6 @@ SQLGetTypeInfo(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLGetFunctions(
@ -824,7 +806,6 @@ SQLGetFunctions(
if (fFunction == SQL_API_ALL_FUNCTIONS)
{
if (globals.lie)
{
int i;
@ -910,13 +891,10 @@ SQLGetFunctions(
}
else
{
if (globals.lie)
*pfExists = TRUE;
else
{
switch (fFunction)
{
case SQL_API_SQLALLOCCONNECT:
@ -1094,12 +1072,10 @@ SQLGetFunctions(
}
}
}
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLTables(
HSTMT hstmt,
@ -1161,13 +1137,12 @@ SQLTables(
}
tbl_stmt = (StatementClass *) htbl_stmt;
/* ********************************************************************** */
/* Create the query to find out the tables */
/* ********************************************************************** */
/*
* Create the query to find out the tables
*/
if (PG_VERSION_GE(conn, 7.1))
{ /* view is represented by its relkind
* since 7.1 */
{
/* view is represented by its relkind since 7.1 */
strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
strcat(tables_query, " where relkind in ('r', 'v')");
}
@ -1180,15 +1155,12 @@ SQLTables(
my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);
/* Parse the extra systable prefix */
strcpy(prefixes, globals.extra_systable_prefixes);
i = 0;
prefix[i] = strtok(prefixes, ";");
while (prefix[i] && i < 32)
{
prefix[++i] = strtok(NULL, ";");
}
/* Parse the desired table types to return */
show_system_tables = FALSE;
@ -1216,7 +1188,6 @@ SQLTables(
show_regular_tables = TRUE;
else if (strstr(table_type[i], "VIEW"))
show_views = TRUE;
i++;
}
}
@ -1243,21 +1214,17 @@ SQLTables(
strcat(tables_query, prefix[i]);
i++;
}
strcat(tables_query, "'");
}
/* match users */
if (PG_VERSION_LT(conn, 7.1)) /* filter out large objects in
* older versions */
if (PG_VERSION_LT(conn, 7.1))
/* filter out large objects in older versions */
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
strcat(tables_query, " and usesysid = relowner");
strcat(tables_query, " order by relname");
/* ********************************************************************** */
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
@ -1330,7 +1297,6 @@ SQLTables(
result = SQLFetch(htbl_stmt);
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
/*
* Determine if this table name is a system table. If treating
* system tables as regular tables, then no need to do this test.
@ -1338,12 +1304,12 @@ SQLTables(
systable = FALSE;
if (!atoi(ci->show_system_tables))
{
if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
systable = TRUE;
else
{ /* Check extra system table prefixes */
{
/* Check extra system table prefixes */
i = 0;
while (prefix[i])
{
@ -1359,8 +1325,8 @@ SQLTables(
}
/* Determine if the table name is a view */
if (PG_VERSION_GE(conn, 7.1)) /* view is represented by its
* relkind since 7.1 */
if (PG_VERSION_GE(conn, 7.1))
/* view is represented by its relkind since 7.1 */
view = (relkind_or_hasrules[0] == 'v');
else
view = (relkind_or_hasrules[0] == '1');
@ -1379,16 +1345,18 @@ SQLTables(
(view && show_views) ||
(regular_table && show_regular_tables))
{
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
set_tuplefield_string(&row->tuple[0], "");
/* I have to hide the table owner from Access, otherwise it */
/* insists on referring to the table as 'owner.table'. */
/* (this is valid according to the ODBC SQL grammar, but */
/* Postgres won't support it.) */
/* set_tuplefield_string(&row->tuple[1], table_owner); */
/*
* I have to hide the table owner from Access, otherwise it
* insists on referring to the table as 'owner.table'.
* (this is valid according to the ODBC SQL grammar, but
* Postgres won't support it.)
*
* set_tuplefield_string(&row->tuple[1], table_owner);
*/
mylog("SQLTables: table_name = '%s'\n", table_name);
@ -1410,8 +1378,10 @@ SQLTables(
return SQL_ERROR;
}
/* also, things need to think that this statement is finished so */
/* the results can be retrieved. */
/*
* also, things need to think that this statement is finished so
* the results can be retrieved.
*/
stmt->status = STMT_FINISHED;
/* set up the current tuple pointer for SQLFetch */
@ -1425,8 +1395,6 @@ SQLTables(
}
RETCODE SQL_API
SQLColumns(
HSTMT hstmt,
@ -1479,13 +1447,10 @@ SQLColumns(
conn = (ConnectionClass *) (stmt->hdbc);
ci = &stmt->hdbc->connInfo;
/* ********************************************************************** */
/*
* Create the query to find out the columns (Note: pre 6.3 did not
* have the atttypmod field)
*/
/* ********************************************************************** */
sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
" from pg_user u, pg_class c, pg_attribute a, pg_type t"
@ -1497,10 +1462,11 @@ SQLColumns(
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
/* give the output in the order the columns were defined */
/* when the table was created */
/*
* give the output in the order the columns were defined
* when the table was created
*/
strcat(columns_query, " order by attnum");
/* ********************************************************************** */
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@ -1673,10 +1639,8 @@ SQLColumns(
QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
result = SQLFetch(hcol_stmt);
/*
* Only show oid if option AND there are other columns AND it's not
* being called by SQLStatistics . Always show OID if it's a system
@ -1685,12 +1649,10 @@ SQLColumns(
if (result != SQL_ERROR && !stmt->internal)
{
if (relhasrules[0] != '1' &&
(atoi(ci->show_oid_column) ||
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
{
/* For OID fields */
the_type = PG_TYPE_OID;
row = (TupleNode *) malloc(sizeof(TupleNode) +
@ -1718,7 +1680,6 @@ SQLColumns(
QR_add_tuple(stmt->result, row);
}
}
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
@ -1776,11 +1737,9 @@ SQLColumns(
}
}
if ((field_type == PG_TYPE_VARCHAR) ||
(field_type == PG_TYPE_BPCHAR))
{
useStaticPrecision = FALSE;
if (mod_length >= 4)
@ -1827,8 +1786,10 @@ SQLColumns(
return SQL_ERROR;
}
/* Put the row version column at the end so it might not be */
/* mistaken for a key field. */
/*
* Put the row version column at the end so it might not be
* mistaken for a key field.
*/
if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
{
/* For Row Versioning fields */
@ -1855,8 +1816,10 @@ SQLColumns(
QR_add_tuple(stmt->result, row);
}
/* also, things need to think that this statement is finished so */
/* the results can be retrieved. */
/*
* also, things need to think that this statement is finished so
* the results can be retrieved.
*/
stmt->status = STMT_FINISHED;
/* set up the current tuple pointer for SQLFetch */
@ -1869,6 +1832,7 @@ SQLColumns(
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLSpecialColumns(
HSTMT hstmt,
@ -1892,8 +1856,6 @@ SQLSpecialColumns(
RETCODE result;
char relhasrules[MAX_INFO_STRING];
mylog("%s: entering...stmt=%u\n", func, stmt);
if (!stmt)
@ -1905,10 +1867,9 @@ SQLSpecialColumns(
stmt->manual_result = TRUE;
/* ********************************************************************** */
/* Create the query to find out if this is a view or not... */
/* ********************************************************************** */
/*
* Create the query to find out if this is a view or not...
*/
sprintf(columns_query, "select c.relhasrules "
"from pg_user u, pg_class c where "
"u.usesysid = c.relowner");
@ -1988,7 +1949,6 @@ SQLSpecialColumns(
}
else if (fColType == SQL_ROWVER)
{
Int2 the_type = PG_TYPE_INT4;
if (atoi(ci->row_versioning))
@ -2009,8 +1969,6 @@ SQLSpecialColumns(
}
}
stmt->status = STMT_FINISHED;
stmt->currTuple = -1;
stmt->rowset_start = -1;
@ -2020,6 +1978,7 @@ SQLSpecialColumns(
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLStatistics(
HSTMT hstmt,
@ -2104,9 +2063,10 @@ SQLStatistics(
QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
/* only use the table name... the owner should be redundant, and */
/* we never use qualifiers. */
/*
* only use the table name... the owner should be redundant, and
* we never use qualifiers.
*/
table_name = make_string(szTableName, cbTableName, NULL);
if (!table_name)
{
@ -2116,8 +2076,10 @@ SQLStatistics(
return SQL_ERROR;
}
/* we need to get a list of the field names first, */
/* so we can return them later. */
/*
* we need to get a list of the field names first,
* so we can return them later.
*/
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
@ -2172,6 +2134,7 @@ SQLStatistics(
result = SQLFetch(hcol_stmt);
}
if (result != SQL_NO_DATA_FOUND || total_columns == 0)
{
stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column
@ -2205,14 +2168,15 @@ SQLStatistics(
result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "Couldn't execute
* index query
* (w/SQLExecDirect) in
* SQLStatistics."; */
/*
* "Couldn't execute index query (w/SQLExecDirect) in
* SQLStatistics.";
*/
stmt->errormsg = SC_create_errormsg(hindx_stmt);
stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA;
}
/* bind the index name column */
@ -2314,7 +2278,6 @@ SQLStatistics(
result = SQLFetch(hindx_stmt);
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
/* If only requesting unique indexs, then just return those. */
if (fUnique == SQL_INDEX_ALL ||
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
@ -2323,7 +2286,6 @@ SQLStatistics(
/* add a row in this table for each field in the index */
while (i < 16 && fields_vector[i] != 0)
{
row = (TupleNode *) malloc(sizeof(TupleNode) +
(13 - 1) *sizeof(TupleField));
@ -2380,8 +2342,8 @@ SQLStatistics(
}
if (result != SQL_NO_DATA_FOUND)
{
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "SQLFetch failed in
* SQLStatistics."; */
/* "SQLFetch failed in SQLStatistics."; */
stmt->errormsg = SC_create_errormsg(hindx_stmt);
stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA;
@ -2389,8 +2351,10 @@ SQLStatistics(
SQLFreeStmt(hindx_stmt, SQL_DROP);
/* also, things need to think that this statement is finished so */
/* the results can be retrieved. */
/*
* also, things need to think that this statement is finished so
* the results can be retrieved.
*/
stmt->status = STMT_FINISHED;
/* set up the current tuple pointer for SQLFetch */
@ -2418,6 +2382,7 @@ SEEYA:
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLColumnPrivileges(
HSTMT hstmt,
@ -2434,15 +2399,17 @@ SQLColumnPrivileges(
mylog("%s: entering...\n", func);
/* Neither Access or Borland care about this. */
/* Neither Access or Borland care about this. */
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
/* SQLPrimaryKeys()
* Retrieve the primary key columns for the specified table.
/*
* SQLPrimaryKeys()
*
* Retrieve the primary key columns for the specified table.
*/
RETCODE SQL_API
SQLPrimaryKeys(
@ -2572,7 +2539,6 @@ SQLPrimaryKeys(
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
set_tuplefield_null(&row->tuple[0]);
@ -2608,8 +2574,10 @@ SQLPrimaryKeys(
SQLFreeStmt(htbl_stmt, SQL_DROP);
/* also, things need to think that this statement is finished so */
/* the results can be retrieved. */
/*
* also, things need to think that this statement is finished so
* the results can be retrieved.
*/
stmt->status = STMT_FINISHED;
/* set up the current tuple pointer for SQLFetch */
@ -2621,6 +2589,7 @@ SQLPrimaryKeys(
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLForeignKeys(
HSTMT hstmt,
@ -2667,14 +2636,11 @@ SQLForeignKeys(
#if (ODBCVER >= 0x0300)
SWORD defer_type;
#endif
char pkey[MAX_INFO_STRING];
Int2 result_cols;
mylog("%s: entering...stmt=%u\n", func, stmt);
mylog("%s: entering...stmt=%u\n", func, stmt);
if (!stmt)
{
@ -2723,8 +2689,10 @@ SQLForeignKeys(
QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
#endif /* ODBCVER >= 0x0300 */
/* also, things need to think that this statement is finished so */
/* the results can be retrieved. */
/*
* also, things need to think that this statement is finished so
* the results can be retrieved.
*/
stmt->status = STMT_FINISHED;
/* set up the current tuple pointer for SQLFetch */
@ -2898,7 +2866,6 @@ SQLForeignKeys(
while (result == SQL_SUCCESS)
{
/* Compute the number of keyparts. */
num_keys = (trig_nargs - 4) / 2;
@ -2913,7 +2880,6 @@ SQLForeignKeys(
/* If there is a pk table specified, then check it. */
if (pk_table_needed[0] != '\0')
{
/* If it doesn't match, then continue */
if (strcmp(pk_table, pk_table_needed))
{
@ -2932,7 +2898,6 @@ SQLForeignKeys(
return SQL_ERROR;
}
/* Check that the key listed is the primary key */
keyresult = SQLFetch(hpkey_stmt);
@ -2949,7 +2914,6 @@ SQLForeignKeys(
num_keys = 0;
break;
}
/* Get to next primary key */
for (k = 0; k < 2; k++)
pkey_ptr += strlen(pkey_ptr) + 1;
@ -3002,7 +2966,6 @@ SQLForeignKeys(
for (k = 0; k < num_keys; k++)
{
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
@ -3050,7 +3013,6 @@ SQLForeignKeys(
*/
else if (pk_table_needed[0] != '\0')
{
sprintf(tables_query, "SELECT pg_trigger.tgargs, "
" pg_trigger.tgnargs, "
" pg_trigger.tgdeferrable, "
@ -3172,7 +3134,6 @@ SQLForeignKeys(
while (result == SQL_SUCCESS)
{
/* Calculate the number of key parts */
num_keys = (trig_nargs - 4) / 2;;
@ -3216,7 +3177,6 @@ SQLForeignKeys(
for (i = 0; i < 5; i++)
pkey_ptr += strlen(pkey_ptr) + 1;
/* Get to first foreign table */
fk_table = trig_args;
fk_table += strlen(fk_table) + 1;
@ -3228,7 +3188,6 @@ SQLForeignKeys(
for (k = 0; k < num_keys; k++)
{
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
@ -3270,7 +3229,6 @@ SQLForeignKeys(
fkey_ptr += strlen(fkey_ptr) + 1;
}
}
result = SQLFetch(htbl_stmt);
}
}
@ -3290,7 +3248,6 @@ SQLForeignKeys(
}
RETCODE SQL_API
SQLProcedureColumns(
HSTMT hstmt,
@ -3311,6 +3268,7 @@ SQLProcedureColumns(
return SQL_ERROR;
}
RETCODE SQL_API
SQLProcedures(
HSTMT hstmt,
@ -3329,6 +3287,7 @@ SQLProcedures(
return SQL_ERROR;
}
RETCODE SQL_API
SQLTablePrivileges(
HSTMT hstmt,

View File

@ -1,4 +1,5 @@
/* Module: lobj.c
/*--------
* Module: lobj.c
*
* Description: This module contains routines related to manipulating
* large objects.
@ -8,13 +9,14 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
#include "lobj.h"
#include "psqlodbc.h"
#include "connection.h"
Oid
lo_creat(ConnectionClass *conn, int mode)
{
@ -30,18 +32,16 @@ lo_creat(ConnectionClass *conn, int mode)
return 0; /* invalid oid */
else
return retval;
}
int
lo_open(ConnectionClass *conn, int lobjId, int mode)
{
int fd;
int result_len;
LO_ARG argv[2];
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = lobjId;
@ -59,6 +59,7 @@ lo_open(ConnectionClass *conn, int lobjId, int mode)
return fd;
}
int
lo_close(ConnectionClass *conn, int fd)
{
@ -66,17 +67,14 @@ lo_close(ConnectionClass *conn, int fd)
int retval,
result_len;
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
if (!CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1))
return -1;
else
return retval;
}
@ -86,7 +84,6 @@ lo_read(ConnectionClass *conn, int fd, char *buf, int len)
LO_ARG argv[2];
int result_len;
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
@ -97,11 +94,11 @@ lo_read(ConnectionClass *conn, int fd, char *buf, int len)
if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2))
return -1;
else
return result_len;
}
int
lo_write(ConnectionClass *conn, int fd, char *buf, int len)
{
@ -109,7 +106,6 @@ lo_write(ConnectionClass *conn, int fd, char *buf, int len)
int retval,
result_len;
if (len <= 0)
return 0;
@ -123,11 +119,11 @@ lo_write(ConnectionClass *conn, int fd, char *buf, int len)
if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2))
return -1;
else
return retval;
}
int
lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
{
@ -135,7 +131,6 @@ lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
int retval,
result_len;
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
@ -150,11 +145,11 @@ lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3))
return -1;
else
return retval;
}
int
lo_tell(ConnectionClass *conn, int fd)
{
@ -162,18 +157,17 @@ lo_tell(ConnectionClass *conn, int fd)
int retval,
result_len;
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
if (!CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1))
return -1;
else
return retval;
}
int
lo_unlink(ConnectionClass *conn, Oid lobjId)
{
@ -181,14 +175,12 @@ lo_unlink(ConnectionClass *conn, Oid lobjId)
int retval,
result_len;
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = lobjId;
if (!CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1))
return -1;
else
return retval;
}

View File

@ -1,4 +1,5 @@
/* Module: misc.c
/*-------
* Module: misc.c
*
* Description: This module contains miscellaneous routines
* such as for debugging/logging and string functions.
@ -8,7 +9,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#include <stdio.h>
@ -31,6 +32,7 @@
extern GLOBAL_VALUES globals;
void generate_filename(char *, char *, char *);
void
generate_filename(char *dirname, char *prefix, char *filename)
{
@ -56,8 +58,8 @@ generate_filename(char *dirname, char *prefix, char *filename)
return;
}
#ifdef MY_LOG
#ifdef MY_LOG
void
mylog(char *fmt,...)
{
@ -83,12 +85,10 @@ mylog(char *fmt,...)
va_end(args);
}
}
#endif
#ifdef Q_LOG
void
qlog(char *fmt,...)
{
@ -114,7 +114,6 @@ qlog(char *fmt,...)
va_end(args);
}
}
#endif
/* Undefine these because windows.h will redefine and cause a warning */
@ -137,7 +136,10 @@ qlog(char *fmt,...)
#endif
/* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */
/*
* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied
* (not including null term)
*/
int
my_strcpy(char *dst, int dst_len, char *src, int src_len)
{
@ -154,7 +156,6 @@ 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)
@ -173,10 +174,13 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
return strlen(dst);
}
/* strncpy copies up to len characters, and doesn't terminate */
/* the destination string if src has len characters or more. */
/* instead, I want it to copy up to len-1 characters and always */
/* terminate the destination string. */
/*
* strncpy copies up to len characters, and doesn't terminate
* the destination string if src has len characters or more.
* instead, I want it to copy up to len-1 characters and always
* terminate the destination string.
*/
char *
strncpy_null(char *dst, const char *src, int len)
{
@ -185,7 +189,6 @@ strncpy_null(char *dst, const char *src, int len)
if (NULL != dst)
{
/* Just in case, check for special lengths */
if (len == SQL_NULL_DATA)
{
@ -204,9 +207,14 @@ strncpy_null(char *dst, const char *src, int len)
return dst;
}
/* Create a null terminated string (handling the SQL_NTS thing): */
/* 1. If buf is supplied, place the string in there (assumes enough space) and return buf. */
/* 2. If buf is not supplied, malloc space and return this string */
/*------
* Create a null terminated string (handling the SQL_NTS thing):
* 1. If buf is supplied, place the string in there
* (assumes enough space) and return buf.
* 2. If buf is not supplied, malloc space and return this string
*------
*/
char *
make_string(char *s, int len, char *buf)
{
@ -234,14 +242,16 @@ make_string(char *s, int len, char *buf)
return NULL;
}
/* Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing. */
/* "fmt" must contain somewhere in it the single form '%.*s' */
/* This is heavily used in creating queries for info routines (SQLTables, SQLColumns). */
/* This routine could be modified to use vsprintf() to handle multiple arguments. */
/*
* Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing.
* "fmt" must contain somewhere in it the single form '%.*s'.
* This is heavily used in creating queries for info routines (SQLTables, SQLColumns).
* This routine could be modified to use vsprintf() to handle multiple arguments.
*/
char *
my_strcat(char *buf, char *fmt, char *s, int len)
{
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
{
int length = (len > 0) ? len : strlen(s);
@ -254,6 +264,7 @@ my_strcat(char *buf, char *fmt, char *s, int len)
return NULL;
}
void
remove_newlines(char *string)
{
@ -267,6 +278,7 @@ remove_newlines(char *string)
}
}
char *
trim(char *s)
{

View File

@ -1,10 +1,10 @@
/*
/*--------
* Module : multibyte.c
*
* Description: Mlutibyte related additional function.
*
* Create 2001-03-03 Eiji Tokuya
*
*--------
*/
#include <string.h>
@ -13,6 +13,7 @@
int multibyte_client_encoding; /* Multibyte Client Encoding. */
int multibyte_status; /* Multibyte Odds and ends character. */
unsigned char *
multibyte_strchr(unsigned char *s, unsigned char c)
{
@ -36,7 +37,6 @@ multibyte_strchr(unsigned char *s, unsigned char c)
}
break;
/* Chinese Big5 Support. */
case BIG5:
{
@ -59,12 +59,14 @@ multibyte_strchr(unsigned char *s, unsigned char c)
return (s + i);
}
void
multibyte_init(void)
{
multibyte_status = 0;
}
unsigned char *
check_client_encoding(unsigned char *str)
{
@ -81,19 +83,21 @@ check_client_encoding(unsigned char *str)
return ("OHTER");
}
/*
/*--------
* Multibyte Status Function.
* Input char
* Output 0 : 1 Byte Character.
* 1 : MultibyteCharacter Last Byte.
* N : MultibyteCharacter Fast or Middle Byte.
*--------
*/
int
multibyte_char_check(unsigned char s)
{
switch (multibyte_client_encoding)
{
/* Japanese Shift-JIS(CP932) Support. */
/* Japanese Shift-JIS(CP932) Support. */
case SJIS:
{
if (multibyte_status < 2 && s > 0x80 && !(s > 0x9f && s < 0xE0))
@ -105,20 +109,19 @@ multibyte_char_check(unsigned char s)
}
break;
/* Chinese Big5(CP950) Support. */
case BIG5:
{
if (multibyte_status < 2 && s > 0xA0)
multibyte_status = 2;
else if (multibyte_status == 2)
multibyte_status = 1;
else
multibyte_status = 0;
}
break;
default:
multibyte_status = 0;
/* Chinese Big5(CP950) Support. */
case BIG5:
{
if (multibyte_status < 2 && s > 0xA0)
multibyte_status = 2;
else if (multibyte_status == 2)
multibyte_status = 1;
else
multibyte_status = 0;
}
break;
default:
multibyte_status = 0;
}
#ifdef _DEBUG
qlog("multibyte_client_encoding = %d s = 0x%02X multibyte_stat = %d\n", multibyte_client_encoding, s, multibyte_status);

View File

@ -1,4 +1,5 @@
/* Module: options.c
/*--------
* Module: options.c
*
* Description: This module contains routines for getting/setting
* connection and statement options.
@ -9,7 +10,7 @@
* SQLGetStmtOption
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
#ifdef HAVE_CONFIG_H
@ -43,7 +44,6 @@ RETCODE set_statement_option(ConnectionClass *conn,
UDWORD vParam);
RETCODE
set_statement_option(ConnectionClass *conn,
StatementClass *stmt,
@ -53,7 +53,6 @@ set_statement_option(ConnectionClass *conn,
static char *func = "set_statement_option";
char changed = FALSE;
switch (fOption)
{
case SQL_ASYNC_ENABLE: /* ignored */
@ -68,12 +67,10 @@ set_statement_option(ConnectionClass *conn,
break;
case SQL_CONCURRENCY:
/*
* positioned update isn't supported so cursor concurrency is
* read-only
*/
if (conn)
conn->stmtOptions.scroll_concurrency = vParam;
if (stmt)
@ -104,7 +101,6 @@ set_statement_option(ConnectionClass *conn,
*/
case SQL_CURSOR_TYPE:
/*
* if declare/fetch, then type can only be forward. otherwise,
* it can only be forward or static.
@ -113,18 +109,15 @@ set_statement_option(ConnectionClass *conn,
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)
@ -137,7 +130,6 @@ set_statement_option(ConnectionClass *conn,
{
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
{
if (conn)
conn->stmtOptions.cursor_type = vParam; /* valid type */
if (stmt)
@ -145,7 +137,6 @@ set_statement_option(ConnectionClass *conn,
}
else
{
if (conn)
conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
if (stmt)
@ -167,14 +158,20 @@ set_statement_option(ConnectionClass *conn,
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 */
case SQL_MAX_LENGTH: /* ignored, but saved */
mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.maxLength = vParam;
@ -182,7 +179,7 @@ set_statement_option(ConnectionClass *conn,
stmt->options.maxLength = vParam;
break;
case SQL_MAX_ROWS: /* ignored, but saved */
case SQL_MAX_ROWS: /* ignored, but saved */
mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.maxRows = vParam;
@ -190,16 +187,16 @@ set_statement_option(ConnectionClass *conn,
stmt->options.maxRows = vParam;
break;
case SQL_NOSCAN: /* ignored */
case SQL_NOSCAN: /* ignored */
mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam);
break;
case SQL_QUERY_TIMEOUT:/* ignored */
case SQL_QUERY_TIMEOUT: /* ignored */
mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam);
/* "0" returned in SQLGetStmtOption */
break;
case SQL_RETRIEVE_DATA:/* ignored, but saved */
case SQL_RETRIEVE_DATA: /* ignored, but saved */
mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam);
if (conn)
conn->stmtOptions.retrieve_data = vParam;
@ -210,7 +207,6 @@ set_statement_option(ConnectionClass *conn,
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
@ -230,7 +226,6 @@ set_statement_option(ConnectionClass *conn,
conn->stmtOptions.rowset_size = vParam;
if (stmt)
stmt->options.rowset_size = vParam;
break;
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
@ -249,7 +244,6 @@ set_statement_option(ConnectionClass *conn,
return SQL_ERROR;
case SQL_USE_BOOKMARKS:
if (stmt)
stmt->options.use_bookmarks = vParam;
if (conn)
@ -298,7 +292,6 @@ set_statement_option(ConnectionClass *conn,
}
/* Implements only SQL_AUTOCOMMIT */
RETCODE SQL_API
SQLSetConnectOption(
@ -320,14 +313,12 @@ SQLSetConnectOption(
return SQL_INVALID_HANDLE;
}
switch (fOption)
{
/*
* Statement Options (apply to all stmts on the connection and
* become defaults for new stmts)
*/
/*
* Statement Options (apply to all stmts on the connection and
* become defaults for new stmts)
*/
case SQL_ASYNC_ENABLE:
case SQL_BIND_TYPE:
case SQL_CONCURRENCY:
@ -362,15 +353,14 @@ SQLSetConnectOption(
break;
/**********************************/
/***** Connection Options *******/
/**********************************/
/*
* Connection Options
*/
case SQL_ACCESS_MODE: /* ignored */
break;
case SQL_AUTOCOMMIT:
if (CC_is_in_trans(conn))
{
conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
@ -397,13 +387,12 @@ SQLSetConnectOption(
CC_log_error(func, "", conn);
return SQL_ERROR;
}
break;
case SQL_CURRENT_QUALIFIER: /* ignored */
break;
case SQL_LOGIN_TIMEOUT:/* ignored */
case SQL_LOGIN_TIMEOUT: /* ignored */
break;
case SQL_PACKET_SIZE: /* ignored */
@ -412,10 +401,10 @@ SQLSetConnectOption(
case SQL_QUIET_MODE: /* ignored */
break;
case SQL_TXN_ISOLATION:/* ignored */
case SQL_TXN_ISOLATION: /* ignored */
break;
/* These options should be handled by driver manager */
/* These options should be handled by driver manager */
case SQL_ODBC_CURSORS:
case SQL_OPT_TRACE:
case SQL_OPT_TRACEFILE:
@ -434,7 +423,6 @@ SQLSetConnectOption(
CC_log_error(func, option, conn);
return SQL_ERROR;
}
}
if (changed)
@ -447,7 +435,6 @@ SQLSetConnectOption(
return SQL_SUCCESS;
}
/* - - - - - - - - - */
/* This function just can tell you whether you are in Autcommit mode or not */
RETCODE SQL_API
@ -469,7 +456,7 @@ SQLGetConnectOption(
switch (fOption)
{
case SQL_ACCESS_MODE: /* NOT SUPPORTED */
case SQL_ACCESS_MODE: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
break;
@ -484,23 +471,23 @@ SQLGetConnectOption(
break;
case SQL_LOGIN_TIMEOUT:/* NOT SUPPORTED */
case SQL_LOGIN_TIMEOUT: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = 0;
break;
case SQL_PACKET_SIZE: /* NOT SUPPORTED */
case SQL_PACKET_SIZE: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = globals.socket_buffersize;
break;
case SQL_QUIET_MODE: /* NOT SUPPORTED */
case SQL_QUIET_MODE: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = (UDWORD) NULL;
break;
case SQL_TXN_ISOLATION:/* NOT SUPPORTED */
case SQL_TXN_ISOLATION: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = SQL_TXN_SERIALIZABLE;
break;
/* These options should be handled by driver manager */
/* These options should be handled by driver manager */
case SQL_ODBC_CURSORS:
case SQL_OPT_TRACE:
case SQL_OPT_TRACEFILE:
@ -520,13 +507,11 @@ SQLGetConnectOption(
return SQL_ERROR;
break;
}
}
return SQL_SUCCESS;
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLSetStmtOption(
@ -539,10 +524,11 @@ SQLSetStmtOption(
mylog("%s: entering...\n", func);
/* thought we could fake Access out by just returning SQL_SUCCESS */
/* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */
/* and expects the driver to reduce it to the real value */
/*
* Though we could fake Access out by just returning SQL_SUCCESS
* all the time, but it tries to set a huge value for SQL_MAX_LENGTH
* and expects the driver to reduce it to the real value.
*/
if (!stmt)
{
SC_log_error(func, "", NULL);
@ -553,8 +539,6 @@ SQLSetStmtOption(
}
/* - - - - - - - - - */
RETCODE SQL_API
SQLGetStmtOption(
HSTMT hstmt,
@ -567,10 +551,11 @@ SQLGetStmtOption(
mylog("%s: entering...\n", func);
/* thought we could fake Access out by just returning SQL_SUCCESS */
/* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */
/* and expects the driver to reduce it to the real value */
/*
* thought we could fake Access out by just returning SQL_SUCCESS
* all the time, but it tries to set a huge value for SQL_MAX_LENGTH
* and expects the driver to reduce it to the real value
*/
if (!stmt)
{
SC_log_error(func, "", NULL);
@ -689,5 +674,3 @@ SQLGetStmtOption(
return SQL_SUCCESS;
}
/* - - - - - - - - - */

View File

@ -1,20 +1,24 @@
/* Module: parse.c
/*--------
* Module: parse.c
*
* Description: This module contains routines related to parsing SQL statements.
* This can be useful for two reasons:
* Description: This module contains routines related to parsing SQL
* statements. This can be useful for two reasons:
*
* 1. So the query does not actually have to be executed to return data about it
* 1. So the query does not actually have to be executed
* to return data about it
*
* 2. To be able to return information about precision, nullability, aliases, etc.
* in the functions SQLDescribeCol and SQLColAttributes. Currently, Postgres
* doesn't return any information about these things in a query.
* 2. To be able to return information about precision,
* nullability, aliases, etc. in the functions
* SQLDescribeCol and SQLColAttributes. Currently,
* Postgres doesn't return any information about
* these things in a query.
*
* Classes: none
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
@ -50,6 +54,7 @@ char *getNextToken(char *s, char *token, int smax, char *delim, char *quote,
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
char *
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
{
@ -87,7 +92,6 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
s[i] != '\0' && out != smax)
{
/* Handle quoted stuff */
if (out == 0 && (s[i] == '\"' || s[i] == '\''))
{
@ -225,13 +229,13 @@ getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
}
char
searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
{
int k, cmp;
char *col;
for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
{
col = QR_get_value_manual(col_info->result, k, 3);
@ -289,7 +293,6 @@ parse_statement(StatementClass *stmt)
StatementClass *col_stmt;
RETCODE result;
mylog("%s: entering...\n", func);
ptr = stmt->statement;
@ -301,7 +304,6 @@ parse_statement(StatementClass *stmt)
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);
@ -345,7 +347,6 @@ parse_statement(StatementClass *stmt)
!stricmp(token, "group") ||
!stricmp(token, "having")))
{
in_select = FALSE;
in_from = FALSE;
in_where = TRUE;
@ -356,7 +357,6 @@ parse_statement(StatementClass *stmt)
if (in_select)
{
if (in_distinct)
{
mylog("in distinct\n");
@ -378,7 +378,8 @@ parse_statement(StatementClass *stmt)
}
if (in_expr || in_func)
{ /* just eat the expression */
{
/* just eat the expression */
mylog("in_expr=%d or func=%d\n", in_expr, in_func);
if (quote || dquote)
continue;
@ -389,7 +390,6 @@ parse_statement(StatementClass *stmt)
in_expr = FALSE;
in_field = FALSE;
}
else if (token[0] == '(')
{
blevel++;
@ -414,7 +414,6 @@ parse_statement(StatementClass *stmt)
if (!in_field)
{
if (!token[0])
continue;
@ -462,7 +461,6 @@ parse_statement(StatementClass *stmt)
blevel = 1;
continue;
}
else
{
strcpy(fi[stmt->nfld]->name, token);
@ -478,9 +476,9 @@ parse_statement(StatementClass *stmt)
continue;
}
/**************************/
/* We are in a field now */
/**************************/
/*
* We are in a field now
*/
if (in_dot)
{
stmt->nfld--;
@ -494,7 +492,6 @@ parse_statement(StatementClass *stmt)
mylog("in_dot: got comma\n");
in_field = FALSE;
}
continue;
}
@ -547,12 +544,10 @@ 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 (!token[0])
@ -603,17 +598,15 @@ parse_statement(StatementClass *stmt)
}
}
/*************************************************/
/* Resolve any possible field names with tables */
/*************************************************/
/*
* Resolve any possible field names with tables
*/
parse = TRUE;
/* Resolve field names with tables */
for (i = 0; i < stmt->nfld; i++)
{
if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
{
fi[i]->ti = NULL;
@ -621,7 +614,6 @@ parse_statement(StatementClass *stmt)
parse = FALSE;
continue;
}
else if (fi[i]->quote)
{ /* handle as text */
fi[i]->ti = NULL;
@ -629,7 +621,6 @@ parse_statement(StatementClass *stmt)
fi[i]->precision = 0;
continue;
}
/* it's a dot, resolve to table or alias */
else if (fi[i]->dot[0])
{
@ -665,15 +656,13 @@ parse_statement(StatementClass *stmt)
mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);
/******************************************************/
/* Now save the SQLColumns Info for the parse tables */
/******************************************************/
/*
* Now save the SQLColumns Info for the parse tables
*/
/* Call SQLColumns for each table and store the result */
for (i = 0; i < stmt->ntab; i++)
{
/* See if already got it */
char found = FALSE;
@ -689,7 +678,6 @@ parse_statement(StatementClass *stmt)
if (!found)
{
mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
@ -713,7 +701,6 @@ parse_statement(StatementClass *stmt)
mylog(" Success\n");
if (!(conn->ntables % COL_INCR))
{
mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables);
conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *));
@ -762,18 +749,13 @@ parse_statement(StatementClass *stmt)
mylog("associate col_info: i=%d, k=%d\n", i, k);
}
mylog("Done SQLColumns\n");
/******************************************************/
/* Now resolve the fields to point to column info */
/******************************************************/
/*
* Now resolve the fields to point to column info
*/
for (i = 0; i < stmt->nfld;)
{
/* Dont worry about functions or quotes */
if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
{
@ -784,7 +766,6 @@ parse_statement(StatementClass *stmt)
/* Stars get expanded to all fields in the table */
else if (fi[i]->name[0] == '*')
{
char do_all_tables;
int total_cols,
old_alloc,
@ -810,7 +791,6 @@ parse_statement(StatementClass *stmt)
increased_cols = total_cols - 1;
/* Allocate some more field pointers if necessary */
/*------------------------------------------------------------- */
old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR;
new_size = stmt->nfld + increased_cols;
@ -830,8 +810,6 @@ parse_statement(StatementClass *stmt)
stmt->fi = fi;
}
/*------------------------------------------------------------- */
/*
* copy any other fields (if there are any) up past the
* expansion
@ -843,21 +821,16 @@ parse_statement(StatementClass *stmt)
}
mylog("done copying fields\n");
/*------------------------------------------------------------- */
/* Set the new number of fields */
stmt->nfld += increased_cols;
mylog("stmt->nfld now at %d\n", stmt->nfld);
/*------------------------------------------------------------- */
/* copy the new field info */
do_all_tables = (fi[i]->ti ? FALSE : TRUE);
for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)
{
TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
cols = QR_get_num_tuples(the_ti->col_info->result);
@ -890,8 +863,6 @@ parse_statement(StatementClass *stmt)
i += cols;
mylog("i now at %d\n", i);
}
/*------------------------------------------------------------- */
}
/*
@ -901,7 +872,6 @@ parse_statement(StatementClass *stmt)
*/
else if (fi[i]->ti)
{
if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
parse = FALSE;
@ -925,13 +895,11 @@ parse_statement(StatementClass *stmt)
}
}
if (!parse)
stmt->parse_status = STMT_PARSE_INCOMPLETE;
else
stmt->parse_status = STMT_PARSE_COMPLETE;
mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
return parse;
}

View File

@ -1,17 +1,19 @@
/* Module: pgtypes.c
/*--------
* Module: pgtypes.c
*
* Description: This module contains routines for getting information
* about the supported Postgres data types. Only the function
* pgtype_to_sqltype() returns an unknown condition. All other
* functions return a suitable default so that even data types that
* are not directly supported can be used (it is handled as char data).
* about the supported Postgres data types. Only the
* function pgtype_to_sqltype() returns an unknown condition.
* All other functions return a suitable default so that
* even data types that are not directly supported can be
* used (it is handled as char data).
*
* Classes: n/a
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
#ifdef HAVE_CONFIG_H
@ -40,15 +42,18 @@ extern GLOBAL_VALUES globals;
Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
/*
* these are the types we support. all of the pgtype_ functions should
* return values for each one of these.
* Even types not directly supported are handled as character types
* so all types should work (points, etc.)
*/
/* these are the types we support. all of the pgtype_ functions should */
/* return values for each one of these. */
/* Even types not directly supported are handled as character types
so all types should work (points, etc.) */
/*
* ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all
* the SQL TYPES are reported and mapped to a corresponding Postgres Type
*/
/* ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all
the SQL TYPES are reported and mapped to a corresponding Postgres Type
*/
/*
Int4 pgtypes_defined[] = {
PG_TYPE_CHAR,
@ -102,6 +107,7 @@ Int2 sqlTypes[] = {
0
};
Int4
sqltype_to_pgtype(SWORD fSqlType)
{
@ -109,7 +115,6 @@ sqltype_to_pgtype(SWORD fSqlType)
switch (fSqlType)
{
case SQL_BINARY:
pgType = PG_TYPE_BYTEA;
break;
@ -185,15 +190,19 @@ sqltype_to_pgtype(SWORD fSqlType)
return pgType;
}
/* There are two ways of calling this function:
1. When going through the supported PG types (SQLGetTypeInfo)
2. When taking any type id (SQLColumns, SQLGetData)
The first type will always work because all the types defined are returned here.
The second type will return a default based on global parameter when it does not
know. This allows for supporting
types that are unknown. All other pg routines in here return a suitable default.
*/
/*
* There are two ways of calling this function:
*
* 1. When going through the supported PG types (SQLGetTypeInfo)
*
* 2. When taking any type id (SQLColumns, SQLGetData)
*
* The first type will always work because all the types defined are returned here.
* The second type will return a default based on global parameter when it does not
* know. This allows for supporting
* types that are unknown. All other pg routines in here return a suitable default.
*/
Int2
pgtype_to_sqltype(StatementClass *stmt, Int4 type)
{
@ -228,7 +237,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
case PG_TYPE_INT4:
return SQL_INTEGER;
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
case PG_TYPE_INT8:
return SQL_CHAR;
@ -253,20 +262,20 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
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.
*/
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
/* hack until permanent type is available */
if (type == stmt->hdbc->lobj_type)
return SQL_LONGVARBINARY;
return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
}
}
Int2
pgtype_to_ctype(StatementClass *stmt, Int4 type)
{
@ -305,21 +314,21 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
return SQL_C_BINARY;
default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
/* hack until permanent type is available */
if (type == stmt->hdbc->lobj_type)
return SQL_C_BINARY;
return SQL_C_CHAR;
}
}
char *
pgtype_to_name(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_CHAR:return "char";
case PG_TYPE_CHAR:return "char";
case PG_TYPE_CHAR2:
return "char2";
case PG_TYPE_CHAR4:
@ -369,8 +378,8 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
return PG_TYPE_LO_NAME;
default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
/* hack until permanent type is available */
if (type == stmt->hdbc->lobj_type)
return PG_TYPE_LO_NAME;
/*
@ -381,6 +390,7 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
}
}
static Int2
getNumericScale(StatementClass *stmt, Int4 type, int col)
{
@ -417,6 +427,7 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
PG_NUMERIC_MAX_SCALE);
}
static Int4
getNumericPrecision(StatementClass *stmt, Int4 type, int col)
{
@ -453,6 +464,7 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
PG_NUMERIC_MAX_PRECISION);
}
Int4
getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
@ -524,19 +536,19 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
return p;
}
/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
override this length with the atttypmod length from pg_attribute .
If col >= 0, then will attempt to get the info from the result set.
This is used for functions SQLDescribeCol and SQLColAttributes.
*/
/*
* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
* override this length with the atttypmod length from pg_attribute .
*
* If col >= 0, then will attempt to get the info from the result set.
* This is used for functions SQLDescribeCol and SQLColAttributes.
*/
Int4
pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_CHAR:
return 1;
case PG_TYPE_CHAR2:
@ -597,10 +609,10 @@ 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)
{
switch (type)
{
case PG_TYPE_INT2:
@ -628,22 +640,22 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
case PG_TYPE_FLOAT8:
return 22;
/* Character types use regular precision */
/* Character types use regular precision */
default:
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
}
}
/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
override this length with the atttypmod length from pg_attribute
*/
/*
* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
* override this length with the atttypmod length from pg_attribute
*/
Int4
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_INT2:
return 2;
@ -674,19 +686,18 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
case PG_TYPE_TIMESTAMP:
return 16;
/* Character types (and NUMERIC) use the default precision */
/* Character types (and NUMERIC) use the default precision */
default:
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
}
}
Int2
pgtype_scale(StatementClass *stmt, Int4 type, int col)
{
switch (type)
{
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -697,10 +708,10 @@ 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:
@ -729,24 +740,24 @@ pgtype_radix(StatementClass *stmt, Int4 type)
case PG_TYPE_MONEY:
case PG_TYPE_FLOAT8:
return 10;
default:
return -1;
}
}
Int2
pgtype_nullable(StatementClass *stmt, Int4 type)
{
return SQL_NULLABLE; /* everything should be nullable */
}
Int2
pgtype_auto_increment(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -770,6 +781,7 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_case_sensitive(StatementClass *stmt, Int4 type)
{
@ -792,6 +804,7 @@ pgtype_case_sensitive(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_money(StatementClass *stmt, Int4 type)
{
@ -804,6 +817,7 @@ pgtype_money(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_searchable(StatementClass *stmt, Int4 type)
{
@ -825,6 +839,7 @@ pgtype_searchable(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_unsigned(StatementClass *stmt, Int4 type)
{
@ -848,12 +863,12 @@ pgtype_unsigned(StatementClass *stmt, Int4 type)
}
}
char *
pgtype_literal_prefix(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -869,12 +884,12 @@ pgtype_literal_prefix(StatementClass *stmt, Int4 type)
}
}
char *
pgtype_literal_suffix(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_INT2:
case PG_TYPE_OID:
case PG_TYPE_XID:
@ -890,13 +905,14 @@ pgtype_literal_suffix(StatementClass *stmt, Int4 type)
}
}
char *
pgtype_create_params(StatementClass *stmt, Int4 type)
{
switch (type)
{
case PG_TYPE_CHAR:
case PG_TYPE_VARCHAR:return "max. length";
case PG_TYPE_CHAR:
case PG_TYPE_VARCHAR:return "max. length";
default:
return NULL;
}
@ -906,8 +922,10 @@ pgtype_create_params(StatementClass *stmt, Int4 type)
Int2
sqltype_to_default_ctype(Int2 sqltype)
{
/* from the table on page 623 of ODBC 2.0 Programmer's Reference */
/* (Appendix D) */
/*
* from the table on page 623 of ODBC 2.0 Programmer's Reference
* (Appendix D)
*/
switch (sqltype)
{
case SQL_CHAR:
@ -951,7 +969,8 @@ sqltype_to_default_ctype(Int2 sqltype)
case SQL_TIMESTAMP:
return SQL_C_TIMESTAMP;
default: /* should never happen */
default:
/* should never happen */
return SQL_C_CHAR;
}
}

View File

@ -1,15 +1,16 @@
/* Module: psqlodbc.c
/*--------
* Module: psqlodbc.c
*
* Description: This module contains the main entry point (DllMain) for the library.
* It also contains functions to get and set global variables for the
* driver in the registry.
* Description: This module contains the main entry point (DllMain)
* for the library. It also contains functions to get
* and set global variables for the driver in the registry.
*
* Classes: n/a
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
#ifdef HAVE_CONFIG_H
@ -59,7 +60,6 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return FALSE;
}
@ -71,9 +71,7 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
break;
case DLL_PROCESS_DETACH:
WSACleanup();
return TRUE;
case DLL_THREAD_DETACH:
@ -111,7 +109,8 @@ init(void)
#else /* not __GNUC__ */
/* These two functions do shared library initialziation on UNIX, well at least
/*
* These two functions do shared library initialziation on UNIX, well at least
* on Linux. I don't know about other systems.
*/
BOOL
@ -131,12 +130,14 @@ _fini(void)
#endif /* not WIN32 */
/* This function is used to cause the Driver Manager to
call functions by number rather than name, which is faster.
The ordinal value of this function must be 199 to have the
Driver Manager do this. Also, the ordinal values of the
functions must match the value of fFunction in SQLGetFunctions()
*/
/*
* This function is used to cause the Driver Manager to
* call functions by number rather than name, which is faster.
* The ordinal value of this function must be 199 to have the
* Driver Manager do this. Also, the ordinal values of the
* functions must match the value of fFunction in SQLGetFunctions()
*/
RETCODE SQL_API
SQLDummyOrdinal(void)
{

View File

@ -1,20 +1,23 @@
/* Module: qresult.c
/*---------
* Module: qresult.c
*
* Description: This module contains functions related to
* managing result information (i.e, fetching rows from the backend,
* managing the tuple cache, etc.) and retrieving it.
* Depending on the situation, a QResultClass will hold either data
* from the backend or a manually built result (see "qresult.h" to
* see which functions/macros are for manual or backend results.
* For manually built results, the QResultClass simply points to
* TupleList and ColumnInfo structures, which actually hold the data.
* managing result information (i.e, fetching rows
* from the backend, managing the tuple cache, etc.)
* and retrieving it. Depending on the situation, a
* QResultClass will hold either data from the backend
* or a manually built result (see "qresult.h" to
* see which functions/macros are for manual or backend
* results. For manually built results, the
* QResultClass simply points to TupleList and
* ColumnInfo structures, which actually hold the data.
*
* Classes: QResultClass (Functions prefix: "QR_")
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*---------
*/
#include "qresult.h"
@ -31,8 +34,11 @@
extern GLOBAL_VALUES globals;
/* Used for building a Manual Result only */
/* All info functions call this function to create the manual result set. */
/*
* Used for building a Manual Result only
* All info functions call this function to create the manual result set.
*/
void
QR_set_num_fields(QResultClass *self, int new_num_fields)
{
@ -47,34 +53,38 @@ QR_set_num_fields(QResultClass *self, int new_num_fields)
mylog("exit QR_set_num_fields\n");
}
void
QR_set_position(QResultClass *self, int pos)
{
self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields);
}
void
QR_set_cache_size(QResultClass *self, int cache_size)
{
self->cache_size = cache_size;
}
void
QR_set_rowset_size(QResultClass *self, int rowset_size)
{
self->rowset_size = rowset_size;
}
void
QR_inc_base(QResultClass *self, int base_inc)
{
self->base += base_inc;
}
/************************************/
/* CLASS QResult */
/************************************/
/*
* CLASS QResult
*/
QResultClass *
QR_Constructor(void)
{
@ -111,13 +121,13 @@ QR_Constructor(void)
rv->cache_size = globals.fetch_max;
rv->rowset_size = 1;
}
mylog("exit QR_Constructor\n");
return rv;
}
void
QR_Destructor(QResultClass *self)
{
@ -127,8 +137,10 @@ QR_Destructor(QResultClass *self)
if (self->manual_tuples)
TL_Destructor(self->manual_tuples);
/* If conn is defined, then we may have used "backend_tuples", */
/* so in case we need to, free it up. Also, close the cursor. */
/*
* If conn is defined, then we may have used "backend_tuples",
* so in case we need to, free it up. Also, close the cursor.
*/
if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
QR_close(self); /* close the cursor if there is one */
@ -153,9 +165,9 @@ QR_Destructor(QResultClass *self)
free(self);
mylog("QResult: exit DESTRUCTOR\n");
}
void
QR_set_command(QResultClass *self, char *msg)
{
@ -165,6 +177,7 @@ QR_set_command(QResultClass *self, char *msg)
self->command = msg ? strdup(msg) : NULL;
}
void
QR_set_notice(QResultClass *self, char *msg)
{
@ -174,6 +187,7 @@ QR_set_notice(QResultClass *self, char *msg)
self->notice = msg ? strdup(msg) : NULL;
}
void
QR_free_memory(QResultClass *self)
{
@ -187,7 +201,6 @@ QR_free_memory(QResultClass *self)
if (self->backend_tuples)
{
for (row = 0; row < fcount; row++)
{
mylog("row = %d, num_fields = %d\n", row, num_fields);
@ -211,17 +224,20 @@ QR_free_memory(QResultClass *self)
mylog("QResult: free memory out\n");
}
/* This function is called by send_query() */
char
QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
{
int tuple_size;
/* If called from send_query the first time (conn != NULL), */
/* then set the inTuples state, */
/* and read the tuples. If conn is NULL, */
/* it implies that we are being called from next_tuple(), */
/* like to get more rows so don't call next_tuple again! */
/*
* If called from send_query the first time (conn != NULL),
* then set the inTuples state,
* and read the tuples. If conn is NULL,
* it implies that we are being called from next_tuple(),
* like to get more rows so don't call next_tuple again!
*/
if (conn != NULL)
{
self->conn = conn;
@ -242,8 +258,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
self->cursor = strdup(cursor);
}
/* Read the field attributes. */
/* $$$$ Should do some error control HERE! $$$$ */
/*
* Read the field attributes.
*
* $$$$ Should do some error control HERE! $$$$
*/
if (CI_read_fields(self->fields, self->conn))
{
self->status = PGRES_FIELDS_OK;
@ -275,7 +294,6 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
self->inTuples = TRUE;
/* Force a read to occur in next_tuple */
self->fcount = tuple_size + 1;
self->fetch_count = tuple_size + 1;
@ -285,9 +303,10 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
}
else
{
/* Always have to read the field attributes. */
/* But we dont have to reallocate memory for them! */
/*
* Always have to read the field attributes.
* But we dont have to reallocate memory for them!
*/
if (!CI_read_fields(NULL, self->conn))
{
@ -299,8 +318,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
}
}
/* Close the cursor and end the transaction (if no cursors left) */
/* We only close cursor/end the transaction if a cursor was used. */
/*
* Close the cursor and end the transaction (if no cursors left)
* We only close cursor/end the transaction if a cursor was used.
*/
int
QR_close(QResultClass *self)
{
@ -346,12 +368,12 @@ QR_close(QResultClass *self)
}
QR_Destructor(res);
}
}
return TRUE;
}
/* This function is called by fetch_tuples() AND SQLFetch() */
int
QR_next_tuple(QResultClass *self)
@ -360,7 +382,7 @@ QR_next_tuple(QResultClass *self)
QResultClass *res;
SocketClass *sock;
/* Speed up access */
/* Speed up access */
int fetch_count = self->fetch_count;
int fcount = self->fcount;
int fetch_size,
@ -370,30 +392,31 @@ QR_next_tuple(QResultClass *self)
TupleField *the_tuples = self->backend_tuples;
/* ERROR_MSG_LENGTH is sufficient */
static char msgbuffer[ERROR_MSG_LENGTH + 1];
char cmdbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups
* this string so dont
* need static */
/* QR_set_command() dups this string so doesn't need static */
char cmdbuffer[ERROR_MSG_LENGTH + 1];
char fetch[128];
QueryInfo qi;
if (fetch_count < fcount)
{ /* return a row from cache */
{
/* 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 */
{
/* 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 */
/* end of tuples */
return -1;
}
else
{
/*
* See if we need to fetch another group of rows. We may be being
* called from send_query(), and if so, don't send another fetch,
@ -403,7 +426,6 @@ QR_next_tuple(QResultClass *self)
if (!self->inTuples)
{
if (!globals.use_declarefetch)
{
mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
@ -413,8 +435,8 @@ QR_next_tuple(QResultClass *self)
}
if (self->base == fcount)
{ /* not a correction */
{
/* not a correction */
/* Determine the optimum cache size. */
if (globals.fetch_max % self->rowset_size == 0)
fetch_size = globals.fetch_max;
@ -427,8 +449,8 @@ QR_next_tuple(QResultClass *self)
self->fetch_count = 1;
}
else
{ /* need to correct */
{
/* need to correct */
corrected = TRUE;
fetch_size = end_tuple - fcount;
@ -437,10 +459,8 @@ 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)
{
@ -484,17 +504,16 @@ QR_next_tuple(QResultClass *self)
self->fcount = 0;
}
sock = CC_get_socket(self->conn);
self->tupleField = NULL;
for (;;)
{
id = SOCK_get_char(sock);
switch (id)
{
case 'T': /* Tuples within tuples cannot be handled */
self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Tuples within tuples cannot be handled");
@ -523,11 +542,9 @@ QR_next_tuple(QResultClass *self)
QR_set_message(self, "Error reading the tuple");
return FALSE;
}
self->fcount++;
break; /* continue reading */
case 'C': /* End of tuple list */
SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
QR_set_command(self, cmdbuffer);
@ -537,7 +554,6 @@ QR_next_tuple(QResultClass *self)
self->inTuples = FALSE;
if (self->fcount > 0)
{
qlog(" [ fetched %d rows ]\n", self->fcount);
mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount);
@ -546,8 +562,8 @@ QR_next_tuple(QResultClass *self)
return TRUE;
}
else
{ /* We are surely done here (we read 0
* tuples) */
{
/* 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 */
@ -585,6 +601,7 @@ QR_next_tuple(QResultClass *self)
return TRUE;
}
char
QR_read_tuple(QResultClass *self, char binary)
{
@ -601,7 +618,6 @@ QR_read_tuple(QResultClass *self, char binary)
SocketClass *sock = CC_get_socket(self->conn);
ColumnInfoClass *flds;
/* set the current row to read the fields into */
this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
@ -630,7 +646,6 @@ QR_read_tuple(QResultClass *self, char binary)
}
else
{
/*
* NO, the field is not null. so get at first the length of
* the field (four bytes)

View File

@ -1,17 +1,18 @@
/* Module: results.c
/*-------
* Module: results.c
*
* Description: This module contains functions related to
* retrieving result information through the ODBC API.
*
* Classes: n/a
*
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol, SQLColAttributes,
* SQLGetData, SQLFetch, SQLExtendedFetch,
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol,
* SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch,
* SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
* SQLSetCursorName, SQLGetCursorName
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#ifdef HAVE_CONFIG_H
@ -42,7 +43,6 @@
extern GLOBAL_VALUES globals;
RETCODE SQL_API
SQLRowCount(
HSTMT hstmt,
@ -81,7 +81,6 @@ SQLRowCount(
}
else
{
res = SC_get_Result(stmt);
if (res && pcrow)
{
@ -97,7 +96,6 @@ SQLRowCount(
else
{
*pcrow = -1;
mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow);
}
@ -110,10 +108,10 @@ SQLRowCount(
}
/* This returns the number of columns associated with the database */
/* attached to "hstmt". */
/*
* This returns the number of columns associated with the database
* attached to "hstmt".
*/
RETCODE SQL_API
SQLNumResultCols(
HSTMT hstmt,
@ -135,7 +133,6 @@ SQLNumResultCols(
parse_ok = FALSE;
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE)
{
mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt);
@ -152,7 +149,6 @@ SQLNumResultCols(
if (!parse_ok)
{
SC_pre_execute(stmt);
result = SC_get_Result(stmt);
@ -173,12 +169,10 @@ SQLNumResultCols(
}
/* - - - - - - - - - */
/* Return information about the database column the user wants */
/* information about. */
/*
* Return information about the database column the user wants
* information about.
*/
RETCODE SQL_API
SQLDescribeCol(
HSTMT hstmt,
@ -205,7 +199,6 @@ SQLDescribeCol(
int len = 0;
RETCODE result;
mylog("%s: entering...\n", func);
if (!stmt)
@ -219,29 +212,25 @@ SQLDescribeCol(
SC_clear_error(stmt);
/*
* Dont check for bookmark column. This is the responsibility of the
* driver manager.
* Dont check for bookmark column. This is the responsibility of the
* driver manager.
*/
icol--; /* use zero based column numbers */
parse_ok = FALSE;
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE)
{
mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt);
parse_statement(stmt);
}
mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi);
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
{
if (icol >= stmt->nfld)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
@ -261,11 +250,10 @@ SQLDescribeCol(
}
}
/*
* If couldn't parse it OR the field being described was not parsed
* (i.e., because it was a function or expression, etc, then do it the
* old fashioned way.
* If couldn't parse it OR the field being described was not parsed
* (i.e., because it was a function or expression, etc, then do it the
* old fashioned way.
*/
if (!parse_ok)
{
@ -295,20 +283,19 @@ SQLDescribeCol(
col_name = QR_get_fieldname(res, icol);
fieldtype = QR_get_field_type(res, icol);
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); /* atoi(ci->unknown_sizes
* ) */
}
/* atoi(ci->unknown_sizes) */
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes);
}
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
mylog("describeCol: col %d precision = %d\n", icol, precision);
result = SQL_SUCCESS;
/************************/
/* COLUMN NAME */
/************************/
/*
* COLUMN NAME
*/
len = strlen(col_name);
if (pcbColName)
@ -326,10 +313,9 @@ SQLDescribeCol(
}
}
/************************/
/* SQL TYPE */
/************************/
/*
* SQL TYPE
*/
if (pfSqlType)
{
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
@ -337,12 +323,11 @@ SQLDescribeCol(
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
}
/************************/
/* PRECISION */
/************************/
/*
* PRECISION
*/
if (pcbColDef)
{
if (precision < 0)
precision = 0; /* "I dont know" */
@ -351,9 +336,9 @@ SQLDescribeCol(
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
}
/************************/
/* SCALE */
/************************/
/*
* SCALE
*/
if (pibScale)
{
Int2 scale;
@ -366,9 +351,9 @@ SQLDescribeCol(
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
}
/************************/
/* NULLABILITY */
/************************/
/*
* NULLABILITY
*/
if (pfNullable)
{
*pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
@ -379,8 +364,8 @@ SQLDescribeCol(
return result;
}
/* Returns result column descriptor information for a result set. */
/* Returns result column descriptor information for a result set. */
RETCODE SQL_API
SQLColAttributes(
HSTMT hstmt,
@ -421,16 +406,16 @@ SQLColAttributes(
icol--;
unknown_sizes = globals.unknown_sizes; /* atoi(ci->unknown_sizes);
* */
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) /* not appropriate for
* SQLColAttributes() */
/* atoi(ci->unknown_sizes); */
unknown_sizes = globals.unknown_sizes;
/* not appropriate for SQLColAttributes() */
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW)
unknown_sizes = UNKNOWNS_AS_MAX;
parse_ok = FALSE;
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE)
{
mylog("SQLColAttributes: calling parse_statement\n");
@ -453,7 +438,6 @@ SQLColAttributes(
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
{
if (icol >= cols)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
@ -461,7 +445,6 @@ SQLColAttributes(
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
field_type = stmt->fi[icol]->type;
if (field_type > 0)
parse_ok = TRUE;
@ -522,12 +505,11 @@ SQLColAttributes(
value = pgtype_case_sensitive(stmt, field_type);
break;
/*
* This special case is handled above.
*
* case SQL_COLUMN_COUNT:
*/
/*
* This special case is handled above.
*
* case SQL_COLUMN_COUNT:
*/
case SQL_COLUMN_DISPLAY_SIZE:
value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes);
@ -543,11 +525,10 @@ SQLColAttributes(
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
break;
} /* otherwise same as column name -- FALL
* THROUGH!!! */
}
/* otherwise same as column name -- FALL THROUGH!!! */
case SQL_COLUMN_NAME:
p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);
mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p);
@ -590,7 +571,6 @@ SQLColAttributes(
break;
case SQL_COLUMN_TABLE_NAME:
p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";
mylog("SQLColAttr: TABLE_NAME = '%s'\n", p);
@ -612,14 +592,12 @@ SQLColAttributes(
break;
case SQL_COLUMN_UPDATABLE:
/*
* Neither Access or Borland care about this.
*
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
* else
*/
value = SQL_ATTR_WRITE;
mylog("SQLColAttr: UPDATEABLE = %d\n", value);
@ -648,19 +626,17 @@ SQLColAttributes(
*pcbDesc = len;
}
else
{ /* numeric data */
{
/* numeric data */
if (pfDesc)
*pfDesc = value;
}
return result;
}
/* Returns result data for a single column in the current row. */
/* Returns result data for a single column in the current row. */
RETCODE SQL_API
SQLGetData(
HSTMT hstmt,
@ -707,7 +683,6 @@ SQLGetData(
if (icol == 0)
{
if (stmt->options.use_bookmarks == SQL_UB_OFF)
{
stmt->errornumber = STMT_COLNUM_ERROR;
@ -726,12 +701,9 @@ SQLGetData(
}
get_bookmark = TRUE;
}
else
{
/* use zero-based column numbers */
icol--;
@ -770,7 +742,8 @@ SQLGetData(
}
}
else
{ /* it's a SOCKET result (backend data) */
{
/* it's a SOCKET result (backend data) */
if (stmt->currTuple == -1 || !res || !res->tupleField)
{
stmt->errormsg = "Not positioned on a valid row for GetData.";
@ -845,10 +818,10 @@ SQLGetData(
}
/* Returns data for bound columns in the current row ("hstmt->iCursor"), */
/* advances the cursor. */
/*
* Returns data for bound columns in the current row ("hstmt->iCursor"),
* advances the cursor.
*/
RETCODE SQL_API
SQLFetch(
HSTMT hstmt)
@ -892,7 +865,6 @@ SQLFetch(
return SQL_ERROR;
}
if (stmt->status != STMT_FINISHED)
{
stmt->errornumber = STMT_STATUS_ERROR;
@ -917,8 +889,8 @@ SQLFetch(
return SC_fetch(stmt);
}
/* This fetchs a block of data (rowset). */
/* This fetchs a block of data (rowset). */
RETCODE SQL_API
SQLExtendedFetch(
HSTMT hstmt,
@ -1020,7 +992,6 @@ SQLExtendedFetch(
switch (fFetchType)
{
case SQL_FETCH_NEXT:
/*
* From the odbc spec... If positioned before the start of the
* RESULT SET, then this should be equivalent to
@ -1031,36 +1002,25 @@ SQLExtendedFetch(
stmt->rowset_start = 0;
else
{
stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size);
}
mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
break;
case SQL_FETCH_PRIOR:
mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
/*
* From the odbc spec... If positioned after the end of the
* RESULT SET, then this should be equivalent to
* SQL_FETCH_LAST.
*/
if (stmt->rowset_start >= num_tuples)
{
stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
}
else
{
stmt->rowset_start -= stmt->options.rowset_size;
}
break;
case SQL_FETCH_FIRST:
@ -1091,11 +1051,9 @@ SQLExtendedFetch(
/* Position with respect to the end of the result set */
else
stmt->rowset_start = num_tuples + irow;
break;
case SQL_FETCH_RELATIVE:
/*
* Refresh the current rowset -- not currently implemented,
* but lie anyway
@ -1104,25 +1062,20 @@ SQLExtendedFetch(
break;
stmt->rowset_start += irow;
break;
case SQL_FETCH_BOOKMARK:
stmt->rowset_start = irow - 1;
break;
default:
SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
return SQL_ERROR;
}
/***********************************/
/* CHECK FOR PROPER CURSOR STATE */
/***********************************/
/*
* CHECK FOR PROPER CURSOR STATE
*/
/*
* Handle Declare Fetch style specially because the end is not really
@ -1172,7 +1125,6 @@ SQLExtendedFetch(
truncated = error = FALSE;
for (i = 0; i < stmt->options.rowset_size; i++)
{
stmt->bind_row = i; /* set the binding location */
result = SC_fetch(stmt);
@ -1212,21 +1164,21 @@ SQLExtendedFetch(
*pcrow = i;
if (i == 0)
return SQL_NO_DATA_FOUND; /* Only DeclareFetch should wind
* up here */
/* Only DeclareFetch should wind up here */
return SQL_NO_DATA_FOUND;
else if (error)
return SQL_ERROR;
else if (truncated)
return SQL_SUCCESS_WITH_INFO;
else
return SQL_SUCCESS;
}
/* This determines whether there are more results sets available for */
/* the "hstmt". */
/*
* This determines whether there are more results sets available for
* the "hstmt".
*/
/* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */
RETCODE SQL_API
SQLMoreResults(
@ -1235,8 +1187,11 @@ SQLMoreResults(
return SQL_NO_DATA_FOUND;
}
/* This positions the cursor within a rowset, that was positioned using SQLExtendedFetch. */
/* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch. */
/*
* This positions the cursor within a rowset, that was positioned using SQLExtendedFetch.
* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch.
*/
RETCODE SQL_API
SQLSetPos(
HSTMT hstmt,
@ -1301,11 +1256,10 @@ SQLSetPos(
stmt->currTuple = stmt->rowset_start + irow;
return SQL_SUCCESS;
}
/* Sets options that control the behavior of cursors. */
/* Sets options that control the behavior of cursors. */
RETCODE SQL_API
SQLSetScrollOptions(
HSTMT hstmt,
@ -1320,8 +1274,7 @@ SQLSetScrollOptions(
}
/* Set the cursor name on a statement handle */
/* Set the cursor name on a statement handle */
RETCODE SQL_API
SQLSetCursorName(
HSTMT hstmt,
@ -1354,8 +1307,8 @@ SQLSetCursorName(
return SQL_SUCCESS;
}
/* Return the cursor name for a statement handle */
/* Return the cursor name for a statement handle */
RETCODE SQL_API
SQLGetCursorName(
HSTMT hstmt,

View File

@ -1,4 +1,5 @@
/* Module: setup.c
/*-------
* Module: setup.c
*
* Description: This module contains the setup functions for
* adding/modifying a Data Source in the ODBC.INI portion
@ -9,7 +10,7 @@
* API functions: ConfigDSN
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#include "psqlodbc.h"
@ -28,7 +29,7 @@
extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
extern GLOBAL_VALUES globals;
/* Constants --------------------------------------------------------------- */
/* Constants */
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#ifdef WIN32
@ -40,7 +41,7 @@ extern GLOBAL_VALUES globals;
#define MAXDSNAME (32+1) /* Max data source name length */
/* Globals ----------------------------------------------------------------- */
/* Globals */
/* NOTE: All these are used by the dialog procedures */
typedef struct tagSETUPDLG
{
@ -55,24 +56,26 @@ typedef struct tagSETUPDLG
/* Prototypes -------------------------------------------------------------- */
/* Prototypes */
void INTFUNC CenterDialog(HWND hdlg);
int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
/* ConfigDSN ---------------------------------------------------------------
Description: ODBC Setup entry point
This entry point is called by the ODBC Installer
(see file header for more details)
Input : hwnd ----------- Parent window handle
fRequest ------- Request type (i.e., add, config, or remove)
lpszDriver ----- Driver name
lpszAttributes - data source attribute string
Output : TRUE success, FALSE otherwise
--------------------------------------------------------------------------*/
/*--------
* ConfigDSN
*
* Description: ODBC Setup entry point
* This entry point is called by the ODBC Installer
* (see file header for more details)
* Input : hwnd ----------- Parent window handle
* fRequest ------- Request type (i.e., add, config, or remove)
* lpszDriver ----- Driver name
* lpszAttributes - data source attribute string
* Output : TRUE success, FALSE otherwise
*--------
*/
BOOL CALLBACK
ConfigDSN(HWND hwnd,
WORD fRequest,
@ -111,7 +114,6 @@ ConfigDSN(HWND hwnd,
else
fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn);
}
/* Add or Configure data source */
else
{
@ -134,7 +136,6 @@ ConfigDSN(HWND hwnd,
ConfigDlgProc,
(LONG) (LPSTR) lpsetupdlg));
}
else if (lpsetupdlg->ci.dsn[0])
fSuccess = SetDSNAttributes(hwnd, lpsetupdlg);
else
@ -148,11 +149,14 @@ ConfigDSN(HWND hwnd,
}
/* CenterDialog ------------------------------------------------------------
Description: Center the dialog over the frame window
Input : hdlg -- Dialog window handle
Output : None
--------------------------------------------------------------------------*/
/*-------
* CenterDialog
*
* Description: Center the dialog over the frame window
* Input : hdlg -- Dialog window handle
* Output : None
*-------
*/
void INTFUNC
CenterDialog(HWND hdlg)
{
@ -198,23 +202,22 @@ CenterDialog(HWND hdlg)
return;
}
/* ConfigDlgProc -----------------------------------------------------------
Description: Manage add data source name dialog
Input : hdlg --- Dialog window handle
wMsg --- Message
wParam - Message parameter
lParam - Message parameter
Output : TRUE if message processed, FALSE otherwise
--------------------------------------------------------------------------*/
/*-------
* ConfigDlgProc
* Description: Manage add data source name dialog
* Input : hdlg --- Dialog window handle
* wMsg --- Message
* wParam - Message parameter
* lParam - Message parameter
* Output : TRUE if message processed, FALSE otherwise
*-------
*/
int CALLBACK
ConfigDlgProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (wMsg)
{
/* Initialize the dialog */
@ -241,11 +244,9 @@ ConfigDlgProc(HWND hdlg,
/* Fill in any defaults */
getDSNdefaults(ci);
/* Initialize dialog fields */
SetDlgStuff(hdlg, ci);
if (lpsetupdlg->fDefault)
{
EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
@ -260,13 +261,10 @@ ConfigDlgProc(HWND hdlg,
return TRUE; /* Focus was not set */
}
/* Process buttons */
/* Process buttons */
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
/*
* Ensure the OK button is enabled only when a data
* source name
@ -281,12 +279,11 @@ ConfigDlgProc(HWND hdlg,
EnableWindow(GetDlgItem(hdlg, IDOK),
GetDlgItemText(hdlg, IDC_DSNAME,
szItem, sizeof(szItem)));
return TRUE;
}
break;
/* Accept results */
/* Accept results */
case IDOK:
{
LPSETUPDLG lpsetupdlg;
@ -297,8 +294,6 @@ ConfigDlgProc(HWND hdlg,
GetDlgItemText(hdlg, IDC_DSNAME,
lpsetupdlg->ci.dsn,
sizeof(lpsetupdlg->ci.dsn));
/* Get Dialog Values */
GetDlgStuff(hdlg, &lpsetupdlg->ci);
@ -306,13 +301,12 @@ ConfigDlgProc(HWND hdlg,
SetDSNAttributes(hdlg, lpsetupdlg);
}
/* Return to caller */
/* Return to caller */
case IDCANCEL:
EndDialog(hdlg, wParam);
return TRUE;
case IDC_DRIVER:
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
hdlg, driver_optionsProc, (LPARAM) NULL);
@ -330,7 +324,6 @@ ConfigDlgProc(HWND hdlg,
return TRUE;
}
}
break;
}
@ -339,11 +332,14 @@ ConfigDlgProc(HWND hdlg,
}
/* ParseAttributes ---------------------------------------------------------
Description: Parse attribute string moving values into the aAttr array
Input : lpszAttributes - Pointer to attribute string
Output : None (global aAttr normally updated)
--------------------------------------------------------------------------*/
/*-------
* ParseAttributes
*
* Description: Parse attribute string moving values into the aAttr array
* Input : lpszAttributes - Pointer to attribute string
* Output : None (global aAttr normally updated)
*-------
*/
void INTFUNC
ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
{
@ -356,8 +352,8 @@ 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++)
{
@ -370,15 +366,14 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
cbKey = lpsz - lpszStart;
if (cbKey < sizeof(aszKey))
{
_fmemcpy(aszKey, lpszStart, cbKey);
aszKey[cbKey] = '\0';
}
/* Locate end of key value */
lpszStart = ++lpsz;
for (; *lpsz; lpsz++);
for (; *lpsz; lpsz++)
;
/* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
_fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH));
@ -392,12 +387,14 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
}
/* SetDSNAttributes --------------------------------------------------------
Description: Write data source attributes to ODBC.INI
Input : hwnd - Parent window handle (plus globals)
Output : TRUE if successful, FALSE otherwise
--------------------------------------------------------------------------*/
/*--------
* SetDSNAttributes
*
* Description: Write data source attributes to ODBC.INI
* Input : hwnd - Parent window handle (plus globals)
* Output : TRUE if successful, FALSE otherwise
*--------
*/
BOOL INTFUNC
SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
{
@ -425,11 +422,9 @@ SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
return FALSE;
}
/* Update ODBC.INI */
writeDSNinfo(&lpsetupdlg->ci);
/* If the data source name has changed, remove the old name */
if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
SQLRemoveDSNFromIni(lpsetupdlg->szDSN);

View File

@ -1,4 +1,5 @@
/* Module: socket.c
/*-------
* Module: socket.c
*
* Description: This module contains functions for low level socket
* operations (connecting/reading/writing to the backend)
@ -8,7 +9,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#ifdef HAVE_CONFIG_H
@ -42,6 +43,7 @@ SOCK_clear_error(SocketClass *self)
self->errormsg = NULL;
}
SocketClass *
SOCK_Constructor()
{
@ -70,16 +72,14 @@ SOCK_Constructor()
free(rv);
return NULL;
}
rv->errormsg = NULL;
rv->errornumber = 0;
rv->reverse = FALSE;
}
return rv;
}
void
SOCK_Destructor(SocketClass *self)
{
@ -97,7 +97,6 @@ SOCK_Destructor(SocketClass *self)
free(self->buffer_out);
free(self);
}
@ -149,7 +148,6 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
if (connect(self->socket, (struct sockaddr *) & (sadr),
sizeof(sadr)) < 0)
{
self->errornumber = SOCKET_COULD_NOT_CONNECT;
self->errormsg = "Could not connect to remote socket.";
closesocket(self->socket);
@ -194,9 +192,10 @@ SOCK_put_n_char(SocketClass *self, char *buffer, int len)
}
/* bufsize must include room for the null terminator
will read at most bufsize-1 characters + null.
*/
/*
* bufsize must include room for the null terminator
* will read at most bufsize-1 characters + null.
*/
void
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
{
@ -297,15 +296,16 @@ SOCK_flush_output(SocketClass *self)
self->buffer_filled_out = 0;
}
unsigned char
SOCK_get_next_byte(SocketClass *self)
{
if (self->buffer_read_in >= self->buffer_filled_in)
{
/* there are no more bytes left in the buffer so */
/* reload the buffer */
/*
* 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);
@ -329,6 +329,7 @@ SOCK_get_next_byte(SocketClass *self)
return self->buffer_in[self->buffer_read_in++];
}
void
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
{

View File

@ -1,4 +1,5 @@
/* Module: statement.c
/*-------
* Module: statement.c
*
* Description: This module contains functions related to creating
* and manipulating a statement.
@ -8,7 +9,7 @@
* API functions: SQLAllocStmt, SQLFreeStmt
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#ifdef HAVE_CONFIG_H
@ -44,6 +45,7 @@ extern GLOBAL_VALUES globals;
#endif
#define PRN_NULLCHECK
/* Map sql commands to statement types */
static struct
{
@ -126,12 +128,9 @@ 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;
/* Save the handle for later */
stmt->phstmt = phstmt;
@ -180,29 +179,27 @@ SQLFreeStmt(HSTMT hstmt,
/* Destroy the statement and free any results, cursors, etc. */
SC_Destructor(stmt);
}
else if (fOption == SQL_UNBIND)
{
SC_unbind_cols(stmt);
}
else if (fOption == SQL_CLOSE)
{
/* this should discard all the results, but leave the statement */
/* itself in place (it can be executed again) */
/*
* this should discard all the results, but leave the statement
* itself in place (it can be executed again)
*/
if (!SC_recycle_statement(stmt))
{
/* errormsg passed in above */
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
else if (fOption == SQL_RESET_PARAMS)
{
SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
}
else
{
@ -216,8 +213,7 @@ SQLFreeStmt(HSTMT hstmt,
}
/**********************************************************************
/*
* StatementClass implementation
*/
void
@ -234,6 +230,7 @@ InitializeStatementOptions(StatementOptions *opt)
opt->use_bookmarks = SQL_UB_OFF;
}
StatementClass *
SC_Constructor(void)
{
@ -288,7 +285,6 @@ SC_Constructor(void)
rv->nfld = 0;
rv->parse_status = STMT_PARSE_NONE;
/* Clear Statement Options -- defaults will be set in AllocStmt */
memset(&rv->options, 0, sizeof(StatementOptions));
@ -298,10 +294,10 @@ SC_Constructor(void)
return rv;
}
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)
{
@ -325,18 +321,13 @@ SC_Destructor(StatementClass *self)
/*
* 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
* driver but 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)
{
@ -358,7 +349,6 @@ SC_Destructor(StatementClass *self)
free(self->fi);
}
free(self);
mylog("SC_Destructor: EXIT\n");
@ -366,9 +356,11 @@ SC_Destructor(StatementClass *self)
return TRUE;
}
/* Free parameters and free the memory from the
data-at-execution parameters that was allocated in SQLPutData.
*/
/*
* Free parameters and free the memory from the
* data-at-execution parameters that was allocated in SQLPutData.
*/
void
SC_free_params(StatementClass *self, char option)
{
@ -383,7 +375,6 @@ SC_free_params(StatementClass *self, char option)
{
if (self->parameters[i].data_at_exec == TRUE)
{
if (self->parameters[i].EXEC_used)
{
free(self->parameters[i].EXEC_used);
@ -430,9 +421,10 @@ statement_type(char *statement)
}
/* Called from SQLPrepare if STMT_PREMATURE, or
from SQLExecute if STMT_FINISHED, or
from SQLFreeStmt(SQL_CLOSE)
/*
* Called from SQLPrepare if STMT_PREMATURE, or
* from SQLExecute if STMT_FINISHED, or
* from SQLFreeStmt(SQL_CLOSE)
*/
char
SC_recycle_statement(StatementClass *self)
@ -472,7 +464,6 @@ SC_recycle_statement(StatementClass *self)
conn = SC_get_conn(self);
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
{
QResultClass *res = CC_send_query(conn, "ABORT", NULL);
QR_Destructor(res);
@ -523,10 +514,9 @@ SC_recycle_statement(StatementClass *self)
}
self->inaccurate_result = FALSE;
/****************************************************************/
/* Reset only parameters that have anything to do with results */
/****************************************************************/
/*
* Reset only parameters that have anything to do with results
*/
self->status = STMT_READY;
self->manual_result = FALSE;/* very important */
@ -542,14 +532,17 @@ SC_recycle_statement(StatementClass *self)
self->lobj_fd = -1;
/* Free any data at exec params before the statement is executed */
/* again. If not, then there will be a memory leak when */
/* the next SQLParamData/SQLPutData is called. */
/*
* Free any data at exec params before the statement is executed
* again. If not, then there will be a memory leak when
* the next SQLParamData/SQLPutData is called.
*/
SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
return TRUE;
}
/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */
void
SC_pre_execute(StatementClass *self)
@ -586,6 +579,7 @@ SC_pre_execute(StatementClass *self)
}
}
/* This is only called from SQLFreeStmt(SQL_UNBIND) */
char
SC_unbind_cols(StatementClass *self)
@ -607,6 +601,7 @@ SC_unbind_cols(StatementClass *self)
return 1;
}
void
SC_clear_error(StatementClass *self)
{
@ -616,8 +611,10 @@ SC_clear_error(StatementClass *self)
}
/* This function creates an error msg which is the concatenation */
/* of the result, statement, connection, and socket messages. */
/*
* This function creates an error msg which is the concatenation
* of the result, statement, connection, and socket messages.
*/
char *
SC_create_errormsg(StatementClass *self)
{
@ -654,12 +651,13 @@ SC_create_errormsg(StatementClass *self)
return msg;
}
char
SC_get_error(StatementClass *self, int *number, char **message)
{
char rv;
/* Create a very informative errormsg if it hasn't been done yet. */
/* Create a very informative errormsg if it hasn't been done yet. */
if (!self->errormsg_created)
{
self->errormsg = SC_create_errormsg(self);
@ -679,16 +677,19 @@ SC_get_error(StatementClass *self, int *number, char **message)
return rv;
}
/* Currently, the driver offers very simple bookmark support -- it is
just the current row number. But it could be more sophisticated
someday, such as mapping a key to a 32 bit value
*/
/*
* Currently, the driver offers very simple bookmark support -- it is
* just the current row number. But it could be more sophisticated
* someday, such as mapping a key to a 32 bit value
*/
unsigned long
SC_get_bookmark(StatementClass *self)
{
return (self->currTuple + 1);
}
RETCODE
SC_fetch(StatementClass *self)
{
@ -702,7 +703,7 @@ SC_fetch(StatementClass *self)
char *value;
ColumnInfoClass *ci;
/* TupleField *tupleField; */
/* TupleField *tupleField; */
self->last_fetch_count = 0;
ci = QR_get_fields(res); /* the column info */
@ -711,11 +712,9 @@ SC_fetch(StatementClass *self)
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 at the end of the tuples, return "no data found" and set
* the cursor past the end of the result set
@ -729,7 +728,6 @@ SC_fetch(StatementClass *self)
}
else
{
/* read from the cache or the physical next tuple */
retval = QR_next_tuple(res);
if (retval < 0)
@ -739,7 +737,6 @@ SC_fetch(StatementClass *self)
}
else if (retval > 0)
(self->currTuple)++;/* all is well */
else
{
mylog("SQLFetch: error\n");
@ -772,7 +769,6 @@ SC_fetch(StatementClass *self)
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 */
@ -828,13 +824,13 @@ SC_fetch(StatementClass *self)
result = SQL_SUCCESS_WITH_INFO;
break;
case COPY_GENERAL_ERROR: /* error msg already
* filled in */
/* error msg already filled in */
case COPY_GENERAL_ERROR:
SC_log_error(func, "", self);
result = SQL_ERROR;
break;
/* This would not be meaningful in SQLFetch. */
/* This would not be meaningful in SQLFetch. */
case COPY_NO_DATA_FOUND:
break;
@ -908,13 +904,10 @@ 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. */
/*
@ -924,19 +917,16 @@ SC_execute(StatementClass *self)
/* in copy_statement... */
if (self->statement_type == STMT_TYPE_SELECT)
{
char fetch[128];
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
/* send the declare/select */
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
if (globals.use_declarefetch && self->result != NULL &&
QR_command_successful(self->result))
{
QR_Destructor(self->result);
/*
@ -954,20 +944,15 @@ SC_execute(StatementClass *self)
* 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 */
{
/* 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);
@ -986,7 +971,6 @@ SC_execute(StatementClass *self)
QR_Destructor(res);
CC_set_no_trans(conn);
}
}
conn->status = oldstatus;
@ -995,7 +979,6 @@ SC_execute(StatementClass *self)
/* Check the status of the result */
if (self->result)
{
was_ok = QR_command_successful(self->result);
was_nonfatal = QR_command_nonfatal(self->result);
@ -1004,8 +987,8 @@ 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 */
/* set cursor before the first tuple in the list */
self->currTuple = -1;
self->current_col = -1;
self->rowset_start = -1;
@ -1029,9 +1012,8 @@ SC_execute(StatementClass *self)
CC_abort(conn);
}
else
{ /* Bad Error -- The error message will be
* in the Connection */
{
/* Bad Error -- The error message will be in the Connection */
if (self->statement_type == STMT_TYPE_CREATE)
{
self->errornumber = STMT_CREATE_TABLE_ERROR;
@ -1069,6 +1051,7 @@ SC_execute(StatementClass *self)
}
}
void
SC_log_error(char *func, char *desc, StatementClass *self)
{

View File

@ -1,23 +1,27 @@
/* Module: tuple.c
/*-------
* Module: tuple.c
*
* Description: This module contains functions for setting the data for individual
* fields (TupleField structure) of a manual result set.
* Description: This module contains functions for setting the data
* for individual fields (TupleField structure) of a
* manual result set.
*
* Important Note: These functions are ONLY used in building manual result sets for
* info functions (SQLTables, SQLColumns, etc.)
* Important Note: These functions are ONLY used in building manual
* result sets for info functions (SQLTables,
* SQLColumns, etc.)
*
* Classes: n/a
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*-------
*/
#include "tuple.h"
#include <string.h>
#include <stdlib.h>
void
set_tuplefield_null(TupleField *tuple_field)
{
@ -25,6 +29,7 @@ set_tuplefield_null(TupleField *tuple_field)
tuple_field->value = NULL; /* strdup(""); */
}
void
set_tuplefield_string(TupleField *tuple_field, char *string)
{
@ -39,7 +44,6 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
{
char buffer[10];
sprintf(buffer, "%d", value);
tuple_field->len = strlen(buffer) + 1;
@ -47,6 +51,7 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
tuple_field->value = strdup(buffer);
}
void
set_tuplefield_int4(TupleField *tuple_field, Int4 value)
{

View File

@ -1,20 +1,23 @@
/* Module: tuplelist.c
/*--------
* Module: tuplelist.c
*
* Description: This module contains functions for creating a manual result set
* (the TupleList) and retrieving data from it for a specific row/column.
* Description: This module contains functions for creating a manual
* result set (the TupleList) and retrieving data from
* it for a specific row/column.
*
* Classes: TupleListClass (Functions prefix: "TL_")
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*--------
*/
#include <stdlib.h>
#include "tuplelist.h"
#include "tuple.h"
TupleListClass *
TL_Constructor(UInt4 fieldcnt)
{
@ -25,7 +28,6 @@ TL_Constructor(UInt4 fieldcnt)
rv = (TupleListClass *) malloc(sizeof(TupleListClass));
if (rv)
{
rv->num_fields = fieldcnt;
rv->num_tuples = 0;
rv->list_start = NULL;
@ -39,6 +41,7 @@ TL_Constructor(UInt4 fieldcnt)
return rv;
}
void
TL_Destructor(TupleListClass *self)
{
@ -134,7 +137,6 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
}
else if (start_is_closer)
{
/*
* the shortest way is to start the search from the head of the
* list
@ -177,11 +179,9 @@ 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
@ -200,7 +200,6 @@ TL_add_tuple(TupleListClass *self, TupleNode *new_field)
}
else
{
/*
* there is already an element in the list, so add the new one at
* the end of the list