Commit 755a8733 authored by Bruce Momjian's avatar Bruce Momjian

Run pgindent over ODBC source. We couldn't do this years ago because we

weren't the master source.  We are now, and it really needs it.
parent 505a828a
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
/* Bind parameters on a statement handle */ /* Bind parameters on a statement handle */
RETCODE SQL_API SQLBindParameter( RETCODE SQL_API
SQLBindParameter(
HSTMT hstmt, HSTMT hstmt,
UWORD ipar, UWORD ipar,
SWORD fParamType, SWORD fParamType,
...@@ -45,27 +46,31 @@ RETCODE SQL_API SQLBindParameter( ...@@ -45,27 +46,31 @@ RETCODE SQL_API SQLBindParameter(
SWORD ibScale, SWORD ibScale,
PTR rgbValue, PTR rgbValue,
SDWORD cbValueMax, SDWORD cbValueMax,
SDWORD FAR *pcbValue) SDWORD FAR * pcbValue)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
static char *func="SQLBindParameter"; static char *func = "SQLBindParameter";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if(stmt->parameters_allocated < ipar) { if (stmt->parameters_allocated < ipar)
{
ParameterInfoClass *old_parameters; ParameterInfoClass *old_parameters;
int i, old_parameters_allocated; int i,
old_parameters_allocated;
old_parameters = stmt->parameters; old_parameters = stmt->parameters;
old_parameters_allocated = stmt->parameters_allocated; old_parameters_allocated = stmt->parameters_allocated;
stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass)*(ipar)); stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass) * (ipar));
if ( ! stmt->parameters) { if (!stmt->parameters)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Could not allocate memory for statement parameters"; stmt->errormsg = "Could not allocate memory for statement parameters";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -75,18 +80,23 @@ static char *func="SQLBindParameter"; ...@@ -75,18 +80,23 @@ static char *func="SQLBindParameter";
stmt->parameters_allocated = ipar; stmt->parameters_allocated = ipar;
/* copy the old parameters over */ /* copy the old parameters over */
for(i = 0; i < old_parameters_allocated; i++) { for (i = 0; i < old_parameters_allocated; i++)
{
/* a structure copy should work */ /* a structure copy should work */
stmt->parameters[i] = old_parameters[i]; stmt->parameters[i] = old_parameters[i];
} }
/* get rid of the old parameters, if there were any */ /* get rid of the old parameters, if there were any */
if(old_parameters) if (old_parameters)
free(old_parameters); free(old_parameters);
/* zero out the newly allocated parameters (in case they skipped some, */ /*
* zero out the newly allocated parameters (in case they skipped
* some,
*/
/* so we don't accidentally try to use them later) */ /* so we don't accidentally try to use them later) */
for(; i < stmt->parameters_allocated; i++) { for (; i < stmt->parameters_allocated; i++)
{
stmt->parameters[i].buflen = 0; stmt->parameters[i].buflen = 0;
stmt->parameters[i].buffer = 0; stmt->parameters[i].buffer = 0;
stmt->parameters[i].used = 0; stmt->parameters[i].used = 0;
...@@ -102,7 +112,8 @@ static char *func="SQLBindParameter"; ...@@ -102,7 +112,8 @@ static char *func="SQLBindParameter";
} }
} }
ipar--; /* use zero based column numbers for the below part */ ipar--; /* use zero based column numbers for the
* below part */
/* store the given info */ /* store the given info */
stmt->parameters[ipar].buflen = cbValueMax; stmt->parameters[ipar].buflen = cbValueMax;
...@@ -114,15 +125,18 @@ static char *func="SQLBindParameter"; ...@@ -114,15 +125,18 @@ static char *func="SQLBindParameter";
stmt->parameters[ipar].precision = cbColDef; stmt->parameters[ipar].precision = cbColDef;
stmt->parameters[ipar].scale = ibScale; stmt->parameters[ipar].scale = ibScale;
/* If rebinding a parameter that had data-at-exec stuff in it, /*
then free that stuff * If rebinding a parameter that had data-at-exec stuff in it, then
* free that stuff
*/ */
if (stmt->parameters[ipar].EXEC_used) { if (stmt->parameters[ipar].EXEC_used)
{
free(stmt->parameters[ipar].EXEC_used); free(stmt->parameters[ipar].EXEC_used);
stmt->parameters[ipar].EXEC_used = NULL; stmt->parameters[ipar].EXEC_used = NULL;
} }
if (stmt->parameters[ipar].EXEC_buffer) { if (stmt->parameters[ipar].EXEC_buffer)
{
if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY) if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY)
free(stmt->parameters[ipar].EXEC_buffer); free(stmt->parameters[ipar].EXEC_buffer);
stmt->parameters[ipar].EXEC_buffer = NULL; stmt->parameters[ipar].EXEC_buffer = NULL;
...@@ -134,7 +148,7 @@ static char *func="SQLBindParameter"; ...@@ -134,7 +148,7 @@ static char *func="SQLBindParameter";
else else
stmt->parameters[ipar].data_at_exec = FALSE; stmt->parameters[ipar].data_at_exec = FALSE;
mylog("SQLBindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue: -777, stmt->parameters[ipar].data_at_exec); mylog("SQLBindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, stmt->parameters[ipar].data_at_exec);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -142,22 +156,24 @@ static char *func="SQLBindParameter"; ...@@ -142,22 +156,24 @@ static char *func="SQLBindParameter";
/* - - - - - - - - - */ /* - - - - - - - - - */
/* Associate a user-supplied buffer with a database column. */ /* Associate a user-supplied buffer with a database column. */
RETCODE SQL_API SQLBindCol( RETCODE SQL_API
SQLBindCol(
HSTMT hstmt, HSTMT hstmt,
UWORD icol, UWORD icol,
SWORD fCType, SWORD fCType,
PTR rgbValue, PTR rgbValue,
SDWORD cbValueMax, SDWORD cbValueMax,
SDWORD FAR *pcbValue) SDWORD FAR * pcbValue)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
static char *func="SQLBindCol"; static char *func = "SQLBindCol";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -165,7 +181,8 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); ...@@ -165,7 +181,8 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
SC_clear_error(stmt); SC_clear_error(stmt);
if( stmt->status == STMT_EXECUTING) { if (stmt->status == STMT_EXECUTING)
{
stmt->errormsg = "Can't bind columns while statement is still executing."; stmt->errormsg = "Can't bind columns while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -173,15 +190,19 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); ...@@ -173,15 +190,19 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
} }
/* If the bookmark column is being bound, then just save it */ /* If the bookmark column is being bound, then just save it */
if (icol == 0) { if (icol == 0)
{
if (rgbValue == NULL) { if (rgbValue == NULL)
{
stmt->bookmark.buffer = NULL; stmt->bookmark.buffer = NULL;
stmt->bookmark.used = NULL; stmt->bookmark.used = NULL;
} }
else { else
{
/* Make sure it is the bookmark data type */ /* Make sure it is the bookmark data type */
if ( fCType != SQL_C_BOOKMARK) { if (fCType != SQL_C_BOOKMARK)
{
stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK"; stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE; stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -198,29 +219,34 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); ...@@ -198,29 +219,34 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
/* Most likely, execution of a statement would have setup the */ /* Most likely, execution of a statement would have setup the */
/* necessary bindings. But some apps call BindCol before any */ /* necessary bindings. But some apps call BindCol before any */
/* statement is executed. */ /* statement is executed. */
if ( icol > stmt->bindings_allocated) if (icol > stmt->bindings_allocated)
extend_bindings(stmt, icol); extend_bindings(stmt, icol);
/* check to see if the bindings were allocated */ /* check to see if the bindings were allocated */
if ( ! stmt->bindings) { if (!stmt->bindings)
{
stmt->errormsg = "Could not allocate memory for bindings."; stmt->errormsg = "Could not allocate memory for bindings.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
icol--; /* use zero based col numbers from here out */ icol--; /* use zero based col numbers from here
* out */
/* Reset for SQLGetData */ /* Reset for SQLGetData */
stmt->bindings[icol].data_left = -1; stmt->bindings[icol].data_left = -1;
if (rgbValue == NULL) { if (rgbValue == NULL)
{
/* we have to unbind the column */ /* we have to unbind the column */
stmt->bindings[icol].buflen = 0; stmt->bindings[icol].buflen = 0;
stmt->bindings[icol].buffer = NULL; stmt->bindings[icol].buffer = NULL;
stmt->bindings[icol].used = NULL; stmt->bindings[icol].used = NULL;
stmt->bindings[icol].returntype = SQL_C_CHAR; stmt->bindings[icol].returntype = SQL_C_CHAR;
} else { }
else
{
/* ok, bind that column */ /* ok, bind that column */
stmt->bindings[icol].buflen = cbValueMax; stmt->bindings[icol].buflen = cbValueMax;
stmt->bindings[icol].buffer = rgbValue; stmt->bindings[icol].buffer = rgbValue;
...@@ -242,25 +268,28 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); ...@@ -242,25 +268,28 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
/* it is best to say this function is not supported and let the application assume a */ /* it is best to say this function is not supported and let the application assume a */
/* data type (most likely varchar). */ /* data type (most likely varchar). */
RETCODE SQL_API SQLDescribeParam( RETCODE SQL_API
SQLDescribeParam(
HSTMT hstmt, HSTMT hstmt,
UWORD ipar, UWORD ipar,
SWORD FAR *pfSqlType, SWORD FAR * pfSqlType,
UDWORD FAR *pcbColDef, UDWORD FAR * pcbColDef,
SWORD FAR *pibScale, SWORD FAR * pibScale,
SWORD FAR *pfNullable) SWORD FAR * pfNullable)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "SQLDescribeParam"; static char *func = "SQLDescribeParam";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) { if ((ipar < 1) || (ipar > stmt->parameters_allocated))
{
stmt->errormsg = "Invalid parameter number for SQLDescribeParam."; stmt->errormsg = "Invalid parameter number for SQLDescribeParam.";
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR; stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -269,18 +298,21 @@ static char *func = "SQLDescribeParam"; ...@@ -269,18 +298,21 @@ static char *func = "SQLDescribeParam";
ipar--; ipar--;
/* This implementation is not very good, since it is supposed to describe */ /*
* This implementation is not very good, since it is supposed to
* describe
*/
/* parameter markers, not bound parameters. */ /* parameter markers, not bound parameters. */
if(pfSqlType) if (pfSqlType)
*pfSqlType = stmt->parameters[ipar].SQLType; *pfSqlType = stmt->parameters[ipar].SQLType;
if(pcbColDef) if (pcbColDef)
*pcbColDef = stmt->parameters[ipar].precision; *pcbColDef = stmt->parameters[ipar].precision;
if(pibScale) if (pibScale)
*pibScale = stmt->parameters[ipar].scale; *pibScale = stmt->parameters[ipar].scale;
if(pfNullable) if (pfNullable)
*pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType); *pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType);
return SQL_SUCCESS; return SQL_SUCCESS;
...@@ -290,14 +322,15 @@ static char *func = "SQLDescribeParam"; ...@@ -290,14 +322,15 @@ static char *func = "SQLDescribeParam";
/* Sets multiple values (arrays) for the set of parameter markers. */ /* Sets multiple values (arrays) for the set of parameter markers. */
RETCODE SQL_API SQLParamOptions( RETCODE SQL_API
SQLParamOptions(
HSTMT hstmt, HSTMT hstmt,
UDWORD crow, UDWORD crow,
UDWORD FAR *pirow) UDWORD FAR * pirow)
{ {
static char *func = "SQLParamOptions"; static char *func = "SQLParamOptions";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR; return SQL_ERROR;
...@@ -312,43 +345,51 @@ static char *func = "SQLParamOptions"; ...@@ -312,43 +345,51 @@ static char *func = "SQLParamOptions";
/* like it does for SQLDescribeParam is that some applications don't care and try */ /* like it does for SQLDescribeParam is that some applications don't care and try */
/* to call it anyway. */ /* to call it anyway. */
/* If the statement does not have parameters, it should just return 0. */ /* If the statement does not have parameters, it should just return 0. */
RETCODE SQL_API SQLNumParams( RETCODE SQL_API
SQLNumParams(
HSTMT hstmt, HSTMT hstmt,
SWORD FAR *pcpar) SWORD FAR * pcpar)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
char in_quote = FALSE; char in_quote = FALSE;
unsigned int i; unsigned int i;
static char *func = "SQLNumParams"; static char *func = "SQLNumParams";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if(!stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if (pcpar) if (pcpar)
*pcpar = 0; *pcpar = 0;
else { else
{
SC_log_error(func, "pcpar was null", stmt); SC_log_error(func, "pcpar was null", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if(!stmt->statement) { if (!stmt->statement)
{
/* no statement has been allocated */ /* no statement has been allocated */
stmt->errormsg = "SQLNumParams called with no statement ready."; stmt->errormsg = "SQLNumParams called with no statement ready.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} else { }
else
{
for(i=0; i < strlen(stmt->statement); i++) { for (i = 0; i < strlen(stmt->statement); i++)
{
if(stmt->statement[i] == '?' && !in_quote) if (stmt->statement[i] == '?' && !in_quote)
(*pcpar)++; (*pcpar)++;
else { else
{
if (stmt->statement[i] == '\'') if (stmt->statement[i] == '\'')
in_quote = (in_quote ? FALSE : TRUE); in_quote = (in_quote ? FALSE : TRUE);
} }
...@@ -364,15 +405,15 @@ static char *func = "SQLNumParams"; ...@@ -364,15 +405,15 @@ static char *func = "SQLNumParams";
BindInfoClass * BindInfoClass *
create_empty_bindings(int num_columns) create_empty_bindings(int num_columns)
{ {
BindInfoClass *new_bindings; BindInfoClass *new_bindings;
int i; int i;
new_bindings = (BindInfoClass *)malloc(num_columns * sizeof(BindInfoClass)); new_bindings = (BindInfoClass *) malloc(num_columns * sizeof(BindInfoClass));
if(!new_bindings) { if (!new_bindings)
return 0; return 0;
}
for(i=0; i < num_columns; i++) { for (i = 0; i < num_columns; i++)
{
new_bindings[i].buflen = 0; new_bindings[i].buflen = 0;
new_bindings[i].buffer = NULL; new_bindings[i].buffer = NULL;
new_bindings[i].used = NULL; new_bindings[i].used = NULL;
...@@ -383,23 +424,26 @@ int i; ...@@ -383,23 +424,26 @@ int i;
} }
void void
extend_bindings(StatementClass *stmt, int num_columns) extend_bindings(StatementClass * stmt, int num_columns)
{ {
static char *func="extend_bindings"; static char *func = "extend_bindings";
BindInfoClass *new_bindings; BindInfoClass *new_bindings;
int i; int i;
mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, 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 */ /* if we have too few, allocate room for more, and copy the old */
/* entries into the new structure */ /* entries into the new structure */
if(stmt->bindings_allocated < num_columns) { if (stmt->bindings_allocated < num_columns)
{
new_bindings = create_empty_bindings(num_columns); new_bindings = create_empty_bindings(num_columns);
if ( ! new_bindings) { if (!new_bindings)
{
mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, stmt->bindings_allocated); mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, stmt->bindings_allocated);
if (stmt->bindings) { if (stmt->bindings)
{
free(stmt->bindings); free(stmt->bindings);
stmt->bindings = NULL; stmt->bindings = NULL;
} }
...@@ -407,8 +451,9 @@ mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, ...@@ -407,8 +451,9 @@ mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func,
return; return;
} }
if(stmt->bindings) { if (stmt->bindings)
for(i=0; i<stmt->bindings_allocated; i++) {
for (i = 0; i < stmt->bindings_allocated; i++)
new_bindings[i] = stmt->bindings[i]; new_bindings[i] = stmt->bindings[i];
free(stmt->bindings); free(stmt->bindings);
......
...@@ -15,18 +15,24 @@ ...@@ -15,18 +15,24 @@
/* /*
* BindInfoClass -- stores information about a bound column * BindInfoClass -- stores information about a bound column
*/ */
struct BindInfoClass_ { struct BindInfoClass_
{
Int4 buflen; /* size of buffer */ Int4 buflen; /* size of buffer */
Int4 data_left; /* amount of data left to read (SQLGetData) */ Int4 data_left; /* amount of data left to read
* (SQLGetData) */
char *buffer; /* pointer to the buffer */ char *buffer; /* pointer to the buffer */
Int4 *used; /* used space in the buffer (for strings not counting the '\0') */ Int4 *used; /* used space in the buffer (for strings
Int2 returntype; /* kind of conversion to be applied when returning (SQL_C_DEFAULT, SQL_C_CHAR...) */ * not counting the '\0') */
Int2 returntype; /* kind of conversion to be applied when
* returning (SQL_C_DEFAULT,
* SQL_C_CHAR...) */
}; };
/* /*
* ParameterInfoClass -- stores information about a bound parameter * ParameterInfoClass -- stores information about a bound parameter
*/ */
struct ParameterInfoClass_ { struct ParameterInfoClass_
{
Int4 buflen; Int4 buflen;
char *buffer; char *buffer;
Int4 *used; Int4 *used;
...@@ -36,12 +42,13 @@ struct ParameterInfoClass_ { ...@@ -36,12 +42,13 @@ struct ParameterInfoClass_ {
UInt4 precision; UInt4 precision;
Int2 scale; Int2 scale;
Oid lobj_oid; Oid lobj_oid;
Int4 *EXEC_used; /* amount of data OR the oid of the large object */ Int4 *EXEC_used; /* amount of data OR the oid of the large
* object */
char *EXEC_buffer; /* the data or the FD of the large object */ char *EXEC_buffer; /* the data or the FD of the large object */
char data_at_exec; char data_at_exec;
}; };
BindInfoClass *create_empty_bindings(int num_columns); BindInfoClass *create_empty_bindings(int num_columns);
void extend_bindings(StatementClass *stmt, int num_columns); void extend_bindings(StatementClass * stmt, int num_columns);
#endif #endif
...@@ -20,11 +20,12 @@ ...@@ -20,11 +20,12 @@
ColumnInfoClass * ColumnInfoClass *
CI_Constructor() CI_Constructor()
{ {
ColumnInfoClass *rv; ColumnInfoClass *rv;
rv = (ColumnInfoClass *) malloc(sizeof(ColumnInfoClass)); rv = (ColumnInfoClass *) malloc(sizeof(ColumnInfoClass));
if (rv) { if (rv)
{
rv->num_fields = 0; rv->num_fields = 0;
rv->name = NULL; rv->name = NULL;
rv->adtid = NULL; rv->adtid = NULL;
...@@ -37,7 +38,7 @@ ColumnInfoClass *rv; ...@@ -37,7 +38,7 @@ ColumnInfoClass *rv;
} }
void void
CI_Destructor(ColumnInfoClass *self) CI_Destructor(ColumnInfoClass * self)
{ {
CI_free_memory(self); CI_free_memory(self);
...@@ -49,16 +50,16 @@ CI_Destructor(ColumnInfoClass *self) ...@@ -49,16 +50,16 @@ CI_Destructor(ColumnInfoClass *self)
If self is null, then just read, don't store. If self is null, then just read, don't store.
*/ */
char char
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn) CI_read_fields(ColumnInfoClass * self, ConnectionClass * conn)
{ {
Int2 lf; Int2 lf;
int new_num_fields; int new_num_fields;
Oid new_adtid; Oid new_adtid;
Int2 new_adtsize; Int2 new_adtsize;
Int4 new_atttypmod = -1; Int4 new_atttypmod = -1;
char new_field_name[MAX_MESSAGE_LEN+1]; char new_field_name[MAX_MESSAGE_LEN + 1];
SocketClass *sock; SocketClass *sock;
ConnInfo *ci; ConnInfo *ci;
sock = CC_get_socket(conn); sock = CC_get_socket(conn);
ci = &conn->connInfo; ci = &conn->connInfo;
...@@ -68,19 +69,22 @@ ConnInfo *ci; ...@@ -68,19 +69,22 @@ ConnInfo *ci;
mylog("num_fields = %d\n", new_num_fields); mylog("num_fields = %d\n", new_num_fields);
if (self) { /* according to that allocate memory */ if (self)
{ /* according to that allocate memory */
CI_set_num_fields(self, new_num_fields); CI_set_num_fields(self, new_num_fields);
} }
/* now read in the descriptions */ /* now read in the descriptions */
for(lf = 0; lf < new_num_fields; lf++) { for (lf = 0; lf < new_num_fields; lf++)
{
SOCK_get_string(sock, new_field_name, MAX_MESSAGE_LEN); SOCK_get_string(sock, new_field_name, MAX_MESSAGE_LEN);
new_adtid = (Oid) SOCK_get_int(sock, 4); new_adtid = (Oid) SOCK_get_int(sock, 4);
new_adtsize = (Int2) SOCK_get_int(sock, 2); new_adtsize = (Int2) SOCK_get_int(sock, 2);
/* If 6.4 protocol, then read the atttypmod field */ /* If 6.4 protocol, then read the atttypmod field */
if (PG_VERSION_GE(conn, 6.4)) { if (PG_VERSION_GE(conn, 6.4))
{
mylog("READING ATTTYPMOD\n"); mylog("READING ATTTYPMOD\n");
new_atttypmod = (Int4) SOCK_get_int(sock, 4); new_atttypmod = (Int4) SOCK_get_int(sock, 4);
...@@ -104,14 +108,15 @@ ConnInfo *ci; ...@@ -104,14 +108,15 @@ ConnInfo *ci;
void void
CI_free_memory(ColumnInfoClass *self) CI_free_memory(ColumnInfoClass * self)
{ {
register Int2 lf; register Int2 lf;
int num_fields = self->num_fields; int num_fields = self->num_fields;
for (lf = 0; lf < num_fields; lf++) { for (lf = 0; lf < num_fields; lf++)
if( self->name[lf]) {
free (self->name[lf]); if (self->name[lf])
free(self->name[lf]);
} }
/* Safe to call even if null */ /* Safe to call even if null */
...@@ -124,28 +129,27 @@ int num_fields = self->num_fields; ...@@ -124,28 +129,27 @@ int num_fields = self->num_fields;
} }
void void
CI_set_num_fields(ColumnInfoClass *self, int new_num_fields) CI_set_num_fields(ColumnInfoClass * self, int new_num_fields)
{ {
CI_free_memory(self); /* always safe to call */ CI_free_memory(self); /* always safe to call */
self->num_fields = new_num_fields; self->num_fields = new_num_fields;
self->name = (char **) malloc (sizeof(char *) * self->num_fields); self->name = (char **) malloc(sizeof(char *) * self->num_fields);
self->adtid = (Oid *) malloc (sizeof(Oid) * self->num_fields); self->adtid = (Oid *) malloc(sizeof(Oid) * self->num_fields);
self->adtsize = (Int2 *) malloc (sizeof(Int2) * self->num_fields); self->adtsize = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
self->display_size = (Int2 *) malloc(sizeof(Int2) * self->num_fields); self->display_size = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields); self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields);
} }
void void
CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, CI_set_field_info(ColumnInfoClass * self, int field_num, char *new_name,
Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod) Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod)
{ {
/* check bounds */ /* check bounds */
if((field_num < 0) || (field_num >= self->num_fields)) { if ((field_num < 0) || (field_num >= self->num_fields))
return; return;
}
/* store the info */ /* store the info */
self->name[field_num] = strdup(new_name); self->name[field_num] = strdup(new_name);
...@@ -155,4 +159,3 @@ CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, ...@@ -155,4 +159,3 @@ CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
self->display_size[field_num] = 0; self->display_size[field_num] = 0;
} }
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
#include "psqlodbc.h" #include "psqlodbc.h"
struct ColumnInfoClass_ { struct ColumnInfoClass_
{
Int2 num_fields; Int2 num_fields;
char **name; /* list of type names */ char **name; /* list of type names */
Oid *adtid; /* list of type ids */ Oid *adtid; /* list of type ids */
...@@ -29,14 +30,14 @@ struct ColumnInfoClass_ { ...@@ -29,14 +30,14 @@ struct ColumnInfoClass_ {
#define CI_get_atttypmod(self, col) (self->atttypmod[col]) #define CI_get_atttypmod(self, col) (self->atttypmod[col])
ColumnInfoClass *CI_Constructor(void); ColumnInfoClass *CI_Constructor(void);
void CI_Destructor(ColumnInfoClass *self); void CI_Destructor(ColumnInfoClass * self);
void CI_free_memory(ColumnInfoClass *self); void CI_free_memory(ColumnInfoClass * self);
char CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn); char CI_read_fields(ColumnInfoClass * self, ConnectionClass * conn);
/* functions for setting up the fields from within the program, */ /* functions for setting up the fields from within the program, */
/* without reading from a socket */ /* without reading from a socket */
void CI_set_num_fields(ColumnInfoClass *self, int new_num_fields); void CI_set_num_fields(ColumnInfoClass * self, int new_num_fields);
void CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, void CI_set_field_info(ColumnInfoClass * self, int field_num, char *new_name,
Oid new_adtid, Int2 new_adtsize, Int4 atttypmod); Oid new_adtid, Int2 new_adtsize, Int4 atttypmod);
......
...@@ -26,27 +26,30 @@ ...@@ -26,27 +26,30 @@
#include <odbcinst.h> #include <odbcinst.h>
#endif #endif
#define STMT_INCREMENT 16 /* how many statement holders to allocate at a time */ #define STMT_INCREMENT 16 /* how many statement holders to allocate
* at a time */
#define PRN_NULLCHECK #define PRN_NULLCHECK
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
RETCODE SQL_API SQLAllocConnect( RETCODE SQL_API
SQLAllocConnect(
HENV henv, HENV henv,
HDBC FAR *phdbc) HDBC FAR * phdbc)
{ {
EnvironmentClass *env = (EnvironmentClass *)henv; EnvironmentClass *env = (EnvironmentClass *) henv;
ConnectionClass *conn; ConnectionClass *conn;
static char *func="SQLAllocConnect"; static char *func = "SQLAllocConnect";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
conn = CC_Constructor(); conn = CC_Constructor();
mylog("**** %s: henv = %u, conn = %u\n", func, henv, conn); mylog("**** %s: henv = %u, conn = %u\n", func, henv, conn);
if( ! conn) { if (!conn)
{
env->errormsg = "Couldn't allocate memory for Connection object."; env->errormsg = "Couldn't allocate memory for Connection object.";
env->errornumber = ENV_ALLOC_ERROR; env->errornumber = ENV_ALLOC_ERROR;
*phdbc = SQL_NULL_HDBC; *phdbc = SQL_NULL_HDBC;
...@@ -54,7 +57,8 @@ static char *func="SQLAllocConnect"; ...@@ -54,7 +57,8 @@ static char *func="SQLAllocConnect";
return SQL_ERROR; return SQL_ERROR;
} }
if ( ! EN_add_connection(env, conn)) { if (!EN_add_connection(env, conn))
{
env->errormsg = "Maximum number of connections exceeded."; env->errormsg = "Maximum number of connections exceeded.";
env->errornumber = ENV_ALLOC_ERROR; env->errornumber = ENV_ALLOC_ERROR;
CC_Destructor(conn); CC_Destructor(conn);
...@@ -71,22 +75,24 @@ static char *func="SQLAllocConnect"; ...@@ -71,22 +75,24 @@ static char *func="SQLAllocConnect";
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLConnect( RETCODE SQL_API
SQLConnect(
HDBC hdbc, HDBC hdbc,
UCHAR FAR *szDSN, UCHAR FAR * szDSN,
SWORD cbDSN, SWORD cbDSN,
UCHAR FAR *szUID, UCHAR FAR * szUID,
SWORD cbUID, SWORD cbUID,
UCHAR FAR *szAuthStr, UCHAR FAR * szAuthStr,
SWORD cbAuthStr) SWORD cbAuthStr)
{ {
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci; ConnInfo *ci;
static char *func = "SQLConnect"; static char *func = "SQLConnect";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -100,8 +106,9 @@ static char *func = "SQLConnect"; ...@@ -100,8 +106,9 @@ static char *func = "SQLConnect";
/* initialize pg_version from connInfo.protocol */ /* initialize pg_version from connInfo.protocol */
CC_initialize_pg_version(conn); CC_initialize_pg_version(conn);
/* override values from DSN info with UID and authStr(pwd) /*
This only occurs if the values are actually there. * override values from DSN info with UID and authStr(pwd) This only
* occurs if the values are actually there.
*/ */
make_string(szUID, cbUID, ci->username); make_string(szUID, cbUID, ci->username);
make_string(szAuthStr, cbAuthStr, ci->password); make_string(szAuthStr, cbAuthStr, ci->password);
...@@ -111,30 +118,32 @@ static char *func = "SQLConnect"; ...@@ -111,30 +118,32 @@ static char *func = "SQLConnect";
qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password); qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password);
if ( CC_connect(conn, FALSE) <= 0) { if (CC_connect(conn, FALSE) <= 0)
{
/* Error messages are filled in */ /* Error messages are filled in */
CC_log_error(func, "Error on CC_connect", conn); CC_log_error(func, "Error on CC_connect", conn);
return SQL_ERROR; return SQL_ERROR;
} }
mylog( "%s: returning...\n", func); mylog("%s: returning...\n", func);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLBrowseConnect( RETCODE SQL_API
SQLBrowseConnect(
HDBC hdbc, HDBC hdbc,
UCHAR FAR *szConnStrIn, UCHAR FAR * szConnStrIn,
SWORD cbConnStrIn, SWORD cbConnStrIn,
UCHAR FAR *szConnStrOut, UCHAR FAR * szConnStrOut,
SWORD cbConnStrOutMax, SWORD cbConnStrOutMax,
SWORD FAR *pcbConnStrOut) SWORD FAR * pcbConnStrOut)
{ {
static char *func="SQLBrowseConnect"; static char *func = "SQLBrowseConnect";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -142,23 +151,26 @@ static char *func="SQLBrowseConnect"; ...@@ -142,23 +151,26 @@ static char *func="SQLBrowseConnect";
/* - - - - - - - - - */ /* - - - - - - - - - */
/* Drop any hstmts open on hdbc and disconnect from database */ /* Drop any hstmts open on hdbc and disconnect from database */
RETCODE SQL_API SQLDisconnect( RETCODE SQL_API
SQLDisconnect(
HDBC hdbc) HDBC hdbc)
{ {
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
static char *func = "SQLDisconnect"; static char *func = "SQLDisconnect";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
qlog("conn=%u, %s\n", conn, func); qlog("conn=%u, %s\n", conn, func);
if (conn->status == CONN_EXECUTING) { if (conn->status == CONN_EXECUTING)
{
conn->errornumber = CONN_IN_USE; conn->errornumber = CONN_IN_USE;
conn->errormsg = "A transaction is currently being executed"; conn->errormsg = "A transaction is currently being executed";
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
...@@ -179,22 +191,25 @@ static char *func = "SQLDisconnect"; ...@@ -179,22 +191,25 @@ static char *func = "SQLDisconnect";
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLFreeConnect( RETCODE SQL_API
SQLFreeConnect(
HDBC hdbc) HDBC hdbc)
{ {
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
static char *func = "SQLFreeConnect"; static char *func = "SQLFreeConnect";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
mylog("**** in %s: hdbc=%u\n", func, hdbc); mylog("**** in %s: hdbc=%u\n", func, hdbc);
if ( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
/* Remove the connection from the environment */ /* Remove the connection from the environment */
if ( ! EN_remove_connection(conn->henv, conn)) { if (!EN_remove_connection(conn->henv, conn))
{
conn->errornumber = CONN_IN_USE; conn->errornumber = CONN_IN_USE;
conn->errormsg = "A transaction is currently being executed"; conn->errormsg = "A transaction is currently being executed";
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
...@@ -215,13 +230,15 @@ static char *func = "SQLFreeConnect"; ...@@ -215,13 +230,15 @@ static char *func = "SQLFreeConnect";
* *
*/ */
ConnectionClass *CC_Constructor() ConnectionClass *
CC_Constructor()
{ {
ConnectionClass *rv; ConnectionClass *rv;
rv = (ConnectionClass *)malloc(sizeof(ConnectionClass)); rv = (ConnectionClass *) malloc(sizeof(ConnectionClass));
if (rv != NULL) { if (rv != NULL)
{
rv->henv = NULL; /* not yet associated with an environment */ rv->henv = NULL; /* not yet associated with an environment */
...@@ -235,11 +252,11 @@ ConnectionClass *rv; ...@@ -235,11 +252,11 @@ ConnectionClass *rv;
memset(&rv->connInfo, 0, sizeof(ConnInfo)); memset(&rv->connInfo, 0, sizeof(ConnInfo));
rv->sock = SOCK_Constructor(); rv->sock = SOCK_Constructor();
if ( ! rv->sock) if (!rv->sock)
return NULL; return NULL;
rv->stmts = (StatementClass **) malloc( sizeof(StatementClass *) * STMT_INCREMENT); rv->stmts = (StatementClass **) malloc(sizeof(StatementClass *) * STMT_INCREMENT);
if ( ! rv->stmts) if (!rv->stmts)
return NULL; return NULL;
memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT); memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT);
...@@ -270,7 +287,7 @@ ConnectionClass *rv; ...@@ -270,7 +287,7 @@ ConnectionClass *rv;
char char
CC_Destructor(ConnectionClass *self) CC_Destructor(ConnectionClass * self)
{ {
mylog("enter CC_Destructor, self=%u\n", self); mylog("enter CC_Destructor, self=%u\n", self);
...@@ -283,17 +300,22 @@ CC_Destructor(ConnectionClass *self) ...@@ -283,17 +300,22 @@ CC_Destructor(ConnectionClass *self)
mylog("after CC_Cleanup\n"); mylog("after CC_Cleanup\n");
/* Free up statement holders */ /* Free up statement holders */
if (self->stmts) { if (self->stmts)
{
free(self->stmts); free(self->stmts);
self->stmts = NULL; self->stmts = NULL;
} }
mylog("after free statement holders\n"); mylog("after free statement holders\n");
/* Free cached table info */ /* Free cached table info */
if (self->col_info) { if (self->col_info)
{
int i; int i;
for (i = 0; i < self->ntables; i++) {
if (self->col_info[i]->result) /* Free the SQLColumns result structure */ for (i = 0; i < self->ntables; i++)
{
if (self->col_info[i]->result) /* Free the SQLColumns
* result structure */
QR_Destructor(self->col_info[i]->result); QR_Destructor(self->col_info[i]->result);
free(self->col_info[i]); free(self->col_info[i]);
...@@ -310,14 +332,16 @@ CC_Destructor(ConnectionClass *self) ...@@ -310,14 +332,16 @@ CC_Destructor(ConnectionClass *self)
/* Return how many cursors are opened on this connection */ /* Return how many cursors are opened on this connection */
int int
CC_cursor_count(ConnectionClass *self) CC_cursor_count(ConnectionClass * self)
{ {
StatementClass *stmt; StatementClass *stmt;
int i, count = 0; int i,
count = 0;
mylog("CC_cursor_count: self=%u, num_stmts=%d\n", self, self->num_stmts); mylog("CC_cursor_count: self=%u, num_stmts=%d\n", self, self->num_stmts);
for (i = 0; i < self->num_stmts; i++) { for (i = 0; i < self->num_stmts; i++)
{
stmt = self->stmts[i]; stmt = self->stmts[i];
if (stmt && stmt->result && stmt->result->cursor) if (stmt && stmt->result && stmt->result->cursor)
count++; count++;
...@@ -329,7 +353,7 @@ int i, count = 0; ...@@ -329,7 +353,7 @@ int i, count = 0;
} }
void void
CC_clear_error(ConnectionClass *self) CC_clear_error(ConnectionClass * self)
{ {
self->errornumber = 0; self->errornumber = 0;
self->errormsg = NULL; self->errormsg = NULL;
...@@ -339,11 +363,12 @@ CC_clear_error(ConnectionClass *self) ...@@ -339,11 +363,12 @@ CC_clear_error(ConnectionClass *self)
/* Used to cancel a transaction */ /* Used to cancel a transaction */
/* We are almost always in the middle of a transaction. */ /* We are almost always in the middle of a transaction. */
char char
CC_abort(ConnectionClass *self) CC_abort(ConnectionClass * self)
{ {
QResultClass *res; QResultClass *res;
if ( CC_is_in_trans(self)) { if (CC_is_in_trans(self))
{
res = NULL; res = NULL;
mylog("CC_abort: sending ABORT!\n"); mylog("CC_abort: sending ABORT!\n");
...@@ -363,10 +388,10 @@ QResultClass *res; ...@@ -363,10 +388,10 @@ QResultClass *res;
/* This is called by SQLDisconnect also */ /* This is called by SQLDisconnect also */
char char
CC_cleanup(ConnectionClass *self) CC_cleanup(ConnectionClass * self)
{ {
int i; int i;
StatementClass *stmt; StatementClass *stmt;
if (self->status == CONN_EXECUTING) if (self->status == CONN_EXECUTING)
return FALSE; return FALSE;
...@@ -382,7 +407,8 @@ StatementClass *stmt; ...@@ -382,7 +407,8 @@ StatementClass *stmt;
mylog("after CC_abort\n"); mylog("after CC_abort\n");
/* This actually closes the connection to the dbase */ /* This actually closes the connection to the dbase */
if (self->sock) { if (self->sock)
{
SOCK_Destructor(self->sock); SOCK_Destructor(self->sock);
self->sock = NULL; self->sock = NULL;
} }
...@@ -390,9 +416,11 @@ StatementClass *stmt; ...@@ -390,9 +416,11 @@ StatementClass *stmt;
mylog("after SOCK destructor\n"); mylog("after SOCK destructor\n");
/* Free all the stmts on this connection */ /* Free all the stmts on this connection */
for (i = 0; i < self->num_stmts; i++) { for (i = 0; i < self->num_stmts; i++)
{
stmt = self->stmts[i]; stmt = self->stmts[i];
if (stmt) { if (stmt)
{
stmt->hdbc = NULL; /* prevent any more dbase interactions */ stmt->hdbc = NULL; /* prevent any more dbase interactions */
SC_Destructor(stmt); SC_Destructor(stmt);
self->stmts[i] = NULL; self->stmts[i] = NULL;
...@@ -401,8 +429,9 @@ StatementClass *stmt; ...@@ -401,8 +429,9 @@ StatementClass *stmt;
/* Check for translation dll */ /* Check for translation dll */
#ifdef WIN32 #ifdef WIN32
if ( self->translation_handle) { if (self->translation_handle)
FreeLibrary (self->translation_handle); {
FreeLibrary(self->translation_handle);
self->translation_handle = NULL; self->translation_handle = NULL;
} }
#endif #endif
...@@ -412,37 +441,40 @@ StatementClass *stmt; ...@@ -412,37 +441,40 @@ StatementClass *stmt;
} }
int int
CC_set_translation (ConnectionClass *self) CC_set_translation(ConnectionClass * self)
{ {
#ifdef WIN32 #ifdef WIN32
if (self->translation_handle != NULL) { if (self->translation_handle != NULL)
FreeLibrary (self->translation_handle); {
FreeLibrary(self->translation_handle);
self->translation_handle = NULL; self->translation_handle = NULL;
} }
if (self->connInfo.translation_dll[0] == 0) if (self->connInfo.translation_dll[0] == 0)
return TRUE; return TRUE;
self->translation_option = atoi (self->connInfo.translation_option); self->translation_option = atoi(self->connInfo.translation_option);
self->translation_handle = LoadLibrary (self->connInfo.translation_dll); self->translation_handle = LoadLibrary(self->connInfo.translation_dll);
if (self->translation_handle == NULL) { if (self->translation_handle == NULL)
{
self->errornumber = CONN_UNABLE_TO_LOAD_DLL; self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
self->errormsg = "Could not load the translation DLL."; self->errormsg = "Could not load the translation DLL.";
return FALSE; return FALSE;
} }
self->DataSourceToDriver self->DataSourceToDriver
= (DataSourceToDriverProc) GetProcAddress (self->translation_handle, = (DataSourceToDriverProc) GetProcAddress(self->translation_handle,
"SQLDataSourceToDriver"); "SQLDataSourceToDriver");
self->DriverToDataSource self->DriverToDataSource
= (DriverToDataSourceProc) GetProcAddress (self->translation_handle, = (DriverToDataSourceProc) GetProcAddress(self->translation_handle,
"SQLDriverToDataSource"); "SQLDriverToDataSource");
if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL) { if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL)
{
self->errornumber = CONN_UNABLE_TO_LOAD_DLL; self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
self->errormsg = "Could not find translation DLL functions."; self->errormsg = "Could not find translation DLL functions.";
return FALSE; return FALSE;
...@@ -452,25 +484,26 @@ CC_set_translation (ConnectionClass *self) ...@@ -452,25 +484,26 @@ CC_set_translation (ConnectionClass *self)
} }
char char
CC_connect(ConnectionClass *self, char do_password) CC_connect(ConnectionClass * self, char do_password)
{ {
StartupPacket sp; StartupPacket sp;
QResultClass *res; QResultClass *res;
SocketClass *sock; SocketClass *sock;
ConnInfo *ci = &(self->connInfo); ConnInfo *ci = &(self->connInfo);
int areq = -1; int areq = -1;
int beresp; int beresp;
char msgbuffer[ERROR_MSG_LENGTH]; char msgbuffer[ERROR_MSG_LENGTH];
char salt[2]; char salt[2];
static char *func="CC_connect"; static char *func = "CC_connect";
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( do_password) if (do_password)
sock = self->sock; /* already connected, just authenticate */ sock = self->sock; /* already connected, just authenticate */
else { else
{
qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n", qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
POSTGRESDRIVERVERSION, POSTGRESDRIVERVERSION,
...@@ -492,13 +525,15 @@ static char *func="CC_connect"; ...@@ -492,13 +525,15 @@ static char *func="CC_connect";
globals.extra_systable_prefixes, globals.extra_systable_prefixes,
globals.conn_settings); globals.conn_settings);
if (self->status != CONN_NOT_CONNECTED) { if (self->status != CONN_NOT_CONNECTED)
{
self->errormsg = "Already connected."; self->errormsg = "Already connected.";
self->errornumber = CONN_OPENDB_ERROR; self->errornumber = CONN_OPENDB_ERROR;
return 0; return 0;
} }
if ( ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\0') { if (ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\0')
{
self->errornumber = CONN_INIREAD_ERROR; self->errornumber = CONN_INIREAD_ERROR;
self->errormsg = "Missing server name, port, or database name in call to CC_connect."; self->errormsg = "Missing server name, port, or database name in call to CC_connect.";
return 0; return 0;
...@@ -506,12 +541,15 @@ static char *func="CC_connect"; ...@@ -506,12 +541,15 @@ static char *func="CC_connect";
mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password); mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);
/* If the socket was closed for some reason (like a SQLDisconnect, but no SQLFreeConnect /*
then create a socket now. * If the socket was closed for some reason (like a SQLDisconnect,
* but no SQLFreeConnect then create a socket now.
*/ */
if ( ! self->sock) { if (!self->sock)
{
self->sock = SOCK_Constructor(); self->sock = SOCK_Constructor();
if ( ! self->sock) { if (!self->sock)
{
self->errornumber = CONNECTION_SERVER_NOT_REACHED; self->errornumber = CONNECTION_SERVER_NOT_REACHED;
self->errormsg = "Could not open a socket to the server"; self->errormsg = "Could not open a socket to the server";
return 0; return 0;
...@@ -523,7 +561,8 @@ static char *func="CC_connect"; ...@@ -523,7 +561,8 @@ static char *func="CC_connect";
mylog("connecting to the server socket...\n"); mylog("connecting to the server socket...\n");
SOCK_connect_to(sock, (short) atoi(ci->port), ci->server); SOCK_connect_to(sock, (short) atoi(ci->port), ci->server);
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
mylog("connection to the server socket failed.\n"); mylog("connection to the server socket failed.\n");
self->errornumber = CONNECTION_SERVER_NOT_REACHED; self->errornumber = CONNECTION_SERVER_NOT_REACHED;
self->errormsg = "Could not connect to the server"; self->errormsg = "Could not connect to the server";
...@@ -536,7 +575,7 @@ static char *func="CC_connect"; ...@@ -536,7 +575,7 @@ static char *func="CC_connect";
mylog("sizeof startup packet = %d\n", sizeof(StartupPacket)); mylog("sizeof startup packet = %d\n", sizeof(StartupPacket));
/* Send length of Authentication Block */ /* Send length of Authentication Block */
SOCK_put_int(sock, 4+sizeof(StartupPacket), 4); SOCK_put_int(sock, 4 + sizeof(StartupPacket), 4);
sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST); sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST);
...@@ -548,7 +587,8 @@ static char *func="CC_connect"; ...@@ -548,7 +587,8 @@ static char *func="CC_connect";
mylog("sent the authentication block.\n"); mylog("sent the authentication block.\n");
if (sock->errornumber != 0) { if (sock->errornumber != 0)
{
mylog("couldn't send the authentication block properly.\n"); mylog("couldn't send the authentication block properly.\n");
self->errornumber = CONN_INVALID_AUTHENTICATION; self->errornumber = CONN_INVALID_AUTHENTICATION;
self->errormsg = "Sending the authentication packet failed"; self->errormsg = "Sending the authentication packet failed";
...@@ -564,14 +604,16 @@ static char *func="CC_connect"; ...@@ -564,14 +604,16 @@ static char *func="CC_connect";
/* Now get the authentication request from backend */ /* Now get the authentication request from backend */
/* *************************************************** */ /* *************************************************** */
do { do
{
if (do_password) if (do_password)
beresp = 'R'; beresp = 'R';
else else
beresp = SOCK_get_char(sock); beresp = SOCK_get_char(sock);
switch(beresp) { switch (beresp)
{
case 'E': case 'E':
mylog("auth got 'E'\n"); mylog("auth got 'E'\n");
...@@ -582,12 +624,14 @@ static char *func="CC_connect"; ...@@ -582,12 +624,14 @@ static char *func="CC_connect";
return 0; return 0;
case 'R': case 'R':
if (do_password) { if (do_password)
{
mylog("in 'R' do_password\n"); mylog("in 'R' do_password\n");
areq = AUTH_REQ_PASSWORD; areq = AUTH_REQ_PASSWORD;
do_password = FALSE; do_password = FALSE;
} }
else { else
{
mylog("auth got 'R'\n"); mylog("auth got 'R'\n");
areq = SOCK_get_int(sock, 4); areq = SOCK_get_int(sock, 4);
...@@ -596,7 +640,8 @@ static char *func="CC_connect"; ...@@ -596,7 +640,8 @@ static char *func="CC_connect";
mylog("areq = %d\n", areq); mylog("areq = %d\n", areq);
} }
switch(areq) { switch (areq)
{
case AUTH_REQ_OK: case AUTH_REQ_OK:
break; break;
...@@ -613,7 +658,8 @@ static char *func="CC_connect"; ...@@ -613,7 +658,8 @@ static char *func="CC_connect";
case AUTH_REQ_PASSWORD: case AUTH_REQ_PASSWORD:
mylog("in AUTH_REQ_PASSWORD\n"); mylog("in AUTH_REQ_PASSWORD\n");
if (ci->password[0] == '\0') { if (ci->password[0] == '\0')
{
self->errornumber = CONNECTION_NEED_PASSWORD; self->errornumber = CONNECTION_NEED_PASSWORD;
self->errormsg = "A password is required for this connection."; self->errormsg = "A password is required for this connection.";
return -1; /* need password */ return -1; /* need password */
...@@ -621,7 +667,7 @@ static char *func="CC_connect"; ...@@ -621,7 +667,7 @@ static char *func="CC_connect";
mylog("past need password\n"); mylog("past need password\n");
SOCK_put_int(sock, 4+strlen(ci->password)+1, 4); SOCK_put_int(sock, 4 + strlen(ci->password) + 1, 4);
SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1); SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1);
SOCK_flush_output(sock); SOCK_flush_output(sock);
...@@ -654,7 +700,8 @@ static char *func="CC_connect"; ...@@ -654,7 +700,8 @@ static char *func="CC_connect";
mylog("sending an empty query...\n"); mylog("sending an empty query...\n");
res = CC_send_query(self, " ", NULL); res = CC_send_query(self, " ", NULL);
if ( res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY) { if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
{
mylog("got no result from the empty query. (probably database does not exist)\n"); mylog("got no result from the empty query. (probably database does not exist)\n");
self->errornumber = CONNECTION_NO_SUCH_DATABASE; self->errornumber = CONNECTION_NO_SUCH_DATABASE;
self->errormsg = "The database does not exist on the server\nor user authentication failed."; self->errormsg = "The database does not exist on the server\nor user authentication failed.";
...@@ -667,19 +714,23 @@ static char *func="CC_connect"; ...@@ -667,19 +714,23 @@ static char *func="CC_connect";
mylog("empty query seems to be OK.\n"); mylog("empty query seems to be OK.\n");
CC_set_translation (self); CC_set_translation(self);
/**********************************************/ /**********************************************/
/******* Send any initial settings *********/ /******* Send any initial settings *********/
/**********************************************/ /**********************************************/
/* Since these functions allocate statements, and since the connection is not /*
established yet, it would violate odbc state transition rules. Therefore, * Since these functions allocate statements, and since the connection
these functions call the corresponding local function instead. * is not established yet, it would violate odbc state transition
* rules. Therefore, these functions call the corresponding local
* function instead.
*/ */
CC_send_settings(self); CC_send_settings(self);
CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */ CC_lookup_lo(self); /* a hack to get the oid of our large
CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo use */ * object oid type */
CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo
* use */
CC_clear_error(self); /* clear any initial command errors */ CC_clear_error(self); /* clear any initial command errors */
self->status = CONN_CONNECTED; self->status = CONN_CONNECTED;
...@@ -691,14 +742,16 @@ static char *func="CC_connect"; ...@@ -691,14 +742,16 @@ static char *func="CC_connect";
} }
char char
CC_add_statement(ConnectionClass *self, StatementClass *stmt) CC_add_statement(ConnectionClass * self, StatementClass * stmt)
{ {
int i; int i;
mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt); mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt);
for (i = 0; i < self->num_stmts; i++) { for (i = 0; i < self->num_stmts; i++)
if ( ! self->stmts[i]) { {
if (!self->stmts[i])
{
stmt->hdbc = self; stmt->hdbc = self;
self->stmts[i] = stmt; self->stmts[i] = stmt;
return TRUE; return TRUE;
...@@ -706,8 +759,8 @@ int i; ...@@ -706,8 +759,8 @@ int i;
} }
/* no more room -- allocate more memory */ /* no more room -- allocate more memory */
self->stmts = (StatementClass **) realloc( self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts)); self->stmts = (StatementClass **) realloc(self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));
if ( ! self->stmts) if (!self->stmts)
return FALSE; return FALSE;
memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT); memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT);
...@@ -721,12 +774,14 @@ int i; ...@@ -721,12 +774,14 @@ int i;
} }
char char
CC_remove_statement(ConnectionClass *self, StatementClass *stmt) CC_remove_statement(ConnectionClass * self, StatementClass * stmt)
{ {
int i; int i;
for (i = 0; i < self->num_stmts; i++) { for (i = 0; i < self->num_stmts; i++)
if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING) { {
if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING)
{
self->stmts[i] = NULL; self->stmts[i] = NULL;
return TRUE; return TRUE;
} }
...@@ -739,11 +794,11 @@ int i; ...@@ -739,11 +794,11 @@ int i;
error message with its socket error message. error message with its socket error message.
*/ */
char * char *
CC_create_errormsg(ConnectionClass *self) CC_create_errormsg(ConnectionClass * self)
{ {
SocketClass *sock = self->sock; SocketClass *sock = self->sock;
int pos; int pos;
static char msg[4096]; static char msg[4096];
mylog("enter CC_create_errormsg\n"); mylog("enter CC_create_errormsg\n");
...@@ -754,7 +809,8 @@ static char msg[4096]; ...@@ -754,7 +809,8 @@ static char msg[4096];
mylog("msg = '%s'\n", msg); mylog("msg = '%s'\n", msg);
if (sock && sock->errormsg && sock->errormsg[0] != '\0') { if (sock && sock->errormsg && sock->errormsg[0] != '\0')
{
pos = strlen(msg); pos = strlen(msg);
sprintf(&msg[pos], ";\n%s", sock->errormsg); sprintf(&msg[pos], ";\n%s", sock->errormsg);
} }
...@@ -765,19 +821,21 @@ static char msg[4096]; ...@@ -765,19 +821,21 @@ static char msg[4096];
char char
CC_get_error(ConnectionClass *self, int *number, char **message) CC_get_error(ConnectionClass * self, int *number, char **message)
{ {
int rv; int rv;
mylog("enter CC_get_error\n"); mylog("enter CC_get_error\n");
/* 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) { if (!self->errormsg_created)
{
self->errormsg = CC_create_errormsg(self); self->errormsg = CC_create_errormsg(self);
self->errormsg_created = TRUE; self->errormsg_created = TRUE;
} }
if (self->errornumber) { if (self->errornumber)
{
*number = self->errornumber; *number = self->errornumber;
*message = self->errormsg; *message = self->errormsg;
} }
...@@ -800,21 +858,25 @@ int rv; ...@@ -800,21 +858,25 @@ int rv;
'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements. 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/ */
QResultClass * QResultClass *
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) CC_send_query(ConnectionClass * self, char *query, QueryInfo * qi)
{ {
QResultClass *result_in, *res = NULL; QResultClass *result_in,
char swallow; *res = NULL;
int id; char swallow;
SocketClass *sock = self->sock; int id;
static char msgbuffer[MAX_MESSAGE_LEN+1]; SocketClass *sock = self->sock;
char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont need static */ static char msgbuffer[MAX_MESSAGE_LEN + 1];
char cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
* this string so dont
* need static */
mylog("send_query(): conn=%u, query='%s'\n", self, query); mylog("send_query(): conn=%u, query='%s'\n", self, query);
qlog("conn=%u, query='%s'\n", self, query); qlog("conn=%u, query='%s'\n", self, query);
/* Indicate that we are sending a query to the backend */ /* Indicate that we are sending a query to the backend */
if(strlen(query) > MAX_MESSAGE_LEN-2) { if (strlen(query) > MAX_MESSAGE_LEN - 2)
{
self->errornumber = CONNECTION_MSG_TOO_LONG; self->errornumber = CONNECTION_MSG_TOO_LONG;
self->errormsg = "Query string is too long"; self->errormsg = "Query string is too long";
return NULL; return NULL;
...@@ -823,7 +885,8 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -823,7 +885,8 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
if ((NULL == query) || (query[0] == '\0')) if ((NULL == query) || (query[0] == '\0'))
return NULL; return NULL;
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_COULD_NOT_SEND; self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send Query to backend"; self->errormsg = "Could not send Query to backend";
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -831,7 +894,8 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -831,7 +894,8 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
} }
SOCK_put_char(sock, 'Q'); SOCK_put_char(sock, 'Q');
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_COULD_NOT_SEND; self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send Query to backend"; self->errormsg = "Could not send Query to backend";
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -841,7 +905,8 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -841,7 +905,8 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
SOCK_put_string(sock, query); SOCK_put_string(sock, query);
SOCK_flush_output(sock); SOCK_flush_output(sock);
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_COULD_NOT_SEND; self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send Query to backend"; self->errormsg = "Could not send Query to backend";
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -850,11 +915,13 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -850,11 +915,13 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
mylog("send_query: done sending query\n"); mylog("send_query: done sending query\n");
while(1) { while (1)
{
/* what type of message is coming now ? */ /* what type of message is coming now ? */
id = SOCK_get_char(sock); id = SOCK_get_char(sock);
if ((SOCK_get_errcode(sock) != 0) || (id == EOF)) { if ((SOCK_get_errcode(sock) != 0) || (id == EOF))
{
self->errornumber = CONNECTION_NO_RESPONSE; self->errornumber = CONNECTION_NO_RESPONSE;
self->errormsg = "No response from the backend"; self->errormsg = "No response from the backend";
if (res) if (res)
...@@ -867,22 +934,27 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -867,22 +934,27 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
mylog("send_query: got id = '%c'\n", id); mylog("send_query: got id = '%c'\n", id);
switch (id) { switch (id)
case 'A' : /* Asynchronous Messages are ignored */ {
(void)SOCK_get_int(sock, 4); /* id of notification */ case 'A': /* Asynchronous Messages are ignored */
(void) SOCK_get_int(sock, 4); /* id of notification */
SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN); SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
/* name of the relation the message comes from */ /* name of the relation the message comes from */
break; break;
case 'C' : /* portal query command, no tuples returned */ case 'C': /* portal query command, no tuples
* returned */
/* read in the return message from the backend */ /* read in the return message from the backend */
SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN); SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_NO_RESPONSE; self->errornumber = CONNECTION_NO_RESPONSE;
self->errormsg = "No response from backend while receiving a portal query command"; self->errormsg = "No response from backend while receiving a portal query command";
mylog("send_query: 'C' - %s\n", self->errormsg); mylog("send_query: 'C' - %s\n", self->errormsg);
CC_set_no_trans(self); CC_set_no_trans(self);
return NULL; return NULL;
} else { }
else
{
char clear = 0; char clear = 0;
...@@ -897,19 +969,22 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -897,19 +969,22 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
QR_set_status(res, PGRES_COMMAND_OK); QR_set_status(res, PGRES_COMMAND_OK);
QR_set_command(res, cmdbuffer); QR_set_command(res, cmdbuffer);
/* (Quotation from the original comments) /*
since backend may produce more than one result for some commands * (Quotation from the original comments) since
we need to poll until clear * backend may produce more than one result for some
so we send an empty query, and keep reading out of the pipe * commands we need to poll until clear so we send an
until an 'I' is received * empty query, and keep reading out of the pipe until
* an 'I' is received
*/ */
SOCK_put_string(sock, "Q "); SOCK_put_string(sock, "Q ");
SOCK_flush_output(sock); SOCK_flush_output(sock);
while( ! clear) { while (!clear)
{
id = SOCK_get_char(sock); id = SOCK_get_char(sock);
switch(id) { switch (id)
{
case 'I': case 'I':
(void) SOCK_get_char(sock); (void) SOCK_get_char(sock);
clear = TRUE; clear = TRUE;
...@@ -927,13 +1002,17 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -927,13 +1002,17 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
case 'E': case 'E':
SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
qlog("ERROR from backend during clear: '%s'\n", cmdbuffer); qlog("ERROR from backend during clear: '%s'\n", cmdbuffer);
/* We must report this type of error as well
(practically for reference integrity violation /*
error reporting, from PostgreSQL 7.0). * We must report this type of error as
(Zoltan Kovacs, 04/26/2000) * well (practically for reference
* integrity violation error reporting,
* from PostgreSQL 7.0). (Zoltan Kovacs,
* 04/26/2000)
*/ */
self->errormsg = cmdbuffer; self->errormsg = cmdbuffer;
if ( ! strncmp(self->errormsg, "FATAL", 5)) { if (!strncmp(self->errormsg, "FATAL", 5))
{
self->errornumber = CONNECTION_SERVER_REPORTED_ERROR; self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
CC_set_no_trans(self); CC_set_no_trans(self);
} }
...@@ -948,13 +1027,13 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -948,13 +1027,13 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
return res; return res;
} }
case 'K': /* Secret key (6.4 protocol) */ case 'K': /* Secret key (6.4 protocol) */
(void)SOCK_get_int(sock, 4); /* pid */ (void) SOCK_get_int(sock, 4); /* pid */
(void)SOCK_get_int(sock, 4); /* key */ (void) SOCK_get_int(sock, 4); /* key */
break; break;
case 'Z': /* Backend is ready for new query (6.4) */ case 'Z': /* Backend is ready for new query (6.4) */
break; break;
case 'N' : /* NOTICE: */ case 'N': /* NOTICE: */
SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
res = QR_Constructor(); res = QR_Constructor();
...@@ -964,30 +1043,34 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -964,30 +1043,34 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
mylog("~~~ NOTICE: '%s'\n", cmdbuffer); mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer); qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
continue; /* dont return a result -- continue reading */ continue; /* dont return a result -- continue
* reading */
case 'I' : /* The server sends an empty query */ case 'I': /* The server sends an empty query */
/* There is a closing '\0' following the 'I', so we eat it */ /* There is a closing '\0' following the 'I', so we eat it */
swallow = SOCK_get_char(sock); swallow = SOCK_get_char(sock);
if ((swallow != '\0') || SOCK_get_errcode(sock) != 0) { if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_BACKEND_CRAZY; self->errornumber = CONNECTION_BACKEND_CRAZY;
self->errormsg = "Unexpected protocol character from backend (send_query - I)"; self->errormsg = "Unexpected protocol character from backend (send_query - I)";
res = QR_Constructor(); res = QR_Constructor();
QR_set_status(res, PGRES_FATAL_ERROR); QR_set_status(res, PGRES_FATAL_ERROR);
return res; return res;
} else { }
else
{
/* We return the empty query */ /* We return the empty query */
res = QR_Constructor(); res = QR_Constructor();
QR_set_status(res, PGRES_EMPTY_QUERY); QR_set_status(res, PGRES_EMPTY_QUERY);
return res; return res;
} }
break; break;
case 'E' : case 'E':
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
/* Remove a newline */ /* Remove a newline */
if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer)-1] == '\n') if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer) - 1] == '\n')
msgbuffer[strlen(msgbuffer)-1] = '\0'; msgbuffer[strlen(msgbuffer) - 1] = '\0';
self->errormsg = msgbuffer; self->errormsg = msgbuffer;
...@@ -997,28 +1080,32 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -997,28 +1080,32 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
/* We should report that an error occured. Zoltan */ /* We should report that an error occured. Zoltan */
res = QR_Constructor(); res = QR_Constructor();
if ( ! strncmp(self->errormsg, "FATAL", 5)) { if (!strncmp(self->errormsg, "FATAL", 5))
{
self->errornumber = CONNECTION_SERVER_REPORTED_ERROR; self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
CC_set_no_trans(self); CC_set_no_trans(self);
QR_set_status(res, PGRES_FATAL_ERROR); QR_set_status(res, PGRES_FATAL_ERROR);
} }
else { else
{
self->errornumber = CONNECTION_SERVER_REPORTED_WARNING; self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
QR_set_status(res, PGRES_NONFATAL_ERROR); QR_set_status(res, PGRES_NONFATAL_ERROR);
} }
return res; /* instead of NULL. Zoltan */ return res; /* instead of NULL. Zoltan */
case 'P' : /* get the Portal name */ case 'P': /* get the Portal name */
SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN); SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
break; break;
case 'T': /* Tuple results start here */ case 'T': /* Tuple results start here */
result_in = qi ? qi->result_in : NULL; result_in = qi ? qi->result_in : NULL;
if ( result_in == NULL) { if (result_in == NULL)
{
result_in = QR_Constructor(); result_in = QR_Constructor();
mylog("send_query: 'T' no result_in: res = %u\n", result_in); mylog("send_query: 'T' no result_in: res = %u\n", result_in);
if ( ! result_in) { if (!result_in)
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = "Could not create result info in send_query."; self->errormsg = "Could not create result info in send_query.";
return NULL; return NULL;
...@@ -1027,14 +1114,17 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -1027,14 +1114,17 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
if (qi) if (qi)
QR_set_cache_size(result_in, qi->row_size); QR_set_cache_size(result_in, qi->row_size);
if ( ! QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL)) { if (!QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL))
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = QR_get_message(result_in); self->errormsg = QR_get_message(result_in);
return NULL; return NULL;
} }
} }
else { /* next fetch, so reuse an existing result */ else
if ( ! QR_fetch_tuples(result_in, NULL, NULL)) { { /* next fetch, so reuse an existing result */
if (!QR_fetch_tuples(result_in, NULL, NULL))
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = QR_get_message(result_in); self->errormsg = QR_get_message(result_in);
return NULL; return NULL;
...@@ -1062,16 +1152,19 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont ...@@ -1062,16 +1152,19 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
} }
int int
CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs) CC_send_function(ConnectionClass * self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG * args, int nargs)
{ {
char id, c, done; char id,
SocketClass *sock = self->sock; c,
static char msgbuffer[MAX_MESSAGE_LEN+1]; done;
int i; SocketClass *sock = self->sock;
static char msgbuffer[MAX_MESSAGE_LEN + 1];
int i;
mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs); mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_COULD_NOT_SEND; self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send function to backend"; self->errormsg = "Could not send function to backend";
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -1079,7 +1172,8 @@ int i; ...@@ -1079,7 +1172,8 @@ int i;
} }
SOCK_put_string(sock, "F "); SOCK_put_string(sock, "F ");
if (SOCK_get_errcode(sock) != 0) { if (SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_COULD_NOT_SEND; self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send function to backend"; self->errormsg = "Could not send function to backend";
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -1091,7 +1185,8 @@ int i; ...@@ -1091,7 +1185,8 @@ int i;
mylog("send_function: done sending function\n"); mylog("send_function: done sending function\n");
for (i = 0; i < nargs; ++i) { for (i = 0; i < nargs; ++i)
{
mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr); mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
...@@ -1108,11 +1203,13 @@ int i; ...@@ -1108,11 +1203,13 @@ int i;
mylog(" after flush output\n"); mylog(" after flush output\n");
done = FALSE; done = FALSE;
while ( ! done) { while (!done)
{
id = SOCK_get_char(sock); id = SOCK_get_char(sock);
mylog(" got id = %c\n", id); mylog(" got id = %c\n", id);
switch(id) { switch (id)
{
case 'V': case 'V':
done = TRUE; done = TRUE;
break; /* ok */ break; /* ok */
...@@ -1146,8 +1243,10 @@ int i; ...@@ -1146,8 +1243,10 @@ int i;
} }
id = SOCK_get_char(sock); id = SOCK_get_char(sock);
for (;;) { for (;;)
switch (id) { {
switch (id)
{
case 'G': /* function returned properly */ case 'G': /* function returned properly */
mylog(" got G!\n"); mylog(" got G!\n");
...@@ -1182,7 +1281,8 @@ int i; ...@@ -1182,7 +1281,8 @@ int i;
mylog("send_function(G): 'N' - %s\n", msgbuffer); mylog("send_function(G): 'N' - %s\n", msgbuffer);
qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer); qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer);
continue; /* dont return a result -- continue reading */ continue; /* dont return a result -- continue
* reading */
case '0': /* empty result */ case '0': /* empty result */
return TRUE; return TRUE;
...@@ -1200,17 +1300,19 @@ int i; ...@@ -1200,17 +1300,19 @@ int i;
char char
CC_send_settings(ConnectionClass *self) CC_send_settings(ConnectionClass * self)
{ {
/* char ini_query[MAX_MESSAGE_LEN]; */ /* char ini_query[MAX_MESSAGE_LEN]; */
ConnInfo *ci = &(self->connInfo); ConnInfo *ci = &(self->connInfo);
/* QResultClass *res; */ /* QResultClass *res; */
HSTMT hstmt; HSTMT hstmt;
StatementClass *stmt; StatementClass *stmt;
RETCODE result; RETCODE result;
char status = TRUE; char status = TRUE;
char *cs, *ptr; char *cs,
static char *func="CC_send_settings"; *ptr;
static char *func = "CC_send_settings";
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -1219,25 +1321,25 @@ static char *func="CC_send_settings"; ...@@ -1219,25 +1321,25 @@ static char *func="CC_send_settings";
has not transitioned to "connected" yet. has not transitioned to "connected" yet.
*/ */
result = SQLAllocStmt( self, &hstmt); result = SQLAllocStmt(self, &hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
return FALSE; return FALSE;
}
stmt = (StatementClass *) hstmt; stmt = (StatementClass *) hstmt;
stmt->internal = TRUE; /* ensure no BEGIN/COMMIT/ABORT stuff */ stmt->internal = TRUE; /* ensure no BEGIN/COMMIT/ABORT stuff */
/* Set the Datestyle to the format the driver expects it to be in */ /* Set the Datestyle to the format the driver expects it to be in */
result = SQLExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS); result = SQLExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
status = FALSE; status = FALSE;
mylog("%s: result %d, status %d from set DateStyle\n", func, result, status); mylog("%s: result %d, status %d from set DateStyle\n", func, result, status);
/* Disable genetic optimizer based on global flag */ /* Disable genetic optimizer based on global flag */
if (globals.disable_optimizer) { if (globals.disable_optimizer)
{
result = SQLExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS); result = SQLExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
status = FALSE; status = FALSE;
mylog("%s: result %d, status %d from set geqo\n", func, result, status); mylog("%s: result %d, status %d from set geqo\n", func, result, status);
...@@ -1245,9 +1347,10 @@ static char *func="CC_send_settings"; ...@@ -1245,9 +1347,10 @@ static char *func="CC_send_settings";
} }
/* KSQO */ /* KSQO */
if (globals.ksqo) { if (globals.ksqo)
{
result = SQLExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS); result = SQLExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
status = FALSE; status = FALSE;
mylog("%s: result %d, status %d from set ksqo\n", func, result, status); mylog("%s: result %d, status %d from set ksqo\n", func, result, status);
...@@ -1255,12 +1358,14 @@ static char *func="CC_send_settings"; ...@@ -1255,12 +1358,14 @@ static char *func="CC_send_settings";
} }
/* Global settings */ /* Global settings */
if (globals.conn_settings[0] != '\0') { if (globals.conn_settings[0] != '\0')
{
cs = strdup(globals.conn_settings); cs = strdup(globals.conn_settings);
ptr = strtok(cs, ";"); ptr = strtok(cs, ";");
while (ptr) { while (ptr)
{
result = SQLExecDirect(hstmt, ptr, SQL_NTS); result = SQLExecDirect(hstmt, ptr, SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
status = FALSE; status = FALSE;
mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr); mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
...@@ -1272,12 +1377,14 @@ static char *func="CC_send_settings"; ...@@ -1272,12 +1377,14 @@ static char *func="CC_send_settings";
} }
/* Per Datasource settings */ /* Per Datasource settings */
if (ci->conn_settings[0] != '\0') { if (ci->conn_settings[0] != '\0')
{
cs = strdup(ci->conn_settings); cs = strdup(ci->conn_settings);
ptr = strtok(cs, ";"); ptr = strtok(cs, ";");
while (ptr) { while (ptr)
{
result = SQLExecDirect(hstmt, ptr, SQL_NTS); result = SQLExecDirect(hstmt, ptr, SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
status = FALSE; status = FALSE;
mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr); mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
...@@ -1299,38 +1406,40 @@ static char *func="CC_send_settings"; ...@@ -1299,38 +1406,40 @@ static char *func="CC_send_settings";
will go away and the define 'PG_TYPE_LO' will be updated. will go away and the define 'PG_TYPE_LO' will be updated.
*/ */
void void
CC_lookup_lo(ConnectionClass *self) CC_lookup_lo(ConnectionClass * self)
{ {
HSTMT hstmt; HSTMT hstmt;
StatementClass *stmt; StatementClass *stmt;
RETCODE result; RETCODE result;
static char *func = "CC_lookup_lo"; static char *func = "CC_lookup_lo";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
/* This function must use the local odbc API functions since the odbc state /* This function must use the local odbc API functions since the odbc state
has not transitioned to "connected" yet. has not transitioned to "connected" yet.
*/ */
result = SQLAllocStmt( self, &hstmt); result = SQLAllocStmt(self, &hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
return; return;
}
stmt = (StatementClass *) hstmt; stmt = (StatementClass *) hstmt;
result = SQLExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS); result = SQLExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SQLFreeStmt(hstmt, SQL_DROP); SQLFreeStmt(hstmt, SQL_DROP);
return; return;
} }
result = SQLFetch(hstmt); result = SQLFetch(hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SQLFreeStmt(hstmt, SQL_DROP); SQLFreeStmt(hstmt, SQL_DROP);
return; return;
} }
result = SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL); result = SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SQLFreeStmt(hstmt, SQL_DROP); SQLFreeStmt(hstmt, SQL_DROP);
return; return;
} }
...@@ -1346,53 +1455,57 @@ static char *func = "CC_lookup_lo"; ...@@ -1346,53 +1455,57 @@ static char *func = "CC_lookup_lo";
h-inoue 01-2-2001 h-inoue 01-2-2001
*/ */
void void
CC_initialize_pg_version(ConnectionClass *self) CC_initialize_pg_version(ConnectionClass * self)
{ {
strcpy(self->pg_version, self->connInfo.protocol); strcpy(self->pg_version, self->connInfo.protocol);
self->pg_version_number = (float) 6.4; self->pg_version_number = (float) 6.4;
self->pg_version_major = 6; self->pg_version_major = 6;
self->pg_version_minor = 4; self->pg_version_minor = 4;
} }
/* This function gets the version of PostgreSQL that we're connected to. /* This function gets the version of PostgreSQL that we're connected to.
This is used to return the correct info in SQLGetInfo This is used to return the correct info in SQLGetInfo
DJP - 25-1-2001 DJP - 25-1-2001
*/ */
void void
CC_lookup_pg_version(ConnectionClass *self) CC_lookup_pg_version(ConnectionClass * self)
{ {
HSTMT hstmt; HSTMT hstmt;
StatementClass *stmt; StatementClass *stmt;
RETCODE result; RETCODE result;
char szVersion[32]; char szVersion[32];
int major, minor; int major,
static char *func = "CC_lookup_pg_version"; minor;
static char *func = "CC_lookup_pg_version";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
/* This function must use the local odbc API functions since the odbc state /* This function must use the local odbc API functions since the odbc state
has not transitioned to "connected" yet. has not transitioned to "connected" yet.
*/ */
result = SQLAllocStmt( self, &hstmt); result = SQLAllocStmt(self, &hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
return; return;
}
stmt = (StatementClass *) hstmt; stmt = (StatementClass *) hstmt;
/* get the server's version if possible */ /* get the server's version if possible */
result = SQLExecDirect(hstmt, "select version()", SQL_NTS); result = SQLExecDirect(hstmt, "select version()", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SQLFreeStmt(hstmt, SQL_DROP); SQLFreeStmt(hstmt, SQL_DROP);
return; return;
} }
result = SQLFetch(hstmt); result = SQLFetch(hstmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SQLFreeStmt(hstmt, SQL_DROP); SQLFreeStmt(hstmt, SQL_DROP);
return; return;
} }
result = SQLGetData(hstmt, 1, SQL_C_CHAR, self->pg_version, MAX_INFO_STRING, NULL); result = SQLGetData(hstmt, 1, SQL_C_CHAR, self->pg_version, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SQLFreeStmt(hstmt, SQL_DROP); SQLFreeStmt(hstmt, SQL_DROP);
return; return;
} }
...@@ -1400,7 +1513,8 @@ static char *func = "CC_lookup_pg_version"; ...@@ -1400,7 +1513,8 @@ static char *func = "CC_lookup_pg_version";
/* Extract the Major and Minor numbers from the string. */ /* Extract the Major and Minor numbers from the string. */
/* This assumes the string starts 'Postgresql X.X' */ /* This assumes the string starts 'Postgresql X.X' */
strcpy(szVersion, "0.0"); strcpy(szVersion, "0.0");
if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2) { if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
{
sprintf(szVersion, "%d.%d", major, minor); sprintf(szVersion, "%d.%d", major, minor);
self->pg_version_major = major; self->pg_version_major = major;
self->pg_version_minor = minor; self->pg_version_minor = minor;
...@@ -1416,22 +1530,25 @@ static char *func = "CC_lookup_pg_version"; ...@@ -1416,22 +1530,25 @@ static char *func = "CC_lookup_pg_version";
} }
void void
CC_log_error(char *func, char *desc, ConnectionClass *self) CC_log_error(char *func, char *desc, ConnectionClass * self)
{ {
#ifdef PRN_NULLCHECK #ifdef PRN_NULLCHECK
#define nullcheck(a) (a ? a : "(NULL)") #define nullcheck(a) (a ? a : "(NULL)")
#endif #endif
if (self) { if (self)
qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck (self->errormsg)); {
mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck (self->errormsg)); qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
qlog(" ------------------------------------------------------------\n"); qlog(" ------------------------------------------------------------\n");
qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts); qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type); qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
qlog(" ---------------- Socket Info -------------------------------\n"); qlog(" ---------------- Socket Info -------------------------------\n");
if (self->sock) { if (self->sock)
{
SocketClass *sock = self->sock; SocketClass *sock = self->sock;
qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg)); qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg));
qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out); qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in); qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
...@@ -1441,4 +1558,3 @@ CC_log_error(char *func, char *desc, ConnectionClass *self) ...@@ -1441,4 +1558,3 @@ CC_log_error(char *func, char *desc, ConnectionClass *self)
qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc); qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
#undef PRN_NULLCHECK #undef PRN_NULLCHECK
} }
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
#endif #endif
typedef enum { typedef enum
{
CONN_NOT_CONNECTED, /* Connection has not been established */ CONN_NOT_CONNECTED, /* Connection has not been established */
CONN_CONNECTED, /* Connection is up and has been established */ CONN_CONNECTED, /* Connection is up and has been
* established */
CONN_DOWN, /* Connection is broken */ CONN_DOWN, /* Connection is broken */
CONN_EXECUTING /* the connection is currently executing a statement */ CONN_EXECUTING /* the connection is currently executing a
* statement */
} CONN_Status; } CONN_Status;
/* These errors have general sql error state */ /* These errors have general sql error state */
...@@ -122,7 +125,8 @@ typedef struct _StartupPacket ...@@ -122,7 +125,8 @@ typedef struct _StartupPacket
/* Structure to hold all the connection attributes for a specific /* Structure to hold all the connection attributes for a specific
connection (used for both registry and file, DSN and DRIVER) connection (used for both registry and file, DSN and DRIVER)
*/ */
typedef struct { typedef struct
{
char dsn[MEDIUM_REGISTRY_LEN]; char dsn[MEDIUM_REGISTRY_LEN];
char desc[MEDIUM_REGISTRY_LEN]; char desc[MEDIUM_REGISTRY_LEN];
char driver[MEDIUM_REGISTRY_LEN]; char driver[MEDIUM_REGISTRY_LEN];
...@@ -180,9 +184,10 @@ typedef struct { ...@@ -180,9 +184,10 @@ typedef struct {
#define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver)) #define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver))
/* This is used to store cached table information in the connection */ /* This is used to store cached table information in the connection */
struct col_info { struct col_info
{
QResultClass *result; QResultClass *result;
char name[MAX_TABLE_LEN+1]; char name[MAX_TABLE_LEN + 1];
}; };
/* Translation DLL entry points */ /* Translation DLL entry points */
...@@ -194,7 +199,7 @@ struct col_info { ...@@ -194,7 +199,7 @@ struct col_info {
#define HINSTANCE void * #define HINSTANCE void *
#endif #endif
typedef BOOL (FAR WINAPI *DataSourceToDriverProc) (UDWORD, typedef BOOL(FAR WINAPI * DataSourceToDriverProc) (UDWORD,
SWORD, SWORD,
PTR, PTR,
SDWORD, SDWORD,
...@@ -205,7 +210,7 @@ typedef BOOL (FAR WINAPI *DataSourceToDriverProc) (UDWORD, ...@@ -205,7 +210,7 @@ typedef BOOL (FAR WINAPI *DataSourceToDriverProc) (UDWORD,
SWORD, SWORD,
SWORD FAR *); SWORD FAR *);
typedef BOOL (FAR WINAPI *DriverToDataSourceProc) (UDWORD, typedef BOOL(FAR WINAPI * DriverToDataSourceProc) (UDWORD,
SWORD, SWORD,
PTR, PTR,
SDWORD, SDWORD,
...@@ -217,8 +222,10 @@ typedef BOOL (FAR WINAPI *DriverToDataSourceProc) (UDWORD, ...@@ -217,8 +222,10 @@ typedef BOOL (FAR WINAPI *DriverToDataSourceProc) (UDWORD,
SWORD FAR *); SWORD FAR *);
/******* The Connection handle ************/ /******* The Connection handle ************/
struct ConnectionClass_ { struct ConnectionClass_
HENV henv; /* environment this connection was created on */ {
HENV henv; /* environment this connection was created
* on */
StatementOptions stmtOptions; StatementOptions stmtOptions;
char *errormsg; char *errormsg;
int errornumber; int errornumber;
...@@ -234,9 +241,13 @@ struct ConnectionClass_ { ...@@ -234,9 +241,13 @@ struct ConnectionClass_ {
HINSTANCE translation_handle; HINSTANCE translation_handle;
DataSourceToDriverProc DataSourceToDriver; DataSourceToDriverProc DataSourceToDriver;
DriverToDataSourceProc DriverToDataSource; DriverToDataSourceProc DriverToDataSource;
char transact_status; /* Is a transaction is currently in progress */ char transact_status;/* Is a transaction is currently in
char errormsg_created; /* has an informative error msg been created? */ * progress */
char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL we're connected to - DJP 25-1-2001 */ char errormsg_created; /* has an informative error msg
* been created? */
char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL
* we're connected to -
* DJP 25-1-2001 */
float pg_version_number; float pg_version_number;
Int2 pg_version_major; Int2 pg_version_major;
Int2 pg_version_minor; Int2 pg_version_minor;
...@@ -259,24 +270,24 @@ struct ConnectionClass_ { ...@@ -259,24 +270,24 @@ struct ConnectionClass_ {
/* prototypes */ /* prototypes */
ConnectionClass *CC_Constructor(void); ConnectionClass *CC_Constructor(void);
char CC_Destructor(ConnectionClass *self); char CC_Destructor(ConnectionClass * self);
int CC_cursor_count(ConnectionClass *self); int CC_cursor_count(ConnectionClass * self);
char CC_cleanup(ConnectionClass *self); char CC_cleanup(ConnectionClass * self);
char CC_abort(ConnectionClass *self); char CC_abort(ConnectionClass * self);
int CC_set_translation (ConnectionClass *self); int CC_set_translation(ConnectionClass * self);
char CC_connect(ConnectionClass *self, char do_password); char CC_connect(ConnectionClass * self, char do_password);
char CC_add_statement(ConnectionClass *self, StatementClass *stmt); char CC_add_statement(ConnectionClass * self, StatementClass * stmt);
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt); char CC_remove_statement(ConnectionClass * self, StatementClass * stmt);
char CC_get_error(ConnectionClass *self, int *number, char **message); char CC_get_error(ConnectionClass * self, int *number, char **message);
QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi); QResultClass *CC_send_query(ConnectionClass * self, char *query, QueryInfo * qi);
void CC_clear_error(ConnectionClass *self); void CC_clear_error(ConnectionClass * self);
char *CC_create_errormsg(ConnectionClass *self); char *CC_create_errormsg(ConnectionClass * self);
int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs); int CC_send_function(ConnectionClass * conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG * argv, int nargs);
char CC_send_settings(ConnectionClass *self); char CC_send_settings(ConnectionClass * self);
void CC_lookup_lo(ConnectionClass *conn); void CC_lookup_lo(ConnectionClass * conn);
void CC_lookup_pg_version(ConnectionClass *conn); void CC_lookup_pg_version(ConnectionClass * conn);
void CC_initialize_pg_version(ConnectionClass *conn); void CC_initialize_pg_version(ConnectionClass * conn);
void CC_log_error(char *func, char *desc, ConnectionClass *self); void CC_log_error(char *func, char *desc, ConnectionClass * self);
#endif #endif
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#endif #endif
#ifndef SCHAR #ifndef SCHAR
typedef signed char SCHAR; typedef signed char SCHAR;
#endif #endif
#endif #endif
...@@ -65,47 +66,47 @@ extern GLOBAL_VALUES globals; ...@@ -65,47 +66,47 @@ extern GLOBAL_VALUES globals;
*/ */
char *mapFuncs[][2] = { char *mapFuncs[][2] = {
/* { "ASCII", "ascii" }, */ /* { "ASCII", "ascii" }, */
{ "CHAR", "ichar" }, {"CHAR", "ichar"},
{ "CONCAT", "textcat" }, {"CONCAT", "textcat"},
/* { "DIFFERENCE", "difference" }, */ /* { "DIFFERENCE", "difference" }, */
/* { "INSERT", "insert" }, */ /* { "INSERT", "insert" }, */
{ "LCASE", "lower" }, {"LCASE", "lower"},
{ "LEFT", "ltrunc" }, {"LEFT", "ltrunc"},
{ "LOCATE", "strpos" }, {"LOCATE", "strpos"},
{ "LENGTH", "char_length"}, {"LENGTH", "char_length"},
/* { "LTRIM", "ltrim" }, */ /* { "LTRIM", "ltrim" }, */
{ "RIGHT", "rtrunc" }, {"RIGHT", "rtrunc"},
/* { "REPEAT", "repeat" }, */ /* { "REPEAT", "repeat" }, */
/* { "REPLACE", "replace" }, */ /* { "REPLACE", "replace" }, */
/* { "RTRIM", "rtrim" }, */ /* { "RTRIM", "rtrim" }, */
/* { "SOUNDEX", "soundex" }, */ /* { "SOUNDEX", "soundex" }, */
{ "SUBSTRING", "substr" }, {"SUBSTRING", "substr"},
{ "UCASE", "upper" }, {"UCASE", "upper"},
/* { "ABS", "abs" }, */ /* { "ABS", "abs" }, */
/* { "ACOS", "acos" }, */ /* { "ACOS", "acos" }, */
/* { "ASIN", "asin" }, */ /* { "ASIN", "asin" }, */
/* { "ATAN", "atan" }, */ /* { "ATAN", "atan" }, */
/* { "ATAN2", "atan2" }, */ /* { "ATAN2", "atan2" }, */
{ "CEILING", "ceil" }, {"CEILING", "ceil"},
/* { "COS", "cos" }, */ /* { "COS", "cos" }, */
/* { "COT", "cot" }, */ /* { "COT", "cot" }, */
/* { "DEGREES", "degrees" }, */ /* { "DEGREES", "degrees" }, */
/* { "EXP", "exp" }, */ /* { "EXP", "exp" }, */
/* { "FLOOR", "floor" }, */ /* { "FLOOR", "floor" }, */
{ "LOG", "ln" }, {"LOG", "ln"},
{ "LOG10", "log" }, {"LOG10", "log"},
/* { "MOD", "mod" }, */ /* { "MOD", "mod" }, */
/* { "PI", "pi" }, */ /* { "PI", "pi" }, */
{ "POWER", "pow" }, {"POWER", "pow"},
/* { "RADIANS", "radians" }, */ /* { "RADIANS", "radians" }, */
{ "RAND", "random" }, {"RAND", "random"},
/* { "ROUND", "round" }, */ /* { "ROUND", "round" }, */
/* { "SIGN", "sign" }, */ /* { "SIGN", "sign" }, */
/* { "SIN", "sin" }, */ /* { "SIN", "sin" }, */
/* { "SQRT", "sqrt" }, */ /* { "SQRT", "sqrt" }, */
/* { "TAN", "tan" }, */ /* { "TAN", "tan" }, */
{ "TRUNCATE", "trunc" }, {"TRUNCATE", "trunc"},
/* { "CURDATE", "curdate" }, */ /* { "CURDATE", "curdate" }, */
/* { "CURTIME", "curtime" }, */ /* { "CURTIME", "curtime" }, */
...@@ -124,9 +125,9 @@ char *mapFuncs[][2] = { ...@@ -124,9 +125,9 @@ char *mapFuncs[][2] = {
/* { "YEAR", "year" }, */ /* { "YEAR", "year" }, */
/* { "DATABASE", "database" }, */ /* { "DATABASE", "database" }, */
{ "IFNULL", "coalesce" }, {"IFNULL", "coalesce"},
{ "USER", "odbc_user" }, {"USER", "odbc_user"},
{ 0, 0 } {0, 0}
}; };
char *mapFunction(char *func); char *mapFunction(char *func);
...@@ -153,38 +154,43 @@ char *conv_to_octal(unsigned char val); ...@@ -153,38 +154,43 @@ char *conv_to_octal(unsigned char val);
/* This is called by SQLFetch() */ /* This is called by SQLFetch() */
int int
copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col) copy_and_convert_field_bindinfo(StatementClass * stmt, Int4 field_type, void *value, int col)
{ {
BindInfoClass *bic = &(stmt->bindings[col]); BindInfoClass *bic = &(stmt->bindings[col]);
return copy_and_convert_field(stmt, field_type, value, (Int2)bic->returntype, (PTR)bic->buffer, return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) bic->buffer,
(SDWORD)bic->buflen, (SDWORD *)bic->used); (SDWORD) bic->buflen, (SDWORD *) bic->used);
} }
/* This is called by SQLGetData() */ /* This is called by SQLGetData() */
int int
copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType, copy_and_convert_field(StatementClass * stmt, Int4 field_type, void *value, Int2 fCType,
PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue) PTR rgbValue, SDWORD cbValueMax, SDWORD * pcbValue)
{ {
Int4 len = 0, copy_len = 0; Int4 len = 0,
copy_len = 0;
SIMPLE_TIME st; SIMPLE_TIME st;
time_t t = time(NULL); time_t t = time(NULL);
struct tm *tim; struct tm *tim;
int pcbValueOffset, rgbValueOffset; int pcbValueOffset,
char *rgbValueBindRow, *ptr; rgbValueOffset;
char *rgbValueBindRow,
*ptr;
int bind_row = stmt->bind_row; int bind_row = stmt->bind_row;
int bind_size = stmt->options.bind_size; int bind_size = stmt->options.bind_size;
int result = COPY_OK; int result = COPY_OK;
char tempBuf[TEXT_FIELD_SIZE+5]; char tempBuf[TEXT_FIELD_SIZE + 5];
/* rgbValueOffset is *ONLY* for character and binary data */ /* rgbValueOffset is *ONLY* for character and binary data */
/* pcbValueOffset is for computing any pcbValue location */ /* pcbValueOffset is for computing any pcbValue location */
if (bind_size > 0) { if (bind_size > 0)
{
pcbValueOffset = rgbValueOffset = (bind_size * bind_row); pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
} }
else { else
{
pcbValueOffset = bind_row * sizeof(SDWORD); pcbValueOffset = bind_row * sizeof(SDWORD);
rgbValueOffset = bind_row * cbValueMax; rgbValueOffset = bind_row * cbValueMax;
...@@ -199,21 +205,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -199,21 +205,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
st.d = tim->tm_mday; st.d = tim->tm_mday;
st.y = tim->tm_year + 1900; st.y = tim->tm_year + 1900;
mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value==NULL)?"<NULL>":value, cbValueMax); mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "<NULL>" : value, cbValueMax);
if ( ! value) { if (!value)
{
/* handle a null just by returning SQL_NULL_DATA in pcbValue, */ /* handle a null just by returning SQL_NULL_DATA in pcbValue, */
/* and doing nothing to the buffer. */ /* and doing nothing to the buffer. */
if(pcbValue) { if (pcbValue)
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA; *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
}
return COPY_OK; return COPY_OK;
} }
if (stmt->hdbc->DataSourceToDriver != NULL) { if (stmt->hdbc->DataSourceToDriver != NULL)
int length = strlen (value); {
stmt->hdbc->DataSourceToDriver (stmt->hdbc->translation_option, int length = strlen(value);
stmt->hdbc->DataSourceToDriver(stmt->hdbc->translation_option,
SQL_CHAR, SQL_CHAR,
value, length, value, length,
value, length, NULL, value, length, NULL,
...@@ -228,8 +236,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -228,8 +236,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
NOTE: Conversions from PG char/varchar of a date/time/timestamp NOTE: Conversions from PG char/varchar of a date/time/timestamp
value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*********************************************************************/ *********************************************************************/
switch(field_type) { 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: case PG_TYPE_DATE:
sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d); sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
break; break;
...@@ -241,10 +254,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -241,10 +254,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: case PG_TYPE_TIMESTAMP:
if (strnicmp(value, "invalid", 7) != 0) { 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); 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 */ }
else
{ /* The timestamp is invalid so set
* something conspicuous, like the epoch */
t = 0; t = 0;
tim = localtime(&t); tim = localtime(&t);
st.m = tim->tm_mon + 1; st.m = tim->tm_mon + 1;
...@@ -256,8 +273,10 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -256,8 +273,10 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
} }
break; break;
case PG_TYPE_BOOL: { /* change T/F to 1/0 */ case PG_TYPE_BOOL:
{ /* change T/F to 1/0 */
char *s = (char *) value; char *s = (char *) value;
if (s[0] == 'T' || s[0] == 't') if (s[0] == 'T' || s[0] == 't')
s[0] = '1'; s[0] = '1';
else else
...@@ -266,11 +285,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -266,11 +285,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
break; break;
/* This is for internal use by SQLStatistics() */ /* This is for internal use by SQLStatistics() */
case PG_TYPE_INT2VECTOR: { case PG_TYPE_INT2VECTOR:
int nval, i; {
int nval,
i;
char *vp; char *vp;
/* this is an array of eight integers */ /* this is an array of eight integers */
short *short_array = (short *) ( (char *) rgbValue + rgbValueOffset); short *short_array = (short *) ((char *) rgbValue + rgbValueOffset);
len = 16; len = 16;
vp = value; vp = value;
...@@ -283,17 +305,17 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -283,17 +305,17 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
nval++; nval++;
/* skip the current token */ /* skip the current token */
while ((*vp != '\0') && (! isspace((unsigned char) *vp))) vp++; while ((*vp != '\0') && (!isspace((unsigned char) *vp)))
vp++;
/* and skip the space to the next token */ /* and skip the space to the next token */
while ((*vp != '\0') && (isspace((unsigned char) *vp))) vp++; while ((*vp != '\0') && (isspace((unsigned char) *vp)))
vp++;
if (*vp == '\0') if (*vp == '\0')
break; break;
} }
for (i = nval; i < 8; i++) for (i = nval; i < 8; i++)
{
short_array[i] = 0; short_array[i] = 0;
}
#if 0 #if 0
sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd", sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
...@@ -308,25 +330,31 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -308,25 +330,31 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
#endif #endif
/* There is no corresponding fCType for this. */ /* There is no corresponding fCType for this. */
if(pcbValue) if (pcbValue)
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len; *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len;
return COPY_OK; /* dont go any further or the data will be trashed */ return COPY_OK; /* dont go any further or the data will be
* trashed */
} }
/* This is a large object OID, which is used to store LONGVARBINARY objects. */ /*
* This is a large object OID, which is used to store
* LONGVARBINARY objects.
*/
case PG_TYPE_LO: case PG_TYPE_LO:
return convert_lo( stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset)); return convert_lo(stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset));
default: default:
if (field_type == stmt->hdbc->lobj_type) /* hack until permanent type available */ if (field_type == stmt->hdbc->lobj_type) /* hack until permanent
return convert_lo( stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset)); * type available */
return convert_lo(stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset));
} }
/* Change default into something useable */ /* Change default into something useable */
if (fCType == SQL_C_DEFAULT) { if (fCType == SQL_C_DEFAULT)
{
fCType = pgtype_to_ctype(stmt, field_type); fCType = pgtype_to_ctype(stmt, field_type);
mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType); mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
...@@ -335,12 +363,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -335,12 +363,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
rgbValueBindRow = (char *) rgbValue + rgbValueOffset; rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
if(fCType == SQL_C_CHAR) { if (fCType == SQL_C_CHAR)
{
/* Special character formatting as required */ /* Special character formatting as required */
/* These really should return error if cbValueMax is not big enough. */
switch(field_type) { /*
* These really should return error if cbValueMax is not big
* enough.
*/
switch (field_type)
{
case PG_TYPE_DATE: case PG_TYPE_DATE:
len = 10; len = 10;
if (cbValueMax > len) if (cbValueMax > len)
...@@ -364,23 +398,28 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -364,23 +398,28 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
case PG_TYPE_BOOL: case PG_TYPE_BOOL:
len = 1; len = 1;
if (cbValueMax > len) { if (cbValueMax > len)
{
strcpy(rgbValueBindRow, value); strcpy(rgbValueBindRow, value);
mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow); mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow);
} }
break; break;
/* Currently, data is SILENTLY TRUNCATED for BYTEA and character data /*
types if there is not enough room in cbValueMax because the driver * Currently, data is SILENTLY TRUNCATED for BYTEA and
can't handle multiple calls to SQLGetData for these, yet. Most likely, * character data types if there is not enough room in
the buffer passed in will be big enough to handle the maximum limit of * cbValueMax because the driver can't handle multiple
postgres, anyway. * calls to SQLGetData for these, yet. Most likely, the
* buffer passed in will be big enough to handle the
LongVarBinary types are handled correctly above, observing truncation * maximum limit of postgres, anyway.
and all that stuff since there is essentially no limit on the large *
object used to store those. * LongVarBinary types are handled correctly above, observing
* truncation and all that stuff since there is
* essentially no limit on the large object used to store
* those.
*/ */
case PG_TYPE_BYTEA: /* convert binary data to hex strings (i.e, 255 = "FF") */ case PG_TYPE_BYTEA:/* convert binary data to hex strings
* (i.e, 255 = "FF") */
len = convert_pgbinary_to_char(value, rgbValueBindRow, cbValueMax); len = convert_pgbinary_to_char(value, rgbValueBindRow, cbValueMax);
/***** THIS IS NOT PROPERLY IMPLEMENTED *****/ /***** THIS IS NOT PROPERLY IMPLEMENTED *****/
...@@ -393,10 +432,12 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -393,10 +432,12 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
mylog("DEFAULT: len = %d, ptr = '%s'\n", len, ptr); mylog("DEFAULT: len = %d, ptr = '%s'\n", len, ptr);
if (stmt->current_col >= 0) { if (stmt->current_col >= 0)
{
if (stmt->bindings[stmt->current_col].data_left == 0) if (stmt->bindings[stmt->current_col].data_left == 0)
return COPY_NO_DATA_FOUND; return COPY_NO_DATA_FOUND;
else if (stmt->bindings[stmt->current_col].data_left > 0) { else if (stmt->bindings[stmt->current_col].data_left > 0)
{
ptr += len - stmt->bindings[stmt->current_col].data_left; ptr += len - stmt->bindings[stmt->current_col].data_left;
len = stmt->bindings[stmt->current_col].data_left; len = stmt->bindings[stmt->current_col].data_left;
} }
...@@ -404,21 +445,24 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -404,21 +445,24 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
stmt->bindings[stmt->current_col].data_left = strlen(ptr); stmt->bindings[stmt->current_col].data_left = strlen(ptr);
} }
if (cbValueMax > 0) { if (cbValueMax > 0)
{
copy_len = (len >= cbValueMax) ? cbValueMax -1 : len; copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
/* Copy the data */ /* Copy the data */
strncpy_null(rgbValueBindRow, ptr, copy_len + 1); strncpy_null(rgbValueBindRow, ptr, copy_len + 1);
/* Adjust data_left for next time */ /* Adjust data_left for next time */
if (stmt->current_col >= 0) { if (stmt->current_col >= 0)
stmt->bindings[stmt->current_col].data_left -= copy_len; stmt->bindings[stmt->current_col].data_left -= copy_len;
} }
}
/* Finally, check for truncation so that proper status can be returned */ /*
if ( len >= cbValueMax) * Finally, check for truncation so that proper status can
* be returned
*/
if (len >= cbValueMax)
result = COPY_RESULT_TRUNCATED; result = COPY_RESULT_TRUNCATED;
...@@ -427,25 +471,29 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -427,25 +471,29 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
} }
} else { }
else
{
/* for SQL_C_CHAR, it's probably ok to leave currency symbols in. But /*
to convert to numeric types, it is necessary to get rid of those. * for SQL_C_CHAR, it's probably ok to leave currency symbols in.
* But to convert to numeric types, it is necessary to get rid of
* those.
*/ */
if (field_type == PG_TYPE_MONEY) if (field_type == PG_TYPE_MONEY)
convert_money(value); convert_money(value);
switch(fCType) { switch (fCType)
{
case SQL_C_DATE: case SQL_C_DATE:
len = 6; len = 6;
{ {
DATE_STRUCT *ds; DATE_STRUCT *ds;
if (bind_size > 0) { if (bind_size > 0)
ds = (DATE_STRUCT *) ((char *) rgbValue + (bind_row * bind_size)); ds = (DATE_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
} else { else
ds = (DATE_STRUCT *) rgbValue + bind_row; ds = (DATE_STRUCT *) rgbValue + bind_row;
}
ds->year = st.y; ds->year = st.y;
ds->month = st.m; ds->month = st.m;
ds->day = st.d; ds->day = st.d;
...@@ -457,11 +505,10 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -457,11 +505,10 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
{ {
TIME_STRUCT *ts; TIME_STRUCT *ts;
if (bind_size > 0) { if (bind_size > 0)
ts = (TIME_STRUCT *) ((char *) rgbValue + (bind_row * bind_size)); ts = (TIME_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
} else { else
ts = (TIME_STRUCT *) rgbValue + bind_row; ts = (TIME_STRUCT *) rgbValue + bind_row;
}
ts->hour = st.hh; ts->hour = st.hh;
ts->minute = st.mm; ts->minute = st.mm;
ts->second = st.ss; ts->second = st.ss;
...@@ -472,11 +519,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -472,11 +519,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
len = 16; len = 16;
{ {
TIMESTAMP_STRUCT *ts; TIMESTAMP_STRUCT *ts;
if (bind_size > 0) {
if (bind_size > 0)
ts = (TIMESTAMP_STRUCT *) ((char *) rgbValue + (bind_row * bind_size)); ts = (TIMESTAMP_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
} else { else
ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row; ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row;
}
ts->year = st.y; ts->year = st.y;
ts->month = st.m; ts->month = st.m;
ts->day = st.d; ts->day = st.d;
...@@ -489,87 +536,82 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -489,87 +536,82 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
case SQL_C_BIT: case SQL_C_BIT:
len = 1; len = 1;
if (bind_size > 0) { if (bind_size > 0)
*(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value); *(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value);
} else { else
*((UCHAR *)rgbValue + bind_row) = atoi(value); *((UCHAR *) rgbValue + bind_row) = atoi(value);
}
/* mylog("SQL_C_BIT: val = %d, cb = %d, rgb=%d\n", atoi(value), cbValueMax, *((UCHAR *)rgbValue)); */ /*
* mylog("SQL_C_BIT: val = %d, cb = %d, rgb=%d\n",
* atoi(value), cbValueMax, *((UCHAR *)rgbValue));
*/
break; break;
case SQL_C_STINYINT: case SQL_C_STINYINT:
case SQL_C_TINYINT: case SQL_C_TINYINT:
len = 1; len = 1;
if (bind_size > 0) { if (bind_size > 0)
*(SCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value); *(SCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value);
} else { else
*((SCHAR *) rgbValue + bind_row) = atoi(value); *((SCHAR *) rgbValue + bind_row) = atoi(value);
}
break; break;
case SQL_C_UTINYINT: case SQL_C_UTINYINT:
len = 1; len = 1;
if (bind_size > 0) { if (bind_size > 0)
*(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value); *(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value);
} else { else
*((UCHAR *) rgbValue + bind_row) = atoi(value); *((UCHAR *) rgbValue + bind_row) = atoi(value);
}
break; break;
case SQL_C_FLOAT: case SQL_C_FLOAT:
len = 4; len = 4;
if (bind_size > 0) { if (bind_size > 0)
*(SFLOAT *) ((char *) rgbValue + (bind_row * bind_size)) = (float) atof(value); *(SFLOAT *) ((char *) rgbValue + (bind_row * bind_size)) = (float) atof(value);
} else { else
*((SFLOAT *)rgbValue + bind_row) = (float) atof(value); *((SFLOAT *) rgbValue + bind_row) = (float) atof(value);
}
break; break;
case SQL_C_DOUBLE: case SQL_C_DOUBLE:
len = 8; len = 8;
if (bind_size > 0) { if (bind_size > 0)
*(SDOUBLE *) ((char *) rgbValue + (bind_row * bind_size)) = atof(value); *(SDOUBLE *) ((char *) rgbValue + (bind_row * bind_size)) = atof(value);
} else { else
*((SDOUBLE *)rgbValue + bind_row) = atof(value); *((SDOUBLE *) rgbValue + bind_row) = atof(value);
}
break; break;
case SQL_C_SSHORT: case SQL_C_SSHORT:
case SQL_C_SHORT: case SQL_C_SHORT:
len = 2; len = 2;
if (bind_size > 0) { if (bind_size > 0)
*(SWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value); *(SWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value);
} else { else
*((SWORD *)rgbValue + bind_row) = atoi(value); *((SWORD *) rgbValue + bind_row) = atoi(value);
}
break; break;
case SQL_C_USHORT: case SQL_C_USHORT:
len = 2; len = 2;
if (bind_size > 0) { if (bind_size > 0)
*(UWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value); *(UWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value);
} else { else
*((UWORD *)rgbValue + bind_row) = atoi(value); *((UWORD *) rgbValue + bind_row) = atoi(value);
}
break; break;
case SQL_C_SLONG: case SQL_C_SLONG:
case SQL_C_LONG: case SQL_C_LONG:
len = 4; len = 4;
if (bind_size > 0) { if (bind_size > 0)
*(SDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(value); *(SDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(value);
} else { else
*((SDWORD *)rgbValue + bind_row) = atol(value); *((SDWORD *) rgbValue + bind_row) = atol(value);
}
break; break;
case SQL_C_ULONG: case SQL_C_ULONG:
len = 4; len = 4;
if (bind_size > 0) { if (bind_size > 0)
*(UDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(value); *(UDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(value);
} else { else
*((UDWORD *)rgbValue + bind_row) = atol(value); *((UDWORD *) rgbValue + bind_row) = atol(value);
}
break; break;
case SQL_C_BINARY: case SQL_C_BINARY:
...@@ -580,14 +622,19 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -580,14 +622,19 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
len = convert_from_pgbinary(value, tempBuf, sizeof(tempBuf)); len = convert_from_pgbinary(value, tempBuf, sizeof(tempBuf));
ptr = tempBuf; ptr = tempBuf;
if (stmt->current_col >= 0) { if (stmt->current_col >= 0)
{
/* No more data left for this column */ /* No more data left for this column */
if (stmt->bindings[stmt->current_col].data_left == 0) if (stmt->bindings[stmt->current_col].data_left == 0)
return COPY_NO_DATA_FOUND; return COPY_NO_DATA_FOUND;
/* Second (or more) call to SQLGetData so move the pointer */ /*
else if (stmt->bindings[stmt->current_col].data_left > 0) { * Second (or more) call to SQLGetData so move the
* pointer
*/
else if (stmt->bindings[stmt->current_col].data_left > 0)
{
ptr += len - stmt->bindings[stmt->current_col].data_left; ptr += len - stmt->bindings[stmt->current_col].data_left;
len = stmt->bindings[stmt->current_col].data_left; len = stmt->bindings[stmt->current_col].data_left;
} }
...@@ -598,20 +645,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -598,20 +645,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
} }
if (cbValueMax > 0) { if (cbValueMax > 0)
{
copy_len = (len > cbValueMax) ? cbValueMax : len; copy_len = (len > cbValueMax) ? cbValueMax : len;
/* Copy the data */ /* Copy the data */
memcpy(rgbValueBindRow, ptr, copy_len); memcpy(rgbValueBindRow, ptr, copy_len);
/* Adjust data_left for next time */ /* Adjust data_left for next time */
if (stmt->current_col >= 0) { if (stmt->current_col >= 0)
stmt->bindings[stmt->current_col].data_left -= copy_len; stmt->bindings[stmt->current_col].data_left -= copy_len;
} }
}
/* Finally, check for truncation so that proper status can be returned */ /*
if ( len > cbValueMax) * Finally, check for truncation so that proper status can
* be returned
*/
if (len > cbValueMax)
result = COPY_RESULT_TRUNCATED; result = COPY_RESULT_TRUNCATED;
mylog("SQL_C_BINARY: len = %d, copy_len = %d\n", len, copy_len); mylog("SQL_C_BINARY: len = %d, copy_len = %d\n", len, copy_len);
...@@ -623,9 +673,8 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -623,9 +673,8 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
} }
/* store the length of what was copied, if there's a place for it */ /* store the length of what was copied, if there's a place for it */
if(pcbValue) { if (pcbValue)
*(SDWORD *) ((char *)pcbValue + pcbValueOffset) = len; *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len;
}
return result; return result;
...@@ -637,26 +686,34 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -637,26 +686,34 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
This function no longer does any dynamic memory allocation! This function no longer does any dynamic memory allocation!
*/ */
int int
copy_statement_with_parameters(StatementClass *stmt) copy_statement_with_parameters(StatementClass * stmt)
{ {
static char *func="copy_statement_with_parameters"; static char *func = "copy_statement_with_parameters";
unsigned int opos, npos, oldstmtlen; unsigned int opos,
char param_string[128], tmp[256], cbuf[TEXT_FIELD_SIZE+5]; npos,
int param_number; oldstmtlen;
Int2 param_ctype, param_sqltype; char param_string[128],
char *old_statement = stmt->statement; tmp[256],
char *new_statement = stmt->stmt_with_params; cbuf[TEXT_FIELD_SIZE + 5];
SIMPLE_TIME st; int param_number;
time_t t = time(NULL); Int2 param_ctype,
struct tm *tim; param_sqltype;
SDWORD used; char *old_statement = stmt->statement;
char *buffer, *buf; char *new_statement = stmt->stmt_with_params;
char in_quote = FALSE; SIMPLE_TIME st;
Oid lobj_oid; time_t t = time(NULL);
int lobj_fd, retval; struct tm *tim;
SDWORD used;
char *buffer,
if ( ! old_statement) { *buf;
char in_quote = FALSE;
Oid lobj_oid;
int lobj_fd,
retval;
if (!old_statement)
{
SC_log_error(func, "No statement string", stmt); SC_log_error(func, "No statement string", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -670,15 +727,17 @@ int lobj_fd, retval; ...@@ -670,15 +727,17 @@ int lobj_fd, retval;
st.y = tim->tm_year + 1900; st.y = tim->tm_year + 1900;
/* If the application hasn't set a cursor name, then generate one */ /* If the application hasn't set a cursor name, then generate one */
if ( stmt->cursor_name[0] == '\0') if (stmt->cursor_name[0] == '\0')
sprintf(stmt->cursor_name, "SQL_CUR%p", stmt); sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
/* For selects, prepend a declare cursor to the statement */ /* For selects, prepend a declare cursor to the statement */
if (stmt->statement_type == STMT_TYPE_SELECT && globals.use_declarefetch) { if (stmt->statement_type == STMT_TYPE_SELECT && globals.use_declarefetch)
{
sprintf(new_statement, "declare %s cursor for ", stmt->cursor_name); sprintf(new_statement, "declare %s cursor for ", stmt->cursor_name);
npos = strlen(new_statement); npos = strlen(new_statement);
} }
else { else
{
new_statement[0] = '0'; new_statement[0] = '0';
npos = 0; npos = 0;
} }
...@@ -687,31 +746,37 @@ int lobj_fd, retval; ...@@ -687,31 +746,37 @@ int lobj_fd, retval;
oldstmtlen = strlen(old_statement); oldstmtlen = strlen(old_statement);
for (opos = 0; opos < oldstmtlen; opos++) { for (opos = 0; opos < oldstmtlen; opos++)
{
/* Squeeze carriage-return/linefeed pairs to linefeed only */ /* Squeeze carriage-return/linefeed pairs to linefeed only */
if (old_statement[opos] == '\r' && opos+1 < oldstmtlen && if (old_statement[opos] == '\r' && opos + 1 < oldstmtlen &&
old_statement[opos+1] == '\n') { old_statement[opos + 1] == '\n')
continue; continue;
}
/* Handle literals (date, time, timestamp) and ODBC scalar functions */ /*
else if (old_statement[opos] == '{') { * Handle literals (date, time, timestamp) and ODBC scalar
* functions
*/
else if (old_statement[opos] == '{')
{
char *esc; char *esc;
char *begin = &old_statement[opos + 1]; char *begin = &old_statement[opos + 1];
char *end = strchr(begin, '}'); char *end = strchr(begin, '}');
if ( ! end) if (!end)
continue; continue;
*end = '\0'; *end = '\0';
esc = convert_escape(begin); esc = convert_escape(begin);
if (esc) { if (esc)
{
memcpy(&new_statement[npos], esc, strlen(esc)); memcpy(&new_statement[npos], esc, strlen(esc));
npos += strlen(esc); npos += strlen(esc);
} }
else { /* it's not a valid literal so just copy */ else
{ /* it's not a valid literal so just copy */
*end = '}'; *end = '}';
new_statement[npos++] = old_statement[opos]; new_statement[npos++] = old_statement[opos];
continue; continue;
...@@ -724,12 +789,15 @@ int lobj_fd, retval; ...@@ -724,12 +789,15 @@ int lobj_fd, retval;
continue; 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 if needed. * Can you have parameter markers inside of quotes? I dont think
* so. All the queries I've seen expect the driver to put quotes
* if needed.
*/ */
else if (old_statement[opos] == '?' && !in_quote) else if (old_statement[opos] == '?' && !in_quote)
; /* ok */ ; /* ok */
else { else
{
if (old_statement[opos] == '\'') if (old_statement[opos] == '\'')
in_quote = (in_quote ? FALSE : TRUE); in_quote = (in_quote ? FALSE : TRUE);
...@@ -749,26 +817,31 @@ int lobj_fd, retval; ...@@ -749,26 +817,31 @@ int lobj_fd, retval;
break; break;
/* Assign correct buffers based on data at exec param or not */ /* Assign correct buffers based on data at exec param or not */
if ( stmt->parameters[param_number].data_at_exec) { if (stmt->parameters[param_number].data_at_exec)
{
used = stmt->parameters[param_number].EXEC_used ? *stmt->parameters[param_number].EXEC_used : SQL_NTS; used = stmt->parameters[param_number].EXEC_used ? *stmt->parameters[param_number].EXEC_used : SQL_NTS;
buffer = stmt->parameters[param_number].EXEC_buffer; buffer = stmt->parameters[param_number].EXEC_buffer;
} }
else { else
{
used = stmt->parameters[param_number].used ? *stmt->parameters[param_number].used : SQL_NTS; used = stmt->parameters[param_number].used ? *stmt->parameters[param_number].used : SQL_NTS;
buffer = stmt->parameters[param_number].buffer; buffer = stmt->parameters[param_number].buffer;
} }
/* Handle NULL parameter data */ /* Handle NULL parameter data */
if (used == SQL_NULL_DATA) { if (used == SQL_NULL_DATA)
{
strcpy(&new_statement[npos], "NULL"); strcpy(&new_statement[npos], "NULL");
npos += 4; npos += 4;
continue; continue;
} }
/* If no buffer, and it's not null, then what the hell is it? /*
Just leave it alone then. * If no buffer, and it's not null, then what the hell is it? Just
* leave it alone then.
*/ */
if ( ! buffer) { if (!buffer)
{
new_statement[npos++] = '?'; new_statement[npos++] = '?';
continue; continue;
} }
...@@ -779,7 +852,7 @@ int lobj_fd, retval; ...@@ -779,7 +852,7 @@ int lobj_fd, retval;
mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n", param_ctype, param_sqltype); mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n", param_ctype, param_sqltype);
/* replace DEFAULT with something we can use */ /* replace DEFAULT with something we can use */
if(param_ctype == SQL_C_DEFAULT) if (param_ctype == SQL_C_DEFAULT)
param_ctype = sqltype_to_default_ctype(param_sqltype); param_ctype = sqltype_to_default_ctype(param_sqltype);
buf = NULL; buf = NULL;
...@@ -788,7 +861,8 @@ int lobj_fd, retval; ...@@ -788,7 +861,8 @@ int lobj_fd, retval;
/* Convert input C type to a neutral format */ /* Convert input C type to a neutral format */
switch(param_ctype) { switch (param_ctype)
{
case SQL_C_BINARY: case SQL_C_BINARY:
case SQL_C_CHAR: case SQL_C_CHAR:
buf = buffer; buf = buffer;
...@@ -837,15 +911,18 @@ int lobj_fd, retval; ...@@ -837,15 +911,18 @@ int lobj_fd, retval;
*((UCHAR *) buffer)); *((UCHAR *) buffer));
break; break;
case SQL_C_BIT: { case SQL_C_BIT:
{
int i = *((UCHAR *) buffer); int i = *((UCHAR *) buffer);
sprintf(param_string, "%d", i ? 1 : 0); sprintf(param_string, "%d", i ? 1 : 0);
break; break;
} }
case SQL_C_DATE: { case SQL_C_DATE:
{
DATE_STRUCT *ds = (DATE_STRUCT *) buffer; DATE_STRUCT *ds = (DATE_STRUCT *) buffer;
st.m = ds->month; st.m = ds->month;
st.d = ds->day; st.d = ds->day;
st.y = ds->year; st.y = ds->year;
...@@ -853,8 +930,10 @@ int lobj_fd, retval; ...@@ -853,8 +930,10 @@ int lobj_fd, retval;
break; break;
} }
case SQL_C_TIME: { case SQL_C_TIME:
{
TIME_STRUCT *ts = (TIME_STRUCT *) buffer; TIME_STRUCT *ts = (TIME_STRUCT *) buffer;
st.hh = ts->hour; st.hh = ts->hour;
st.mm = ts->minute; st.mm = ts->minute;
st.ss = ts->second; st.ss = ts->second;
...@@ -862,8 +941,10 @@ int lobj_fd, retval; ...@@ -862,8 +941,10 @@ int lobj_fd, retval;
break; break;
} }
case SQL_C_TIMESTAMP: { case SQL_C_TIMESTAMP:
{
TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer; TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer;
st.m = tss->month; st.m = tss->month;
st.d = tss->day; st.d = tss->day;
st.y = tss->year; st.y = tss->year;
...@@ -885,11 +966,13 @@ int lobj_fd, retval; ...@@ -885,11 +966,13 @@ int lobj_fd, retval;
return SQL_ERROR; return SQL_ERROR;
} }
/* Now that the input data is in a neutral format, convert it to /*
the desired output format (sqltype) * Now that the input data is in a neutral format, convert it to
* the desired output format (sqltype)
*/ */
switch(param_sqltype) { switch (param_sqltype)
{
case SQL_CHAR: case SQL_CHAR:
case SQL_VARCHAR: case SQL_VARCHAR:
case SQL_LONGVARCHAR: case SQL_LONGVARCHAR:
...@@ -897,19 +980,22 @@ int lobj_fd, retval; ...@@ -897,19 +980,22 @@ int lobj_fd, retval;
new_statement[npos++] = '\''; /* Open Quote */ new_statement[npos++] = '\''; /* Open Quote */
/* it was a SQL_C_CHAR */ /* it was a SQL_C_CHAR */
if (buf) { if (buf)
{
convert_special_chars(buf, &new_statement[npos], used); convert_special_chars(buf, &new_statement[npos], used);
npos += strlen(&new_statement[npos]); npos += strlen(&new_statement[npos]);
} }
/* it was a numeric type */ /* it was a numeric type */
else if (param_string[0] != '\0') { else if (param_string[0] != '\0')
{
strcpy(&new_statement[npos], param_string); strcpy(&new_statement[npos], param_string);
npos += strlen(param_string); npos += strlen(param_string);
} }
/* it was date,time,timestamp -- use m,d,y,hh,mm,ss */ /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */
else { else
{
sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d", sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
st.y, st.m, st.d, st.hh, st.mm, st.ss); st.y, st.m, st.d, st.hh, st.mm, st.ss);
...@@ -922,7 +1008,8 @@ int lobj_fd, retval; ...@@ -922,7 +1008,8 @@ int lobj_fd, retval;
break; break;
case SQL_DATE: case SQL_DATE:
if (buf) { /* copy char data to time */ if (buf)
{ /* copy char data to time */
my_strcpy(cbuf, sizeof(cbuf), buf, used); my_strcpy(cbuf, sizeof(cbuf), buf, used);
parse_datetime(cbuf, &st); parse_datetime(cbuf, &st);
} }
...@@ -934,7 +1021,8 @@ int lobj_fd, retval; ...@@ -934,7 +1021,8 @@ int lobj_fd, retval;
break; break;
case SQL_TIME: case SQL_TIME:
if (buf) { /* copy char data to time */ if (buf)
{ /* copy char data to time */
my_strcpy(cbuf, sizeof(cbuf), buf, used); my_strcpy(cbuf, sizeof(cbuf), buf, used);
parse_datetime(cbuf, &st); parse_datetime(cbuf, &st);
} }
...@@ -947,7 +1035,8 @@ int lobj_fd, retval; ...@@ -947,7 +1035,8 @@ int lobj_fd, retval;
case SQL_TIMESTAMP: case SQL_TIMESTAMP:
if (buf) { if (buf)
{
my_strcpy(cbuf, sizeof(cbuf), buf, used); my_strcpy(cbuf, sizeof(cbuf), buf, used);
parse_datetime(cbuf, &st); parse_datetime(cbuf, &st);
} }
...@@ -961,7 +1050,8 @@ int lobj_fd, retval; ...@@ -961,7 +1050,8 @@ int lobj_fd, retval;
break; break;
case SQL_BINARY: case SQL_BINARY:
case SQL_VARBINARY: /* non-ascii characters should be converted to octal */ case SQL_VARBINARY:/* non-ascii characters should be
* converted to octal */
new_statement[npos++] = '\''; /* Open Quote */ new_statement[npos++] = '\''; /* Open Quote */
mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used); mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
...@@ -974,20 +1064,24 @@ int lobj_fd, retval; ...@@ -974,20 +1064,24 @@ int lobj_fd, retval;
case SQL_LONGVARBINARY: case SQL_LONGVARBINARY:
if ( stmt->parameters[param_number].data_at_exec) { if (stmt->parameters[param_number].data_at_exec)
{
lobj_oid = stmt->parameters[param_number].lobj_oid; lobj_oid = stmt->parameters[param_number].lobj_oid;
} }
else { else
{
/* begin transaction if needed */ /* begin transaction if needed */
if(!CC_is_in_trans(stmt->hdbc)) { if (!CC_is_in_trans(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "BEGIN", NULL); res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not begin (in-line) a transaction"; stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -995,7 +1089,8 @@ int lobj_fd, retval; ...@@ -995,7 +1089,8 @@ int lobj_fd, retval;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not begin (in-line) a transaction"; stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1007,7 +1102,8 @@ int lobj_fd, retval; ...@@ -1007,7 +1102,8 @@ int lobj_fd, retval;
/* store the oid */ /* store the oid */
lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
if (lobj_oid == 0) { if (lobj_oid == 0)
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt create (in-line) large object."; stmt->errormsg = "Couldnt create (in-line) large object.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1016,7 +1112,8 @@ int lobj_fd, retval; ...@@ -1016,7 +1112,8 @@ int lobj_fd, retval;
/* store the fd */ /* store the fd */
lobj_fd = lo_open(stmt->hdbc, lobj_oid, INV_WRITE); lobj_fd = lo_open(stmt->hdbc, lobj_oid, INV_WRITE);
if ( lobj_fd < 0) { if (lobj_fd < 0)
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt open (in-line) large object for writing."; stmt->errormsg = "Couldnt open (in-line) large object for writing.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1028,12 +1125,14 @@ int lobj_fd, retval; ...@@ -1028,12 +1125,14 @@ int lobj_fd, retval;
lo_close(stmt->hdbc, lobj_fd); lo_close(stmt->hdbc, lobj_fd);
/* commit transaction if needed */ /* commit transaction if needed */
if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "COMMIT", NULL); res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1041,7 +1140,8 @@ int lobj_fd, retval; ...@@ -1041,7 +1140,8 @@ int lobj_fd, retval;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1052,8 +1152,10 @@ int lobj_fd, retval; ...@@ -1052,8 +1152,10 @@ int lobj_fd, retval;
} }
} }
/* the oid of the large object -- just put that in for the /*
parameter marker -- the data has already been sent to the large object * the oid of the large object -- just put that in for the
* parameter marker -- the data has already been sent to
* the large object
*/ */
sprintf(param_string, "'%d'", lobj_oid); sprintf(param_string, "'%d'", lobj_oid);
strcpy(&new_statement[npos], param_string); strcpy(&new_statement[npos], param_string);
...@@ -1061,18 +1163,23 @@ int lobj_fd, retval; ...@@ -1061,18 +1163,23 @@ int lobj_fd, retval;
break; break;
/* because of no conversion operator for bool and int4, SQL_BIT */ /*
* because of no conversion operator for bool and int4,
* SQL_BIT
*/
/* must be quoted (0 or 1 is ok to use inside the quotes) */ /* must be quoted (0 or 1 is ok to use inside the quotes) */
default: /* a numeric type or SQL_BIT */ default: /* a numeric type or SQL_BIT */
if (param_sqltype == SQL_BIT) if (param_sqltype == SQL_BIT)
new_statement[npos++] = '\''; /* Open Quote */ new_statement[npos++] = '\''; /* Open Quote */
if (buf) { if (buf)
{
my_strcpy(&new_statement[npos], sizeof(stmt->stmt_with_params) - npos, buf, used); my_strcpy(&new_statement[npos], sizeof(stmt->stmt_with_params) - npos, buf, used);
npos += strlen(&new_statement[npos]); npos += strlen(&new_statement[npos]);
} }
else { else
{
strcpy(&new_statement[npos], param_string); strcpy(&new_statement[npos], param_string);
npos += strlen(param_string); npos += strlen(param_string);
} }
...@@ -1090,9 +1197,11 @@ int lobj_fd, retval; ...@@ -1090,9 +1197,11 @@ int lobj_fd, retval;
new_statement[npos] = '\0'; new_statement[npos] = '\0';
if(stmt->hdbc->DriverToDataSource != NULL) { if (stmt->hdbc->DriverToDataSource != NULL)
int length = strlen (new_statement); {
stmt->hdbc->DriverToDataSource (stmt->hdbc->translation_option, int length = strlen(new_statement);
stmt->hdbc->DriverToDataSource(stmt->hdbc->translation_option,
SQL_CHAR, SQL_CHAR,
new_statement, length, new_statement, length,
new_statement, length, NULL, new_statement, length, NULL,
...@@ -1106,10 +1215,10 @@ int lobj_fd, retval; ...@@ -1106,10 +1215,10 @@ int lobj_fd, retval;
char * char *
mapFunction(char *func) mapFunction(char *func)
{ {
int i; int i;
for (i = 0; mapFuncs[i][0]; i++) for (i = 0; mapFuncs[i][0]; i++)
if ( ! stricmp(mapFuncs[i][0], func)) if (!stricmp(mapFuncs[i][0], func))
return mapFuncs[i][1]; return mapFuncs[i][1];
return NULL; return NULL;
...@@ -1121,34 +1230,40 @@ int i; ...@@ -1121,34 +1230,40 @@ int i;
char * char *
convert_escape(char *value) convert_escape(char *value)
{ {
static char escape[1024]; static char escape[1024];
char key[33]; char key[33];
/* Separate off the key, skipping leading and trailing whitespace */ /* Separate off the key, skipping leading and trailing whitespace */
while ((*value != '\0') && isspace((unsigned char) *value)) value++; while ((*value != '\0') && isspace((unsigned char) *value))
value++;
sscanf(value, "%32s", key); sscanf(value, "%32s", key);
while ((*value != '\0') && (! isspace((unsigned char) *value))) value++; while ((*value != '\0') && (!isspace((unsigned char) *value)))
while ((*value != '\0') && isspace((unsigned char) *value)) value++; value++;
while ((*value != '\0') && isspace((unsigned char) *value))
value++;
mylog("convert_escape: key='%s', val='%s'\n", key, value); mylog("convert_escape: key='%s', val='%s'\n", key, value);
if ( (strcmp(key, "d") == 0) || if ((strcmp(key, "d") == 0) ||
(strcmp(key, "t") == 0) || (strcmp(key, "t") == 0) ||
(strcmp(key, "ts") == 0)) { (strcmp(key, "ts") == 0))
{
/* Literal; return the escape part as-is */ /* Literal; return the escape part as-is */
strncpy(escape, value, sizeof(escape)-1); strncpy(escape, value, sizeof(escape) - 1);
} }
else if (strcmp(key, "fn") == 0) { else if (strcmp(key, "fn") == 0)
/* Function invocation {
* Separate off the func name,
* skipping trailing whitespace. /*
* Function invocation Separate off the func name, skipping
* trailing whitespace.
*/ */
char *funcEnd = value; char *funcEnd = value;
char svchar; char svchar;
char *mapFunc; char *mapFunc;
while ((*funcEnd != '\0') && (*funcEnd != '(') && while ((*funcEnd != '\0') && (*funcEnd != '(') &&
(! isspace((unsigned char) *funcEnd))) (!isspace((unsigned char) *funcEnd)))
funcEnd++; funcEnd++;
svchar = *funcEnd; svchar = *funcEnd;
*funcEnd = '\0'; *funcEnd = '\0';
...@@ -1157,28 +1272,33 @@ char key[33]; ...@@ -1157,28 +1272,33 @@ char key[33];
while ((*funcEnd != '\0') && isspace((unsigned char) *funcEnd)) while ((*funcEnd != '\0') && isspace((unsigned char) *funcEnd))
funcEnd++; funcEnd++;
/* We expect left parenthesis here, /*
* else return fn body as-is since it is * We expect left parenthesis here, else return fn body as-is
* one of those "function constants". * since it is one of those "function constants".
*/ */
if (*funcEnd != '(') { if (*funcEnd != '(')
strncpy(escape, value, sizeof(escape)-1); {
strncpy(escape, value, sizeof(escape) - 1);
return escape; return escape;
} }
mapFunc = mapFunction(key); mapFunc = mapFunction(key);
/* We could have mapFunction() return key if not in table...
* - thomas 2000-04-03 /*
* We could have mapFunction() return key if not in table... -
* thomas 2000-04-03
*/ */
if (mapFunc == NULL) { if (mapFunc == NULL)
{
/* If unrecognized function name, return fn body as-is */ /* If unrecognized function name, return fn body as-is */
strncpy(escape, value, sizeof(escape)-1); strncpy(escape, value, sizeof(escape) - 1);
return escape; return escape;
} }
/* copy mapped name and remaining input string */ /* copy mapped name and remaining input string */
strcpy(escape, mapFunc); strcpy(escape, mapFunc);
strncat(escape, funcEnd, sizeof(escape)-1-strlen(mapFunc)); strncat(escape, funcEnd, sizeof(escape) - 1 - strlen(mapFunc));
} }
else { else
{
/* Bogus key, leave untranslated */ /* Bogus key, leave untranslated */
return NULL; return NULL;
} }
...@@ -1191,9 +1311,11 @@ char key[33]; ...@@ -1191,9 +1311,11 @@ char key[33];
char * char *
convert_money(char *s) convert_money(char *s)
{ {
size_t i = 0, out = 0; size_t i = 0,
out = 0;
for (i = 0; i < strlen(s); i++) { for (i = 0; i < strlen(s); i++)
{
if (s[i] == '$' || s[i] == ',' || s[i] == ')') if (s[i] == '$' || s[i] == ',' || s[i] == ')')
; /* skip these characters */ ; /* skip these characters */
else if (s[i] == '(') else if (s[i] == '(')
...@@ -1210,19 +1332,25 @@ size_t i = 0, out = 0; ...@@ -1210,19 +1332,25 @@ size_t i = 0, out = 0;
/* This function parses a character string for date/time info and fills in SIMPLE_TIME */ /* 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 */ /* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value */
char char
parse_datetime(char *buf, SIMPLE_TIME *st) parse_datetime(char *buf, SIMPLE_TIME * st)
{ {
int y,m,d,hh,mm,ss; int y,
int nf; m,
d,
hh,
mm,
ss;
int nf;
y = m = d = hh = mm = ss = 0; y = m = d = hh = mm = ss = 0;
if (buf[4] == '-') /* year first */ if (buf[4] == '-') /* year first */
nf = sscanf(buf, "%4d-%2d-%2d %2d:%2d:%2d", &y,&m,&d,&hh,&mm,&ss); nf = sscanf(buf, "%4d-%2d-%2d %2d:%2d:%2d", &y, &m, &d, &hh, &mm, &ss);
else else
nf = sscanf(buf, "%2d-%2d-%4d %2d:%2d:%2d", &m,&d,&y,&hh,&mm,&ss); nf = sscanf(buf, "%2d-%2d-%4d %2d:%2d:%2d", &m, &d, &y, &hh, &mm, &ss);
if (nf == 5 || nf == 6) { if (nf == 5 || nf == 6)
{
st->y = y; st->y = y;
st->m = m; st->m = m;
st->d = d; st->d = d;
...@@ -1238,7 +1366,8 @@ int nf; ...@@ -1238,7 +1366,8 @@ int nf;
else else
nf = sscanf(buf, "%2d-%2d-%4d", &m, &d, &y); nf = sscanf(buf, "%2d-%2d-%4d", &m, &d, &y);
if (nf == 3) { if (nf == 3)
{
st->y = y; st->y = y;
st->m = m; st->m = m;
st->d = d; st->d = d;
...@@ -1247,7 +1376,8 @@ int nf; ...@@ -1247,7 +1376,8 @@ int nf;
} }
nf = sscanf(buf, "%2d:%2d:%2d", &hh, &mm, &ss); nf = sscanf(buf, "%2d:%2d:%2d", &hh, &mm, &ss);
if (nf == 2 || nf == 3) { if (nf == 2 || nf == 3)
{
st->hh = hh; st->hh = hh;
st->mm = mm; st->mm = mm;
st->ss = ss; st->ss = ss;
...@@ -1262,12 +1392,16 @@ int nf; ...@@ -1262,12 +1392,16 @@ int nf;
int int
convert_linefeeds(char *si, char *dst, size_t max) convert_linefeeds(char *si, char *dst, size_t max)
{ {
size_t i = 0, out = 0; size_t i = 0,
out = 0;
for (i = 0; i < strlen(si) && out < max - 1; i++) { for (i = 0; i < strlen(si) && out < max - 1; i++)
if (si[i] == '\n') { {
if (si[i] == '\n')
{
/* Only add the carriage-return if needed */ /* Only add the carriage-return if needed */
if (i > 0 && si[i-1] == '\r') { if (i > 0 && si[i - 1] == '\r')
{
dst[out++] = si[i]; dst[out++] = si[i];
continue; continue;
} }
...@@ -1288,9 +1422,11 @@ size_t i = 0, out = 0; ...@@ -1288,9 +1422,11 @@ size_t i = 0, out = 0;
char * char *
convert_special_chars(char *si, char *dst, int used) convert_special_chars(char *si, char *dst, int used)
{ {
size_t i = 0, out = 0, max; size_t i = 0,
static char sout[TEXT_FIELD_SIZE+5]; out = 0,
char *p; max;
static char sout[TEXT_FIELD_SIZE + 5];
char *p;
if (dst) if (dst)
p = dst; p = dst;
...@@ -1304,8 +1440,9 @@ char *p; ...@@ -1304,8 +1440,9 @@ char *p;
else else
max = used; max = used;
for (i = 0; i < max; i++) { for (i = 0; i < max; i++)
if (si[i] == '\r' && i+1 < strlen(si) && si[i+1] == '\n') {
if (si[i] == '\r' && i + 1 < strlen(si) && si[i + 1] == '\n')
continue; continue;
else if (si[i] == '\'' || si[i] == '\\') else if (si[i] == '\'' || si[i] == '\\')
p[out++] = '\\'; p[out++] = '\\';
...@@ -1329,11 +1466,11 @@ convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax) ...@@ -1329,11 +1466,11 @@ convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
unsigned int unsigned int
conv_from_octal(unsigned char *s) conv_from_octal(unsigned char *s)
{ {
int i, y=0; int i,
y = 0;
for (i = 1; i <= 3; i++) { for (i = 1; i <= 3; i++)
y += (s[i] - 48) * (int) pow(8, 3-i); y += (s[i] - 48) * (int) pow(8, 3 - i);
}
return y; return y;
...@@ -1342,9 +1479,12 @@ int i, y=0; ...@@ -1342,9 +1479,12 @@ int i, y=0;
unsigned int unsigned int
conv_from_hex(unsigned char *s) conv_from_hex(unsigned char *s)
{ {
int i, y=0, val; int i,
y = 0,
val;
for (i = 1; i <= 2; i++) { for (i = 1; i <= 2; i++)
{
if (s[i] >= 'a' && s[i] <= 'f') if (s[i] >= 'a' && s[i] <= 'f')
val = s[i] - 'a' + 10; val = s[i] - 'a' + 10;
...@@ -1353,7 +1493,7 @@ int i, y=0, val; ...@@ -1353,7 +1493,7 @@ int i, y=0, val;
else else
val = s[i] - '0'; val = s[i] - '0';
y += val * (int) pow(16, 2-i); y += val * (int) pow(16, 2 - i);
} }
return y; return y;
...@@ -1363,18 +1503,19 @@ int i, y=0, val; ...@@ -1363,18 +1503,19 @@ int i, y=0, val;
int int
convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax) convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
{ {
size_t i; size_t i;
int o=0; int o = 0;
for (i = 0; i < strlen(value); ) { for (i = 0; i < strlen(value);)
if (value[i] == '\\') { {
if (value[i] == '\\')
{
rgbValue[o] = conv_from_octal(&value[i]); rgbValue[o] = conv_from_octal(&value[i]);
i += 4; i += 4;
} }
else { else
rgbValue[o] = value[i++]; rgbValue[o] = value[i++];
}
mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]); mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]);
o++; o++;
} }
...@@ -1388,14 +1529,15 @@ int o=0; ...@@ -1388,14 +1529,15 @@ int o=0;
char * char *
conv_to_octal(unsigned char val) conv_to_octal(unsigned char val)
{ {
int i; int i;
static char x[6]; static char x[6];
x[0] = '\\'; x[0] = '\\';
x[1] = '\\'; x[1] = '\\';
x[5] = '\0'; x[5] = '\0';
for (i = 4; i > 1; i--) { for (i = 4; i > 1; i--)
{
x[i] = (val & 7) + 48; x[i] = (val & 7) + 48;
val >>= 3; val >>= 3;
} }
...@@ -1407,15 +1549,17 @@ static char x[6]; ...@@ -1407,15 +1549,17 @@ static char x[6];
int int
convert_to_pgbinary(unsigned char *in, char *out, int len) convert_to_pgbinary(unsigned char *in, char *out, int len)
{ {
int i, o=0; int i,
o = 0;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++)
{
mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]); mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
if ( isalnum(in[i]) || in[i] == ' ') { if (isalnum(in[i]) || in[i] == ' ')
out[o++] = in[i]; out[o++] = in[i];
} else
else { {
strcpy(&out[o], conv_to_octal(in[i])); strcpy(&out[o], conv_to_octal(in[i]));
o += 5; o += 5;
} }
...@@ -1431,17 +1575,20 @@ int i, o=0; ...@@ -1431,17 +1575,20 @@ int i, o=0;
void void
encode(char *in, char *out) encode(char *in, char *out)
{ {
unsigned int i, o = 0; unsigned int i,
o = 0;
for (i = 0; i < strlen(in); i++) { for (i = 0; i < strlen(in); i++)
if ( in[i] == '+') { {
if (in[i] == '+')
{
sprintf(&out[o], "%%2B"); sprintf(&out[o], "%%2B");
o += 3; o += 3;
} }
else if ( isspace((unsigned char) in[i])) { else if (isspace((unsigned char) in[i]))
out[o++] = '+'; out[o++] = '+';
} else if (!isalnum((unsigned char) in[i]))
else if ( ! isalnum((unsigned char) in[i])) { {
sprintf(&out[o], "%%%02x", (unsigned char) in[i]); sprintf(&out[o], "%%%02x", (unsigned char) in[i]);
o += 3; o += 3;
} }
...@@ -1455,14 +1602,17 @@ encode(char *in, char *out) ...@@ -1455,14 +1602,17 @@ encode(char *in, char *out)
void void
decode(char *in, char *out) decode(char *in, char *out)
{ {
unsigned int i, o = 0; unsigned int i,
o = 0;
for (i = 0; i < strlen(in); i++) { for (i = 0; i < strlen(in); i++)
{
if (in[i] == '+') if (in[i] == '+')
out[o++] = ' '; out[o++] = ' ';
else if (in[i] == '%') { else if (in[i] == '%')
{
sprintf(&out[o++], "%c", conv_from_hex(&in[i])); sprintf(&out[o++], "%c", conv_from_hex(&in[i]));
i+=2; i += 2;
} }
else else
out[o++] = in[i]; out[o++] = in[i];
...@@ -1487,40 +1637,48 @@ unsigned int i, o = 0; ...@@ -1487,40 +1637,48 @@ unsigned int i, o = 0;
mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now. mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
*/ */
int int
convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, convert_lo(StatementClass * stmt, void *value, Int2 fCType, PTR rgbValue,
SDWORD cbValueMax, SDWORD *pcbValue) SDWORD cbValueMax, SDWORD * pcbValue)
{ {
Oid oid; Oid oid;
int retval, result, left = -1; int retval,
result,
left = -1;
BindInfoClass *bindInfo = NULL; 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) { if (stmt->current_col >= 0)
{
bindInfo = &stmt->bindings[stmt->current_col]; bindInfo = &stmt->bindings[stmt->current_col];
left = bindInfo->data_left; left = bindInfo->data_left;
} }
/* if this is the first call for this column, /*
open the large object for reading * if this is the first call for this column, open the large object
* for reading
*/ */
if ( ! bindInfo || bindInfo->data_left == -1) { if (!bindInfo || bindInfo->data_left == -1)
{
/* begin transaction if needed */ /* begin transaction if needed */
if(!CC_is_in_trans(stmt->hdbc)) { if (!CC_is_in_trans(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "BEGIN", NULL); res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not begin (in-line) a transaction"; stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not begin (in-line) a transaction"; stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
...@@ -1531,7 +1689,8 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, ...@@ -1531,7 +1689,8 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
oid = atoi(value); oid = atoi(value);
stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ); stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ);
if (stmt->lobj_fd < 0) { if (stmt->lobj_fd < 0)
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt open large object for reading."; stmt->errormsg = "Couldnt open large object for reading.";
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
...@@ -1539,7 +1698,8 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, ...@@ -1539,7 +1698,8 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
/* Get the size */ /* Get the size */
retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END); retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END);
if (retval >= 0) { if (retval >= 0)
{
left = lo_tell(stmt->hdbc, stmt->lobj_fd); left = lo_tell(stmt->hdbc, stmt->lobj_fd);
if (bindInfo) if (bindInfo)
...@@ -1550,34 +1710,38 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, ...@@ -1550,34 +1710,38 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
} }
} }
if (left == 0) { if (left == 0)
return COPY_NO_DATA_FOUND; return COPY_NO_DATA_FOUND;
}
if (stmt->lobj_fd < 0) { if (stmt->lobj_fd < 0)
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Large object FD undefined for multiple read."; stmt->errormsg = "Large object FD undefined for multiple read.";
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
} }
retval = lo_read(stmt->hdbc, stmt->lobj_fd, (char *) rgbValue, cbValueMax); retval = lo_read(stmt->hdbc, stmt->lobj_fd, (char *) rgbValue, cbValueMax);
if (retval < 0) { if (retval < 0)
{
lo_close(stmt->hdbc, stmt->lobj_fd); lo_close(stmt->hdbc, stmt->lobj_fd);
/* commit transaction if needed */ /* commit transaction if needed */
if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "COMMIT", NULL); res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
...@@ -1606,23 +1770,27 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, ...@@ -1606,23 +1770,27 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
bindInfo->data_left -= retval; bindInfo->data_left -= retval;
if (! bindInfo || bindInfo->data_left == 0) { if (!bindInfo || bindInfo->data_left == 0)
{
lo_close(stmt->hdbc, stmt->lobj_fd); lo_close(stmt->hdbc, stmt->lobj_fd);
/* commit transaction if needed */ /* commit transaction if needed */
if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "COMMIT", NULL); res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
return COPY_GENERAL_ERROR; return COPY_GENERAL_ERROR;
......
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
#define COPY_GENERAL_ERROR 4 #define COPY_GENERAL_ERROR 4
#define COPY_NO_DATA_FOUND 5 #define COPY_NO_DATA_FOUND 5
typedef struct { typedef struct
{
int m; int m;
int d; int d;
int y; int y;
...@@ -29,14 +30,14 @@ typedef struct { ...@@ -29,14 +30,14 @@ typedef struct {
int ss; int ss;
} SIMPLE_TIME; } SIMPLE_TIME;
int copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col); int copy_and_convert_field_bindinfo(StatementClass * stmt, Int4 field_type, void *value, int col);
int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType, int copy_and_convert_field(StatementClass * stmt, Int4 field_type, void *value, Int2 fCType,
PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue); PTR rgbValue, SDWORD cbValueMax, SDWORD * pcbValue);
int copy_statement_with_parameters(StatementClass *stmt); int copy_statement_with_parameters(StatementClass * stmt);
char *convert_escape(char *value); char *convert_escape(char *value);
char *convert_money(char *s); char *convert_money(char *s);
char parse_datetime(char *buf, SIMPLE_TIME *st); char parse_datetime(char *buf, SIMPLE_TIME * st);
int convert_linefeeds(char *s, char *dst, size_t max); int convert_linefeeds(char *s, char *dst, size_t max);
char *convert_special_chars(char *si, char *dst, int used); char *convert_special_chars(char *si, char *dst, int used);
...@@ -45,7 +46,7 @@ int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbV ...@@ -45,7 +46,7 @@ int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbV
int convert_to_pgbinary(unsigned char *in, char *out, int len); int convert_to_pgbinary(unsigned char *in, char *out, int len);
void encode(char *in, char *out); void encode(char *in, char *out);
void decode(char *in, char *out); void decode(char *in, char *out);
int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue, int convert_lo(StatementClass * stmt, void *value, Int2 fCType, PTR rgbValue,
SDWORD cbValueMax, SDWORD *pcbValue); SDWORD cbValueMax, SDWORD * pcbValue);
#endif #endif
...@@ -20,14 +20,14 @@ ...@@ -20,14 +20,14 @@
#endif #endif
#ifndef WIN32 #ifndef WIN32
# include <string.h> #include <string.h>
# include "gpps.h" #include "gpps.h"
# define SQLGetPrivateProfileString(a,b,c,d,e,f) GetPrivateProfileString(a,b,c,d,e,f) #define SQLGetPrivateProfileString(a,b,c,d,e,f) GetPrivateProfileString(a,b,c,d,e,f)
# define SQLWritePrivateProfileString(a,b,c,d) WritePrivateProfileString(a,b,c,d) #define SQLWritePrivateProfileString(a,b,c,d) WritePrivateProfileString(a,b,c,d)
# ifndef HAVE_STRICMP #ifndef HAVE_STRICMP
# define stricmp(s1,s2) strcasecmp(s1,s2) #define stricmp(s1,s2) strcasecmp(s1,s2)
# define strnicmp(s1,s2,n) strncasecmp(s1,s2,n) #define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
# endif #endif
#endif #endif
#include "dlg_specific.h" #include "dlg_specific.h"
...@@ -47,10 +47,15 @@ extern GLOBAL_VALUES globals; ...@@ -47,10 +47,15 @@ extern GLOBAL_VALUES globals;
#ifdef WIN32 #ifdef WIN32
void void
SetDlgStuff(HWND hdlg, ConnInfo *ci) SetDlgStuff(HWND hdlg, ConnInfo * ci)
{ {
/* If driver attribute NOT present, then set the datasource name and description */
if (ci->driver[0] == '\0') { /*
* If driver attribute NOT present, then set the datasource name and
* description
*/
if (ci->driver[0] == '\0')
{
SetDlgItemText(hdlg, IDC_DSNAME, ci->dsn); SetDlgItemText(hdlg, IDC_DSNAME, ci->dsn);
SetDlgItemText(hdlg, IDC_DESC, ci->desc); SetDlgItemText(hdlg, IDC_DESC, ci->desc);
} }
...@@ -63,7 +68,7 @@ SetDlgStuff(HWND hdlg, ConnInfo *ci) ...@@ -63,7 +68,7 @@ SetDlgStuff(HWND hdlg, ConnInfo *ci)
} }
void void
GetDlgStuff(HWND hdlg, ConnInfo *ci) GetDlgStuff(HWND hdlg, ConnInfo * ci)
{ {
GetDlgItemText(hdlg, IDC_DESC, ci->desc, sizeof(ci->desc)); GetDlgItemText(hdlg, IDC_DESC, ci->desc, sizeof(ci->desc));
...@@ -76,12 +81,14 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci) ...@@ -76,12 +81,14 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci)
int CALLBACK driver_optionsProc(HWND hdlg, int CALLBACK
driver_optionsProc(HWND hdlg,
WORD wMsg, WORD wMsg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
switch (wMsg) { switch (wMsg)
{
case WM_INITDIALOG: case WM_INITDIALOG:
CheckDlgButton(hdlg, DRV_COMMLOG, globals.commlog); CheckDlgButton(hdlg, DRV_COMMLOG, globals.commlog);
...@@ -92,7 +99,8 @@ int CALLBACK driver_optionsProc(HWND hdlg, ...@@ -92,7 +99,8 @@ int CALLBACK driver_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, globals.use_declarefetch); CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, globals.use_declarefetch);
/* Unknown (Default) Data Type sizes */ /* Unknown (Default) Data Type sizes */
switch(globals.unknown_sizes) { switch (globals.unknown_sizes)
{
case UNKNOWNS_AS_DONTKNOW: case UNKNOWNS_AS_DONTKNOW:
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1); CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
break; break;
...@@ -125,7 +133,8 @@ int CALLBACK driver_optionsProc(HWND hdlg, ...@@ -125,7 +133,8 @@ int CALLBACK driver_optionsProc(HWND hdlg,
break; break;
case WM_COMMAND: case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) { switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK: case IDOK:
globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG); globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
...@@ -155,7 +164,8 @@ int CALLBACK driver_optionsProc(HWND hdlg, ...@@ -155,7 +164,8 @@ int CALLBACK driver_optionsProc(HWND hdlg,
globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE); globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE);
globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE); globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE);
globals.max_longvarchar_size= GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for SQL_NO_TOTAL */ globals.max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); /* allows for
* SQL_NO_TOTAL */
GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, sizeof(globals.extra_systable_prefixes)); GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, sizeof(globals.extra_systable_prefixes));
...@@ -185,7 +195,8 @@ int CALLBACK driver_optionsProc(HWND hdlg, ...@@ -185,7 +195,8 @@ int CALLBACK driver_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0); CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0);
CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0); CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0);
CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0); CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0);
switch(DEFAULT_UNKNOWNSIZES) { switch (DEFAULT_UNKNOWNSIZES)
{
case UNKNOWNS_AS_DONTKNOW: case UNKNOWNS_AS_DONTKNOW:
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1); CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
break; break;
...@@ -218,15 +229,17 @@ int CALLBACK driver_optionsProc(HWND hdlg, ...@@ -218,15 +229,17 @@ int CALLBACK driver_optionsProc(HWND hdlg,
return FALSE; return FALSE;
} }
int CALLBACK ds_optionsProc(HWND hdlg, int CALLBACK
ds_optionsProc(HWND hdlg,
WORD wMsg, WORD wMsg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
ConnInfo *ci; ConnInfo *ci;
char buf[128]; char buf[128];
switch (wMsg) { switch (wMsg)
{
case WM_INITDIALOG: case WM_INITDIALOG:
ci = (ConnInfo *) lParam; ci = (ConnInfo *) lParam;
SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK */ SetWindowLong(hdlg, DWL_USER, lParam); /* save for OK */
...@@ -234,7 +247,8 @@ char buf[128]; ...@@ -234,7 +247,8 @@ char buf[128];
/* Change window caption */ /* Change window caption */
if (ci->driver[0]) if (ci->driver[0])
SetWindowText(hdlg, "Advanced Options (Connection)"); SetWindowText(hdlg, "Advanced Options (Connection)");
else { else
{
sprintf(buf, "Advanced Options (%s)", ci->dsn); sprintf(buf, "Advanced Options (%s)", ci->dsn);
SetWindowText(hdlg, buf); SetWindowText(hdlg, buf);
} }
...@@ -260,7 +274,8 @@ char buf[128]; ...@@ -260,7 +274,8 @@ char buf[128];
case WM_COMMAND: case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) { switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case DS_SHOWOIDCOLUMN: case DS_SHOWOIDCOLUMN:
mylog("WM_COMMAND: DS_SHOWOIDCOLUMN\n"); mylog("WM_COMMAND: DS_SHOWOIDCOLUMN\n");
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN)); EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
...@@ -269,7 +284,7 @@ char buf[128]; ...@@ -269,7 +284,7 @@ char buf[128];
case IDOK: case IDOK:
ci = (ConnInfo *)GetWindowLong(hdlg, DWL_USER); ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
mylog("IDOK: got ci = %u\n", ci); mylog("IDOK: got ci = %u\n", ci);
/* Readonly */ /* Readonly */
...@@ -282,7 +297,7 @@ char buf[128]; ...@@ -282,7 +297,7 @@ char buf[128];
sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING)); sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING));
/* OID Options*/ /* OID Options */
sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX)); sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX));
sprintf(ci->show_oid_column, "%d", IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN)); sprintf(ci->show_oid_column, "%d", IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
...@@ -304,10 +319,10 @@ char buf[128]; ...@@ -304,10 +319,10 @@ char buf[128];
#endif /* WIN32 */ #endif /* WIN32 */
void void
makeConnectString(char *connect_string, ConnInfo *ci) makeConnectString(char *connect_string, ConnInfo * ci)
{ {
char got_dsn = (ci->dsn[0] != '\0'); char got_dsn = (ci->dsn[0] != '\0');
char encoded_conn_settings[LARGE_REGISTRY_LEN]; char encoded_conn_settings[LARGE_REGISTRY_LEN];
/* fundamental info */ /* fundamental info */
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s", sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
...@@ -334,28 +349,28 @@ char encoded_conn_settings[LARGE_REGISTRY_LEN]; ...@@ -334,28 +349,28 @@ char encoded_conn_settings[LARGE_REGISTRY_LEN];
} }
void void
copyAttributes(ConnInfo *ci, char *attribute, char *value) copyAttributes(ConnInfo * ci, char *attribute, char *value)
{ {
if(stricmp(attribute, "DSN") == 0) if (stricmp(attribute, "DSN") == 0)
strcpy(ci->dsn, value); strcpy(ci->dsn, value);
else if(stricmp(attribute, "driver") == 0) else if (stricmp(attribute, "driver") == 0)
strcpy(ci->driver, value); strcpy(ci->driver, value);
else if(stricmp(attribute, INI_DATABASE) == 0) else if (stricmp(attribute, INI_DATABASE) == 0)
strcpy(ci->database, value); strcpy(ci->database, value);
else if(stricmp(attribute, INI_SERVER) == 0 || stricmp(attribute, "server") == 0) else if (stricmp(attribute, INI_SERVER) == 0 || stricmp(attribute, "server") == 0)
strcpy(ci->server, value); strcpy(ci->server, value);
else if(stricmp(attribute, INI_USER) == 0 || stricmp(attribute, "uid") == 0) else if (stricmp(attribute, INI_USER) == 0 || stricmp(attribute, "uid") == 0)
strcpy(ci->username, value); strcpy(ci->username, value);
else if(stricmp(attribute, INI_PASSWORD) == 0 || stricmp(attribute, "pwd") == 0) else if (stricmp(attribute, INI_PASSWORD) == 0 || stricmp(attribute, "pwd") == 0)
strcpy(ci->password, value); strcpy(ci->password, value);
else if(stricmp(attribute, INI_PORT) == 0) else if (stricmp(attribute, INI_PORT) == 0)
strcpy(ci->port, value); strcpy(ci->port, value);
else if (stricmp(attribute, INI_READONLY) == 0) else if (stricmp(attribute, INI_READONLY) == 0)
...@@ -376,17 +391,18 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value) ...@@ -376,17 +391,18 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0) else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0)
strcpy(ci->show_system_tables, value); strcpy(ci->show_system_tables, value);
else if (stricmp(attribute, INI_CONNSETTINGS) == 0) { else if (stricmp(attribute, INI_CONNSETTINGS) == 0)
{
decode(value, ci->conn_settings); decode(value, ci->conn_settings);
/* strcpy(ci->conn_settings, value); */ /* strcpy(ci->conn_settings, value); */
} }
mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server,ci->database,ci->username,ci->password,ci->port,ci->onlyread,ci->protocol,ci->conn_settings); 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 void
getDSNdefaults(ConnInfo *ci) getDSNdefaults(ConnInfo * ci)
{ {
if (ci->port[0] == '\0') if (ci->port[0] == '\0')
strcpy(ci->port, DEFAULT_PORT); strcpy(ci->port, DEFAULT_PORT);
...@@ -412,70 +428,73 @@ getDSNdefaults(ConnInfo *ci) ...@@ -412,70 +428,73 @@ getDSNdefaults(ConnInfo *ci)
void void
getDSNinfo(ConnInfo *ci, char overwrite) getDSNinfo(ConnInfo * ci, char overwrite)
{ {
char *DSN = ci->dsn; char *DSN = ci->dsn;
char encoded_conn_settings[LARGE_REGISTRY_LEN]; char encoded_conn_settings[LARGE_REGISTRY_LEN];
/* If a driver keyword was present, then dont use a DSN and return. */ /* 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 is null and no driver, then use the default datasource. */
if ( DSN[0] == '\0') { if (DSN[0] == '\0')
if ( ci->driver[0] != '\0') {
if (ci->driver[0] != '\0')
return; return;
else else
strcpy(DSN, INI_DSN); strcpy(DSN, INI_DSN);
} }
/* brute-force chop off trailing blanks... */ /* brute-force chop off trailing blanks... */
while (*(DSN+strlen(DSN)-1) == ' ') *(DSN+strlen(DSN)-1) = '\0'; while (*(DSN + strlen(DSN) - 1) == ' ')
*(DSN + strlen(DSN) - 1) = '\0';
/* Proceed with getting info for the given DSN. */ /* Proceed with getting info for the given DSN. */
if ( ci->desc[0] == '\0' || overwrite) if (ci->desc[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_KDESC, "", ci->desc, sizeof(ci->desc), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_KDESC, "", ci->desc, sizeof(ci->desc), ODBC_INI);
if ( ci->server[0] == '\0' || overwrite) if (ci->server[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_SERVER, "", ci->server, sizeof(ci->server), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_SERVER, "", ci->server, sizeof(ci->server), ODBC_INI);
if ( ci->database[0] == '\0' || overwrite) if (ci->database[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_DATABASE, "", ci->database, sizeof(ci->database), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_DATABASE, "", ci->database, sizeof(ci->database), ODBC_INI);
if ( ci->username[0] == '\0' || overwrite) if (ci->username[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_USER, "", ci->username, sizeof(ci->username), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_USER, "", ci->username, sizeof(ci->username), ODBC_INI);
if ( ci->password[0] == '\0' || overwrite) if (ci->password[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_PASSWORD, "", ci->password, sizeof(ci->password), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_PASSWORD, "", ci->password, sizeof(ci->password), ODBC_INI);
if ( ci->port[0] == '\0' || overwrite) if (ci->port[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_PORT, "", ci->port, sizeof(ci->port), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_PORT, "", ci->port, sizeof(ci->port), ODBC_INI);
if ( ci->onlyread[0] == '\0' || overwrite) if (ci->onlyread[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_READONLY, "", ci->onlyread, sizeof(ci->onlyread), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_READONLY, "", ci->onlyread, sizeof(ci->onlyread), ODBC_INI);
if ( ci->show_oid_column[0] == '\0' || overwrite) if (ci->show_oid_column[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_SHOWOIDCOLUMN, "", ci->show_oid_column, sizeof(ci->show_oid_column), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_SHOWOIDCOLUMN, "", ci->show_oid_column, sizeof(ci->show_oid_column), ODBC_INI);
if ( ci->fake_oid_index[0] == '\0' || overwrite) if (ci->fake_oid_index[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_FAKEOIDINDEX, "", ci->fake_oid_index, sizeof(ci->fake_oid_index), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_FAKEOIDINDEX, "", ci->fake_oid_index, sizeof(ci->fake_oid_index), ODBC_INI);
if ( ci->row_versioning[0] == '\0' || overwrite) if (ci->row_versioning[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_ROWVERSIONING, "", ci->row_versioning, sizeof(ci->row_versioning), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_ROWVERSIONING, "", ci->row_versioning, sizeof(ci->row_versioning), ODBC_INI);
if ( ci->show_system_tables[0] == '\0' || overwrite) if (ci->show_system_tables[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_SHOWSYSTEMTABLES, "", ci->show_system_tables, sizeof(ci->show_system_tables), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_SHOWSYSTEMTABLES, "", ci->show_system_tables, sizeof(ci->show_system_tables), ODBC_INI);
if ( ci->protocol[0] == '\0' || overwrite) if (ci->protocol[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_PROTOCOL, "", ci->protocol, sizeof(ci->protocol), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_PROTOCOL, "", ci->protocol, sizeof(ci->protocol), ODBC_INI);
if ( ci->conn_settings[0] == '\0' || overwrite) { if (ci->conn_settings[0] == '\0' || overwrite)
{
SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, "", encoded_conn_settings, sizeof(encoded_conn_settings), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, "", encoded_conn_settings, sizeof(encoded_conn_settings), ODBC_INI);
decode(encoded_conn_settings, ci->conn_settings); decode(encoded_conn_settings, ci->conn_settings);
} }
if ( ci->translation_dll[0] == '\0' || overwrite) if (ci->translation_dll[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONDLL, "", ci->translation_dll, sizeof(ci->translation_dll), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_TRANSLATIONDLL, "", ci->translation_dll, sizeof(ci->translation_dll), ODBC_INI);
if ( ci->translation_option[0] == '\0' || overwrite) if (ci->translation_option[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
...@@ -507,10 +526,10 @@ char encoded_conn_settings[LARGE_REGISTRY_LEN]; ...@@ -507,10 +526,10 @@ char encoded_conn_settings[LARGE_REGISTRY_LEN];
/* This is for datasource based options only */ /* This is for datasource based options only */
void void
writeDSNinfo(ConnInfo *ci) writeDSNinfo(ConnInfo * ci)
{ {
char *DSN = ci->dsn; char *DSN = ci->dsn;
char encoded_conn_settings[LARGE_REGISTRY_LEN]; char encoded_conn_settings[LARGE_REGISTRY_LEN];
encode(ci->conn_settings, encoded_conn_settings); encode(ci->conn_settings, encoded_conn_settings);
...@@ -584,107 +603,109 @@ char encoded_conn_settings[LARGE_REGISTRY_LEN]; ...@@ -584,107 +603,109 @@ char encoded_conn_settings[LARGE_REGISTRY_LEN];
/* This function reads the ODBCINST.INI portion of /* This function reads the ODBCINST.INI portion of
the registry and gets any driver defaults. the registry and gets any driver defaults.
*/ */
void getGlobalDefaults(char *section, char *filename, char override) void
getGlobalDefaults(char *section, char *filename, char override)
{ {
char temp[256]; char temp[256];
/* Fetch Count is stored in driver section */ /* Fetch Count is stored in driver section */
SQLGetPrivateProfileString(section, INI_FETCH, "", SQLGetPrivateProfileString(section, INI_FETCH, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) { if (temp[0])
{
globals.fetch_max = atoi(temp); globals.fetch_max = atoi(temp);
/* sanity check if using cursors */ /* sanity check if using cursors */
if (globals.fetch_max <= 0) if (globals.fetch_max <= 0)
globals.fetch_max = FETCH_MAX; globals.fetch_max = FETCH_MAX;
} }
else if ( ! override) else if (!override)
globals.fetch_max = FETCH_MAX; globals.fetch_max = FETCH_MAX;
/* Socket Buffersize is stored in driver section */ /* Socket Buffersize is stored in driver section */
SQLGetPrivateProfileString(section, INI_SOCKET, "", SQLGetPrivateProfileString(section, INI_SOCKET, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.socket_buffersize = atoi(temp); globals.socket_buffersize = atoi(temp);
else if ( ! override) else if (!override)
globals.socket_buffersize = SOCK_BUFFER_SIZE; globals.socket_buffersize = SOCK_BUFFER_SIZE;
/* Debug is stored in the driver section */ /* Debug is stored in the driver section */
SQLGetPrivateProfileString(section, INI_DEBUG, "", SQLGetPrivateProfileString(section, INI_DEBUG, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.debug = atoi(temp); globals.debug = atoi(temp);
else if ( ! override) else if (!override)
globals.debug = DEFAULT_DEBUG; globals.debug = DEFAULT_DEBUG;
/* CommLog is stored in the driver section */ /* CommLog is stored in the driver section */
SQLGetPrivateProfileString(section, INI_COMMLOG, "", SQLGetPrivateProfileString(section, INI_COMMLOG, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.commlog = atoi(temp); globals.commlog = atoi(temp);
else if ( ! override) else if (!override)
globals.commlog = DEFAULT_COMMLOG; globals.commlog = DEFAULT_COMMLOG;
/* Optimizer is stored in the driver section only */ /* Optimizer is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_OPTIMIZER, "", SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.disable_optimizer = atoi(temp); globals.disable_optimizer = atoi(temp);
else if ( ! override) else if (!override)
globals.disable_optimizer = DEFAULT_OPTIMIZER; globals.disable_optimizer = DEFAULT_OPTIMIZER;
/* KSQO is stored in the driver section only */ /* KSQO is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_KSQO, "", SQLGetPrivateProfileString(section, INI_KSQO, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.ksqo = atoi(temp); globals.ksqo = atoi(temp);
else if ( ! override) else if (!override)
globals.ksqo = DEFAULT_KSQO; globals.ksqo = DEFAULT_KSQO;
/* Recognize Unique Index is stored in the driver section only */ /* Recognize Unique Index is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, "", SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.unique_index = atoi(temp); globals.unique_index = atoi(temp);
else if ( ! override) else if (!override)
globals.unique_index = DEFAULT_UNIQUEINDEX; globals.unique_index = DEFAULT_UNIQUEINDEX;
/* Unknown Sizes is stored in the driver section only */ /* Unknown Sizes is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, "", SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.unknown_sizes = atoi(temp); globals.unknown_sizes = atoi(temp);
else if ( ! override) else if (!override)
globals.unknown_sizes = DEFAULT_UNKNOWNSIZES; globals.unknown_sizes = DEFAULT_UNKNOWNSIZES;
/* Lie about supported functions? */ /* Lie about supported functions? */
SQLGetPrivateProfileString(section, INI_LIE, "", SQLGetPrivateProfileString(section, INI_LIE, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.lie = atoi(temp); globals.lie = atoi(temp);
else if ( ! override) else if (!override)
globals.lie = DEFAULT_LIE; globals.lie = DEFAULT_LIE;
/* Parse statements */ /* Parse statements */
SQLGetPrivateProfileString(section, INI_PARSE, "", SQLGetPrivateProfileString(section, INI_PARSE, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.parse = atoi(temp); globals.parse = atoi(temp);
else if ( ! override) else if (!override)
globals.parse = DEFAULT_PARSE; globals.parse = DEFAULT_PARSE;
/* SQLCancel calls SQLFreeStmt in Driver Manager */ /* SQLCancel calls SQLFreeStmt in Driver Manager */
SQLGetPrivateProfileString(section, INI_CANCELASFREESTMT, "", SQLGetPrivateProfileString(section, INI_CANCELASFREESTMT, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.cancel_as_freestmt = atoi(temp); globals.cancel_as_freestmt = atoi(temp);
else if ( ! override) else if (!override)
globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT; globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
...@@ -692,86 +713,95 @@ char temp[256]; ...@@ -692,86 +713,95 @@ char temp[256];
/* UseDeclareFetch is stored in the driver section only */ /* UseDeclareFetch is stored in the driver section only */
SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "", SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.use_declarefetch = atoi(temp); globals.use_declarefetch = atoi(temp);
else if ( ! override) else if (!override)
globals.use_declarefetch = DEFAULT_USEDECLAREFETCH; globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
/* Max Varchar Size */ /* Max Varchar Size */
SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "", SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.max_varchar_size = atoi(temp); globals.max_varchar_size = atoi(temp);
else if ( ! override) else if (!override)
globals.max_varchar_size = MAX_VARCHAR_SIZE; globals.max_varchar_size = MAX_VARCHAR_SIZE;
/* Max TextField Size */ /* Max TextField Size */
SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, "", SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.max_longvarchar_size = atoi(temp); globals.max_longvarchar_size = atoi(temp);
else if ( ! override) else if (!override)
globals.max_longvarchar_size = TEXT_FIELD_SIZE; globals.max_longvarchar_size = TEXT_FIELD_SIZE;
/* Text As LongVarchar */ /* Text As LongVarchar */
SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, "", SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.text_as_longvarchar = atoi(temp); globals.text_as_longvarchar = atoi(temp);
else if ( ! override) else if (!override)
globals.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR; globals.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
/* Unknowns As LongVarchar */ /* Unknowns As LongVarchar */
SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, "", SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.unknowns_as_longvarchar = atoi(temp); globals.unknowns_as_longvarchar = atoi(temp);
else if ( ! override) else if (!override)
globals.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR; globals.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
/* Bools As Char */ /* Bools As Char */
SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, "", SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.bools_as_char = atoi(temp); globals.bools_as_char = atoi(temp);
else if ( ! override) else if (!override)
globals.bools_as_char = DEFAULT_BOOLSASCHAR; globals.bools_as_char = DEFAULT_BOOLSASCHAR;
/* Extra Systable prefixes */ /* Extra Systable prefixes */
/* Use @@@ to distinguish between blank extra prefixes and no key entry */
/*
* Use @@@ to distinguish between blank extra prefixes and no key
* entry
*/
SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, "@@@", SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, "@@@",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( strcmp(temp, "@@@" )) if (strcmp(temp, "@@@"))
strcpy(globals.extra_systable_prefixes, temp); strcpy(globals.extra_systable_prefixes, temp);
else if ( ! override) else if (!override)
strcpy(globals.extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES); strcpy(globals.extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES);
mylog("globals.extra_systable_prefixes = '%s'\n", globals.extra_systable_prefixes); mylog("globals.extra_systable_prefixes = '%s'\n", globals.extra_systable_prefixes);
/* Dont allow override of an override! */ /* Dont allow override of an override! */
if ( ! override) { if (!override)
{
/* ConnSettings is stored in the driver section and per datasource for override */ /*
* ConnSettings is stored in the driver section and per datasource
* for override
*/
SQLGetPrivateProfileString(section, INI_CONNSETTINGS, "", SQLGetPrivateProfileString(section, INI_CONNSETTINGS, "",
globals.conn_settings, sizeof(globals.conn_settings), filename); globals.conn_settings, sizeof(globals.conn_settings), filename);
/* Default state for future DSN's Readonly attribute */ /* Default state for future DSN's Readonly attribute */
SQLGetPrivateProfileString(section, INI_READONLY, "", SQLGetPrivateProfileString(section, INI_READONLY, "",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( temp[0] ) if (temp[0])
globals.onlyread = atoi(temp); globals.onlyread = atoi(temp);
else else
globals.onlyread = DEFAULT_READONLY; globals.onlyread = DEFAULT_READONLY;
/* Default state for future DSN's protocol attribute /*
This isn't a real driver option YET. This is more * Default state for future DSN's protocol attribute This isn't a
intended for customization from the install. * real driver option YET. This is more intended for
* customization from the install.
*/ */
SQLGetPrivateProfileString(section, INI_PROTOCOL, "@@@", SQLGetPrivateProfileString(section, INI_PROTOCOL, "@@@",
temp, sizeof(temp), filename); temp, sizeof(temp), filename);
if ( strcmp(temp, "@@@" )) if (strcmp(temp, "@@@"))
strcpy(globals.protocol, temp); strcpy(globals.protocol, temp);
else else
strcpy(globals.protocol, DEFAULT_PROTOCOL); strcpy(globals.protocol, DEFAULT_PROTOCOL);
...@@ -783,9 +813,10 @@ char temp[256]; ...@@ -783,9 +813,10 @@ char temp[256];
/* This function writes any global parameters (that can be manipulated) /* This function writes any global parameters (that can be manipulated)
to the ODBCINST.INI portion of the registry to the ODBCINST.INI portion of the registry
*/ */
void updateGlobals(void) void
updateGlobals(void)
{ {
char tmp[128]; char tmp[128];
sprintf(tmp, "%d", globals.fetch_max); sprintf(tmp, "%d", globals.fetch_max);
SQLWritePrivateProfileString(DBMS_NAME, SQLWritePrivateProfileString(DBMS_NAME,
......
...@@ -31,23 +31,26 @@ ...@@ -31,23 +31,26 @@
/* INI File Stuff */ /* INI File Stuff */
#ifndef WIN32 #ifndef WIN32
# define ODBC_INI ".odbc.ini" #define ODBC_INI ".odbc.ini"
# ifdef ODBCINSTDIR #ifdef ODBCINSTDIR
# define ODBCINST_INI ODBCINSTDIR "/odbcinst.ini" #define ODBCINST_INI ODBCINSTDIR "/odbcinst.ini"
# else #else
# define ODBCINST_INI "/etc/odbcinst.ini" #define ODBCINST_INI "/etc/odbcinst.ini"
# warning "location of odbcinst.ini file defaulted to /etc" #warning "location of odbcinst.ini file defaulted to /etc"
# endif #endif
#else /* WIN32 */ #else /* WIN32 */
# define ODBC_INI "ODBC.INI" /* ODBC initialization file */ #define ODBC_INI "ODBC.INI" /* ODBC initialization file */
# define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */ #define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */
#endif /* WIN32 */ #endif /* WIN32 */
#define INI_DSN DBMS_NAME /* Name of default Datasource in ini file (not used?) */ #define INI_DSN DBMS_NAME /* Name of default Datasource in
* ini file (not used?) */
#define INI_KDESC "Description" /* Data source description */ #define INI_KDESC "Description" /* Data source description */
#define INI_SERVER "Servername" /* Name of Server running the Postgres service */ #define INI_SERVER "Servername" /* Name of Server running the
#define INI_PORT "Port" /* Port on which the Postmaster is listening */ * Postgres service */
#define INI_PORT "Port"/* Port on which the Postmaster is
* listening */
#define INI_DATABASE "Database" /* Database Name */ #define INI_DATABASE "Database" /* Database Name */
#define INI_USER "Username" /* Default User Name */ #define INI_USER "Username" /* Default User Name */
#define INI_PASSWORD "Password" /* Default Password */ #define INI_PASSWORD "Password" /* Default Password */
...@@ -55,17 +58,22 @@ ...@@ -55,17 +58,22 @@
#define INI_FETCH "Fetch" /* Fetch Max Count */ #define INI_FETCH "Fetch" /* Fetch Max Count */
#define INI_SOCKET "Socket" /* Socket buffer size */ #define INI_SOCKET "Socket" /* Socket buffer size */
#define INI_READONLY "ReadOnly" /* Database is read only */ #define INI_READONLY "ReadOnly" /* Database is read only */
#define INI_COMMLOG "CommLog" /* Communication to backend logging */ #define INI_COMMLOG "CommLog" /* Communication to backend
* logging */
#define INI_PROTOCOL "Protocol" /* What protocol (6.2) */ #define INI_PROTOCOL "Protocol" /* What protocol (6.2) */
#define INI_OPTIMIZER "Optimizer" /* Use backend genetic optimizer */ #define INI_OPTIMIZER "Optimizer" /* Use backend genetic optimizer */
#define INI_KSQO "Ksqo" /* Keyset query optimization */ #define INI_KSQO "Ksqo"/* Keyset query optimization */
#define INI_CONNSETTINGS "ConnSettings" /* Anything to send to backend on successful connection */ #define INI_CONNSETTINGS "ConnSettings" /* Anything to send to
* backend on successful
* connection */
#define INI_UNIQUEINDEX "UniqueIndex" /* Recognize unique indexes */ #define INI_UNIQUEINDEX "UniqueIndex" /* Recognize unique indexes */
#define INI_UNKNOWNSIZES "UnknownSizes" /* How to handle unknown result set sizes */ #define INI_UNKNOWNSIZES "UnknownSizes" /* How to handle unknown
* result set sizes */
#define INI_CANCELASFREESTMT "CancelAsFreeStmt" #define INI_CANCELASFREESTMT "CancelAsFreeStmt"
#define INI_USEDECLAREFETCH "UseDeclareFetch" /* Use Declare/Fetch cursors */ #define INI_USEDECLAREFETCH "UseDeclareFetch" /* Use Declare/Fetch
* cursors */
/* More ini stuff */ /* More ini stuff */
#define INI_TEXTASLONGVARCHAR "TextAsLongVarchar" #define INI_TEXTASLONGVARCHAR "TextAsLongVarchar"
...@@ -90,7 +98,8 @@ ...@@ -90,7 +98,8 @@
/* Connection Defaults */ /* Connection Defaults */
#define DEFAULT_PORT "5432" #define DEFAULT_PORT "5432"
#define DEFAULT_READONLY 1 #define DEFAULT_READONLY 1
#define DEFAULT_PROTOCOL "6.4" /* the latest protocol is the default */ #define DEFAULT_PROTOCOL "6.4" /* the latest protocol is
* the default */
#define DEFAULT_USEDECLAREFETCH 0 #define DEFAULT_USEDECLAREFETCH 0
#define DEFAULT_TEXTASLONGVARCHAR 1 #define DEFAULT_TEXTASLONGVARCHAR 1
#define DEFAULT_UNKNOWNSASLONGVARCHAR 0 #define DEFAULT_UNKNOWNSASLONGVARCHAR 0
...@@ -118,8 +127,8 @@ ...@@ -118,8 +127,8 @@
void getGlobalDefaults(char *section, char *filename, char override); void getGlobalDefaults(char *section, char *filename, char override);
#ifdef WIN32 #ifdef WIN32
void SetDlgStuff(HWND hdlg, ConnInfo *ci); void SetDlgStuff(HWND hdlg, ConnInfo * ci);
void GetDlgStuff(HWND hdlg, ConnInfo *ci); void GetDlgStuff(HWND hdlg, ConnInfo * ci);
int CALLBACK driver_optionsProc(HWND hdlg, int CALLBACK driver_optionsProc(HWND hdlg,
WORD wMsg, WORD wMsg,
...@@ -129,14 +138,15 @@ int CALLBACK ds_optionsProc(HWND hdlg, ...@@ -129,14 +138,15 @@ int CALLBACK ds_optionsProc(HWND hdlg,
WORD wMsg, WORD wMsg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam); LPARAM lParam);
#endif /* WIN32 */ #endif /* WIN32 */
void updateGlobals(void); void updateGlobals(void);
void writeDSNinfo(ConnInfo *ci); void writeDSNinfo(ConnInfo * ci);
void getDSNdefaults(ConnInfo *ci); void getDSNdefaults(ConnInfo * ci);
void getDSNinfo(ConnInfo *ci, char overwrite); void getDSNinfo(ConnInfo * ci, char overwrite);
void makeConnectString(char *connect_string, ConnInfo *ci); void makeConnectString(char *connect_string, ConnInfo * ci);
void copyAttributes(ConnInfo *ci, char *attribute, char *value); void copyAttributes(ConnInfo * ci, char *attribute, char *value);
#endif #endif
...@@ -52,45 +52,50 @@ ...@@ -52,45 +52,50 @@
#include "dlg_specific.h" #include "dlg_specific.h"
/* prototypes */ /* prototypes */
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci); void dconn_get_connect_attributes(UCHAR FAR * connect_string, ConnInfo * ci);
#ifdef WIN32 #ifdef WIN32
BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam); BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci); RETCODE dconn_DoDialog(HWND hwnd, ConnInfo * ci);
extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */
#endif #endif
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
RETCODE SQL_API SQLDriverConnect( RETCODE SQL_API
SQLDriverConnect(
HDBC hdbc, HDBC hdbc,
HWND hwnd, HWND hwnd,
UCHAR FAR *szConnStrIn, UCHAR FAR * szConnStrIn,
SWORD cbConnStrIn, SWORD cbConnStrIn,
UCHAR FAR *szConnStrOut, UCHAR FAR * szConnStrOut,
SWORD cbConnStrOutMax, SWORD cbConnStrOutMax,
SWORD FAR *pcbConnStrOut, SWORD FAR * pcbConnStrOut,
UWORD fDriverCompletion) UWORD fDriverCompletion)
{ {
static char *func = "SQLDriverConnect"; static char *func = "SQLDriverConnect";
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci; ConnInfo *ci;
#ifdef WIN32 #ifdef WIN32
RETCODE dialog_result; RETCODE dialog_result;
#endif #endif
RETCODE result; RETCODE result;
char connStrIn[MAX_CONNECT_STRING]; char connStrIn[MAX_CONNECT_STRING];
char connStrOut[MAX_CONNECT_STRING]; char connStrOut[MAX_CONNECT_STRING];
int retval; int retval;
char password_required = FALSE; char password_required = FALSE;
int len = 0; int len = 0;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -120,13 +125,13 @@ dialog: ...@@ -120,13 +125,13 @@ dialog:
#endif #endif
ci->focus_password = password_required; ci->focus_password = password_required;
switch(fDriverCompletion) { switch (fDriverCompletion)
{
#ifdef WIN32 #ifdef WIN32
case SQL_DRIVER_PROMPT: case SQL_DRIVER_PROMPT:
dialog_result = dconn_DoDialog(hwnd, ci); dialog_result = dconn_DoDialog(hwnd, ci);
if(dialog_result != SQL_SUCCESS) { if (dialog_result != SQL_SUCCESS)
return dialog_result; return dialog_result;
}
break; break;
case SQL_DRIVER_COMPLETE_REQUIRED: case SQL_DRIVER_COMPLETE_REQUIRED:
...@@ -136,17 +141,17 @@ dialog: ...@@ -136,17 +141,17 @@ dialog:
case SQL_DRIVER_COMPLETE: case SQL_DRIVER_COMPLETE:
/* Password is not a required parameter. */ /* Password is not a required parameter. */
if( ci->username[0] == '\0' || if (ci->username[0] == '\0' ||
ci->server[0] == '\0' || ci->server[0] == '\0' ||
ci->database[0] == '\0' || ci->database[0] == '\0' ||
ci->port[0] == '\0' || ci->port[0] == '\0' ||
password_required) { password_required)
{
dialog_result = dconn_DoDialog(hwnd, ci); dialog_result = dconn_DoDialog(hwnd, ci);
if(dialog_result != SQL_SUCCESS) { if (dialog_result != SQL_SUCCESS)
return dialog_result; return dialog_result;
} }
}
break; break;
#else #else
case SQL_DRIVER_PROMPT: case SQL_DRIVER_PROMPT:
...@@ -157,14 +162,17 @@ dialog: ...@@ -157,14 +162,17 @@ dialog:
break; break;
} }
/* Password is not a required parameter unless authentication asks for it. /*
For now, I think it's better to just let the application ask over and over until * Password is not a required parameter unless authentication asks for
a password is entered (the user can always hit Cancel to get out) * it. For now, I think it's better to just let the application ask
* over and over until a password is entered (the user can always hit
* Cancel to get out)
*/ */
if( ci->username[0] == '\0' || if (ci->username[0] == '\0' ||
ci->server[0] == '\0' || ci->server[0] == '\0' ||
ci->database[0] == '\0' || ci->database[0] == '\0' ||
ci->port[0] == '\0') { ci->port[0] == '\0')
{
/* (password_required && ci->password[0] == '\0')) */ /* (password_required && ci->password[0] == '\0')) */
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
...@@ -173,12 +181,16 @@ dialog: ...@@ -173,12 +181,16 @@ dialog:
/* do the actual connect */ /* do the actual connect */
retval = CC_connect(conn, password_required); retval = CC_connect(conn, password_required);
if (retval < 0) { /* need a password */ if (retval < 0)
if (fDriverCompletion == SQL_DRIVER_NOPROMPT) { { /* need a password */
if (fDriverCompletion == SQL_DRIVER_NOPROMPT)
{
CC_log_error(func, "Need password but Driver_NoPrompt", conn); CC_log_error(func, "Need password but Driver_NoPrompt", conn);
return SQL_ERROR; /* need a password but not allowed to prompt so error */ return SQL_ERROR; /* need a password but not allowed to
* prompt so error */
} }
else { else
{
#ifdef WIN32 #ifdef WIN32
password_required = TRUE; password_required = TRUE;
goto dialog; goto dialog;
...@@ -187,7 +199,8 @@ dialog: ...@@ -187,7 +199,8 @@ dialog:
#endif #endif
} }
} }
else if (retval == 0) { else if (retval == 0)
{
/* error msg filled in above */ /* error msg filled in above */
CC_log_error(func, "Error from CC_Connect", conn); CC_log_error(func, "Error from CC_Connect", conn);
return SQL_ERROR; return SQL_ERROR;
...@@ -201,25 +214,29 @@ dialog: ...@@ -201,25 +214,29 @@ dialog:
makeConnectString(connStrOut, ci); makeConnectString(connStrOut, ci);
len = strlen(connStrOut); len = strlen(connStrOut);
if(szConnStrOut) { if (szConnStrOut)
{
/* Return the completed string to the caller. The correct method is to
only construct the connect string if a dialog was put up, otherwise, /*
it should just copy the connection input string to the output. * Return the completed string to the caller. The correct method
However, it seems ok to just always construct an output string. There * is to only construct the connect string if a dialog was put up,
are possible bad side effects on working applications (Access) by * otherwise, it should just copy the connection input string to
implementing the correct behavior, anyway. * the output. However, it seems ok to just always construct an
* output string. There are possible bad side effects on working
* applications (Access) by implementing the correct behavior,
* anyway.
*/ */
strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax); strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);
if (len >= cbConnStrOutMax) { if (len >= cbConnStrOutMax)
{
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
conn->errornumber = CONN_TRUNCATED; conn->errornumber = CONN_TRUNCATED;
conn->errormsg = "The buffer was too small for the result."; conn->errormsg = "The buffer was too small for the result.";
} }
} }
if(pcbConnStrOut) if (pcbConnStrOut)
*pcbConnStrOut = len; *pcbConnStrOut = len;
mylog("szConnStrOut = '%s'\n", szConnStrOut); mylog("szConnStrOut = '%s'\n", szConnStrOut);
...@@ -231,35 +248,38 @@ dialog: ...@@ -231,35 +248,38 @@ dialog:
} }
#ifdef WIN32 #ifdef WIN32
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci) RETCODE
dconn_DoDialog(HWND hwnd, ConnInfo * ci)
{ {
int dialog_result; int dialog_result;
mylog("dconn_DoDialog: ci = %u\n", ci); mylog("dconn_DoDialog: ci = %u\n", ci);
if(hwnd) { if (hwnd)
{
dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_CONFIG), dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_CONFIG),
hwnd, dconn_FDriverConnectProc, (LPARAM) ci); hwnd, dconn_FDriverConnectProc, (LPARAM) ci);
if(!dialog_result || (dialog_result == -1)) { if (!dialog_result || (dialog_result == -1))
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} else { else
return SQL_SUCCESS; return SQL_SUCCESS;
} }
}
return SQL_ERROR; return SQL_ERROR;
} }
BOOL FAR PASCAL dconn_FDriverConnectProc( BOOL FAR PASCAL
dconn_FDriverConnectProc(
HWND hdlg, HWND hdlg,
UINT wMsg, UINT wMsg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
ConnInfo *ci; ConnInfo *ci;
switch (wMsg) { switch (wMsg)
{
case WM_INITDIALOG: case WM_INITDIALOG:
ci = (ConnInfo *) lParam; ci = (ConnInfo *) lParam;
...@@ -274,7 +294,8 @@ ConnInfo *ci; ...@@ -274,7 +294,8 @@ ConnInfo *ci;
ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE);
SetWindowLong(hdlg, DWL_USER, lParam);/* Save the ConnInfo for the "OK" */ SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for
* the "OK" */
SetDlgStuff(hdlg, ci); SetDlgStuff(hdlg, ci);
...@@ -293,7 +314,8 @@ ConnInfo *ci; ...@@ -293,7 +314,8 @@ ConnInfo *ci;
break; break;
case WM_COMMAND: case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) { switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK: case IDOK:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER); ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
...@@ -328,11 +350,15 @@ ConnInfo *ci; ...@@ -328,11 +350,15 @@ ConnInfo *ci;
#endif /* WIN32 */ #endif /* WIN32 */
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci) void
dconn_get_connect_attributes(UCHAR FAR * connect_string, ConnInfo * ci)
{ {
char *our_connect_string; char *our_connect_string;
char *pair, *attribute, *value, *equals; char *pair,
char *strtok_arg; *attribute,
*value,
*equals;
char *strtok_arg;
memset(ci, 0, sizeof(ConnInfo)); memset(ci, 0, sizeof(ConnInfo));
...@@ -341,17 +367,16 @@ char *strtok_arg; ...@@ -341,17 +367,16 @@ char *strtok_arg;
mylog("our_connect_string = '%s'\n", our_connect_string); mylog("our_connect_string = '%s'\n", our_connect_string);
while(1) { while (1)
{
pair = strtok(strtok_arg, ";"); pair = strtok(strtok_arg, ";");
if(strtok_arg) { if (strtok_arg)
strtok_arg = 0; strtok_arg = 0;
} if (!pair)
if(!pair) {
break; break;
}
equals = strchr(pair, '='); equals = strchr(pair, '=');
if ( ! equals) if (!equals)
continue; continue;
*equals = '\0'; *equals = '\0';
...@@ -360,7 +385,7 @@ char *strtok_arg; ...@@ -360,7 +385,7 @@ char *strtok_arg;
mylog("attribute = '%s', value = '%s'\n", attribute, value); mylog("attribute = '%s', value = '%s'\n", attribute, value);
if( !attribute || !value) if (!attribute || !value)
continue; continue;
/* Copy the appropriate value to the conninfo */ /* Copy the appropriate value to the conninfo */
...@@ -371,4 +396,3 @@ char *strtok_arg; ...@@ -371,4 +396,3 @@ char *strtok_arg;
free(our_connect_string); free(our_connect_string);
} }
...@@ -22,14 +22,16 @@ ...@@ -22,14 +22,16 @@
ConnectionClass *conns[MAX_CONNECTIONS]; ConnectionClass *conns[MAX_CONNECTIONS];
RETCODE SQL_API SQLAllocEnv(HENV FAR *phenv) RETCODE SQL_API
SQLAllocEnv(HENV FAR * phenv)
{ {
static char *func = "SQLAllocEnv"; static char *func = "SQLAllocEnv";
mylog("**** in SQLAllocEnv ** \n"); mylog("**** in SQLAllocEnv ** \n");
*phenv = (HENV) EN_Constructor(); *phenv = (HENV) EN_Constructor();
if ( ! *phenv) { if (!*phenv)
{
*phenv = SQL_NULL_HENV; *phenv = SQL_NULL_HENV;
EN_log_error(func, "Error allocating environment", NULL); EN_log_error(func, "Error allocating environment", NULL);
return SQL_ERROR; return SQL_ERROR;
...@@ -39,14 +41,16 @@ mylog("**** in SQLAllocEnv ** \n"); ...@@ -39,14 +41,16 @@ mylog("**** in SQLAllocEnv ** \n");
return SQL_SUCCESS; return SQL_SUCCESS;
} }
RETCODE SQL_API SQLFreeEnv(HENV henv) RETCODE SQL_API
SQLFreeEnv(HENV henv)
{ {
static char *func = "SQLFreeEnv"; static char *func = "SQLFreeEnv";
EnvironmentClass *env = (EnvironmentClass *) henv; EnvironmentClass *env = (EnvironmentClass *) henv;
mylog("**** in SQLFreeEnv: env = %u ** \n", env); mylog("**** in SQLFreeEnv: env = %u ** \n", env);
if (env && EN_Destructor(env)) { if (env && EN_Destructor(env))
{
mylog(" ok\n"); mylog(" ok\n");
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -58,28 +62,32 @@ mylog("**** in SQLFreeEnv: env = %u ** \n", env); ...@@ -58,28 +62,32 @@ mylog("**** in SQLFreeEnv: env = %u ** \n", env);
/* Returns the next SQL error information. */ /* Returns the next SQL error information. */
RETCODE SQL_API SQLError( RETCODE SQL_API
SQLError(
HENV henv, HENV henv,
HDBC hdbc, HDBC hdbc,
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR *szSqlState, UCHAR FAR * szSqlState,
SDWORD FAR *pfNativeError, SDWORD FAR * pfNativeError,
UCHAR FAR *szErrorMsg, UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax, SWORD cbErrorMsgMax,
SWORD FAR *pcbErrorMsg) SWORD FAR * pcbErrorMsg)
{ {
char *msg; char *msg;
int status; int status;
mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u\n", henv, hdbc, hstmt); mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u\n", henv, hdbc, hstmt);
if (SQL_NULL_HSTMT != hstmt) { if (SQL_NULL_HSTMT != hstmt)
{
/* CC: return an error of a hstmt */ /* CC: return an error of a hstmt */
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
if (SC_get_error(stmt, &status, &msg)) { if (SC_get_error(stmt, &status, &msg))
{
mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg); mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg) { if (NULL == msg)
{
if (NULL != szSqlState) if (NULL != szSqlState)
strcpy(szSqlState, "00000"); strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
...@@ -90,7 +98,7 @@ int status; ...@@ -90,7 +98,7 @@ int status;
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
*pcbErrorMsg = (SWORD)strlen(msg); *pcbErrorMsg = (SWORD) strlen(msg);
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax); strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
...@@ -100,7 +108,8 @@ int status; ...@@ -100,7 +108,8 @@ int status;
if (NULL != szSqlState) if (NULL != szSqlState)
switch (status) { switch (status)
{
/* now determine the SQLSTATE to be returned */ /* now determine the SQLSTATE to be returned */
case STMT_TRUNCATED: case STMT_TRUNCATED:
strcpy(szSqlState, "01004"); strcpy(szSqlState, "01004");
...@@ -152,7 +161,8 @@ int status; ...@@ -152,7 +161,8 @@ int status;
break; break;
case STMT_NOT_IMPLEMENTED_ERROR: case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00"); /* == 'driver not capable' */ strcpy(szSqlState, "S1C00"); /* == 'driver not
* capable' */
break; break;
case STMT_OPTION_OUT_OF_RANGE_ERROR: case STMT_OPTION_OUT_OF_RANGE_ERROR:
strcpy(szSqlState, "S1092"); strcpy(szSqlState, "S1092");
...@@ -203,7 +213,9 @@ int status; ...@@ -203,7 +213,9 @@ int status;
mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg); mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
} else { }
else
{
if (NULL != szSqlState) if (NULL != szSqlState)
strcpy(szSqlState, "00000"); strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
...@@ -216,13 +228,17 @@ int status; ...@@ -216,13 +228,17 @@ int status;
} }
return SQL_SUCCESS; return SQL_SUCCESS;
} else if (SQL_NULL_HDBC != hdbc) { }
else if (SQL_NULL_HDBC != hdbc)
{
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
mylog("calling CC_get_error\n"); mylog("calling CC_get_error\n");
if (CC_get_error(conn, &status, &msg)) { if (CC_get_error(conn, &status, &msg))
{
mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg); mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg) { if (NULL == msg)
{
if (NULL != szSqlState) if (NULL != szSqlState)
strcpy(szSqlState, "00000"); strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
...@@ -234,14 +250,15 @@ int status; ...@@ -234,14 +250,15 @@ int status;
} }
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
*pcbErrorMsg = (SWORD)strlen(msg); *pcbErrorMsg = (SWORD) strlen(msg);
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax); strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError) if (NULL != pfNativeError)
*pfNativeError = status; *pfNativeError = status;
if (NULL != szSqlState) if (NULL != szSqlState)
switch(status) { switch (status)
{
case STMT_OPTION_VALUE_CHANGED: case STMT_OPTION_VALUE_CHANGED:
case CONN_OPTION_VALUE_CHANGED: case CONN_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02"); strcpy(szSqlState, "01S02");
...@@ -280,7 +297,11 @@ int status; ...@@ -280,7 +297,11 @@ int status;
break; break;
case CONN_TRANSACT_IN_PROGRES: case CONN_TRANSACT_IN_PROGRES:
strcpy(szSqlState, "S1010"); strcpy(szSqlState, "S1010");
/* when the user tries to switch commit mode in a transaction */
/*
* when the user tries to switch commit mode in a
* transaction
*/
/* -> function sequence error */ /* -> function sequence error */
break; break;
case CONN_NO_MEMORY_ERROR: case CONN_NO_MEMORY_ERROR:
...@@ -302,7 +323,9 @@ int status; ...@@ -302,7 +323,9 @@ int status;
break; break;
} }
} else { }
else
{
mylog("CC_Get_error returned nothing.\n"); mylog("CC_Get_error returned nothing.\n");
if (NULL != szSqlState) if (NULL != szSqlState)
strcpy(szSqlState, "00000"); strcpy(szSqlState, "00000");
...@@ -315,11 +338,16 @@ int status; ...@@ -315,11 +338,16 @@ int status;
} }
return SQL_SUCCESS; return SQL_SUCCESS;
} else if (SQL_NULL_HENV != henv) { }
EnvironmentClass *env = (EnvironmentClass *)henv; else if (SQL_NULL_HENV != henv)
if(EN_get_error(env, &status, &msg)) { {
EnvironmentClass *env = (EnvironmentClass *) henv;
if (EN_get_error(env, &status, &msg))
{
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg); mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg) { if (NULL == msg)
{
if (NULL != szSqlState) if (NULL != szSqlState)
strcpy(szSqlState, "00000"); strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
...@@ -331,14 +359,16 @@ int status; ...@@ -331,14 +359,16 @@ int status;
} }
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
*pcbErrorMsg = (SWORD)strlen(msg); *pcbErrorMsg = (SWORD) strlen(msg);
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax); strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError) if (NULL != pfNativeError)
*pfNativeError = status; *pfNativeError = status;
if(szSqlState) { if (szSqlState)
switch(status) { {
switch (status)
{
case ENV_ALLOC_ERROR: case ENV_ALLOC_ERROR:
/* memory allocation failure */ /* memory allocation failure */
strcpy(szSqlState, "S1001"); strcpy(szSqlState, "S1001");
...@@ -349,7 +379,9 @@ int status; ...@@ -349,7 +379,9 @@ int status;
break; break;
} }
} }
} else { }
else
{
if (NULL != szSqlState) if (NULL != szSqlState)
strcpy(szSqlState, "00000"); strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
...@@ -382,12 +414,13 @@ int status; ...@@ -382,12 +414,13 @@ int status;
EnvironmentClass EnvironmentClass
*EN_Constructor(void) * EN_Constructor(void)
{ {
EnvironmentClass *rv; EnvironmentClass *rv;
rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass)); rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass));
if( rv) { if (rv)
{
rv->errormsg = 0; rv->errormsg = 0;
rv->errornumber = 0; rv->errornumber = 0;
} }
...@@ -397,10 +430,10 @@ EnvironmentClass *rv; ...@@ -397,10 +430,10 @@ EnvironmentClass *rv;
char char
EN_Destructor(EnvironmentClass *self) EN_Destructor(EnvironmentClass * self)
{ {
int lf; int lf;
char rv = 1; char rv = 1;
mylog("in EN_Destructor, self=%u\n", self); mylog("in EN_Destructor, self=%u\n", self);
...@@ -408,7 +441,8 @@ char rv = 1; ...@@ -408,7 +441,8 @@ char rv = 1;
/* the source--they should not be freed */ /* the source--they should not be freed */
/* Free any connections belonging to this environment */ /* Free any connections belonging to this environment */
for (lf = 0; lf < MAX_CONNECTIONS; lf++) { for (lf = 0; lf < MAX_CONNECTIONS; lf++)
{
if (conns[lf] && conns[lf]->henv == self) if (conns[lf] && conns[lf]->henv == self)
rv = rv && CC_Destructor(conns[lf]); rv = rv && CC_Destructor(conns[lf]);
} }
...@@ -418,28 +452,31 @@ char rv = 1; ...@@ -418,28 +452,31 @@ char rv = 1;
} }
char char
EN_get_error(EnvironmentClass *self, int *number, char **message) EN_get_error(EnvironmentClass * self, int *number, char **message)
{ {
if(self && self->errormsg && self->errornumber) { if (self && self->errormsg && self->errornumber)
{
*message = self->errormsg; *message = self->errormsg;
*number = self->errornumber; *number = self->errornumber;
self->errormsg = 0; self->errormsg = 0;
self->errornumber = 0; self->errornumber = 0;
return 1; return 1;
} else {
return 0;
} }
else
return 0;
} }
char char
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn) EN_add_connection(EnvironmentClass * self, ConnectionClass * conn)
{ {
int i; int i;
mylog("EN_add_connection: self = %u, conn = %u\n", self, conn); mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
for (i = 0; i < MAX_CONNECTIONS; i++) { for (i = 0; i < MAX_CONNECTIONS; i++)
if ( ! conns[i]) { {
if (!conns[i])
{
conn->henv = self; conn->henv = self;
conns[i] = conn; conns[i] = conn;
...@@ -453,12 +490,13 @@ mylog("EN_add_connection: self = %u, conn = %u\n", self, conn); ...@@ -453,12 +490,13 @@ mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
} }
char char
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn) EN_remove_connection(EnvironmentClass * self, ConnectionClass * conn)
{ {
int i; int i;
for (i = 0; i < MAX_CONNECTIONS; i++) for (i = 0; i < MAX_CONNECTIONS; i++)
if (conns[i] == conn && conns[i]->status != CONN_EXECUTING) { if (conns[i] == conn && conns[i]->status != CONN_EXECUTING)
{
conns[i] = NULL; conns[i] = NULL;
return TRUE; return TRUE;
} }
...@@ -467,11 +505,10 @@ int i; ...@@ -467,11 +505,10 @@ int i;
} }
void void
EN_log_error(char *func, char *desc, EnvironmentClass *self) EN_log_error(char *func, char *desc, EnvironmentClass * self)
{ {
if (self) { if (self)
qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg); qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
}
else else
qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc); qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
} }
...@@ -29,17 +29,18 @@ ...@@ -29,17 +29,18 @@
#define ENV_ALLOC_ERROR 1 #define ENV_ALLOC_ERROR 1
/********** Environment Handle *************/ /********** Environment Handle *************/
struct EnvironmentClass_ { struct EnvironmentClass_
{
char *errormsg; char *errormsg;
int errornumber; int errornumber;
}; };
/* Environment prototypes */ /* Environment prototypes */
EnvironmentClass *EN_Constructor(void); EnvironmentClass *EN_Constructor(void);
char EN_Destructor(EnvironmentClass *self); char EN_Destructor(EnvironmentClass * self);
char EN_get_error(EnvironmentClass *self, int *number, char **message); char EN_get_error(EnvironmentClass * self, int *number, char **message);
char EN_add_connection(EnvironmentClass *self, ConnectionClass *conn); char EN_add_connection(EnvironmentClass * self, ConnectionClass * conn);
char EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn); char EN_remove_connection(EnvironmentClass * self, ConnectionClass * conn);
void EN_log_error(char *func, char *desc, EnvironmentClass *self); void EN_log_error(char *func, char *desc, EnvironmentClass * self);
#endif #endif
...@@ -39,33 +39,40 @@ extern GLOBAL_VALUES globals; ...@@ -39,33 +39,40 @@ extern GLOBAL_VALUES globals;
/* Perform a Prepare on the SQL statement */ /* Perform a Prepare on the SQL statement */
RETCODE SQL_API SQLPrepare(HSTMT hstmt, RETCODE SQL_API
UCHAR FAR *szSqlStr, SQLPrepare(HSTMT hstmt,
UCHAR FAR * szSqlStr,
SDWORD cbSqlStr) SDWORD cbSqlStr)
{ {
static char *func = "SQLPrepare"; static char *func = "SQLPrepare";
StatementClass *self = (StatementClass *) hstmt; StatementClass *self = (StatementClass *) hstmt;
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! self) { if (!self)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
/* According to the ODBC specs it is valid to call SQLPrepare mulitple times. /*
In that case, the bound SQL statement is replaced by the new one * According to the ODBC specs it is valid to call SQLPrepare mulitple
* times. In that case, the bound SQL statement is replaced by the new
* one
*/ */
switch(self->status) { switch (self->status)
{
case STMT_PREMATURE: case STMT_PREMATURE:
mylog("**** SQLPrepare: STMT_PREMATURE, recycle\n"); mylog("**** SQLPrepare: STMT_PREMATURE, recycle\n");
SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */ SC_recycle_statement(self); /* recycle the statement, but do
* not remove parameter bindings */
break; break;
case STMT_FINISHED: case STMT_FINISHED:
mylog("**** SQLPrepare: STMT_FINISHED, recycle\n"); mylog("**** SQLPrepare: STMT_FINISHED, recycle\n");
SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */ SC_recycle_statement(self); /* recycle the statement, but do
* not remove parameter bindings */
break; break;
case STMT_ALLOCATED: case STMT_ALLOCATED:
...@@ -97,7 +104,8 @@ StatementClass *self = (StatementClass *) hstmt; ...@@ -97,7 +104,8 @@ StatementClass *self = (StatementClass *) hstmt;
free(self->statement); free(self->statement);
self->statement = make_string(szSqlStr, cbSqlStr, NULL); self->statement = make_string(szSqlStr, cbSqlStr, NULL);
if ( ! self->statement) { if (!self->statement)
{
self->errornumber = STMT_NO_MEMORY_ERROR; self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "No memory available to store statement"; self->errormsg = "No memory available to store statement";
SC_log_error(func, "", self); SC_log_error(func, "", self);
...@@ -108,7 +116,8 @@ StatementClass *self = (StatementClass *) hstmt; ...@@ -108,7 +116,8 @@ StatementClass *self = (StatementClass *) hstmt;
self->statement_type = statement_type(self->statement); self->statement_type = statement_type(self->statement);
/* Check if connection is onlyread (only selects are allowed) */ /* Check if connection is onlyread (only selects are allowed) */
if ( CC_is_onlyread(self->hdbc) && STMT_UPDATE(self)) { if (CC_is_onlyread(self->hdbc) && STMT_UPDATE(self))
{
self->errornumber = STMT_EXEC_ERROR; self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Connection is readonly, only select statements are allowed."; self->errormsg = "Connection is readonly, only select statements are allowed.";
SC_log_error(func, "", self); SC_log_error(func, "", self);
...@@ -124,18 +133,20 @@ StatementClass *self = (StatementClass *) hstmt; ...@@ -124,18 +133,20 @@ StatementClass *self = (StatementClass *) hstmt;
/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */ /* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
RETCODE SQL_API SQLExecDirect( RETCODE SQL_API
SQLExecDirect(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR *szSqlStr, UCHAR FAR * szSqlStr,
SDWORD cbSqlStr) SDWORD cbSqlStr)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
RETCODE result; RETCODE result;
static char *func = "SQLExecDirect"; static char *func = "SQLExecDirect";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -146,7 +157,8 @@ static char *func = "SQLExecDirect"; ...@@ -146,7 +157,8 @@ static char *func = "SQLExecDirect";
/* keep a copy of the un-parametrized statement, in case */ /* keep a copy of the un-parametrized statement, in case */
/* they try to execute this statement again */ /* they try to execute this statement again */
stmt->statement = make_string(szSqlStr, cbSqlStr, NULL); stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
if ( ! stmt->statement) { if (!stmt->statement)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "No memory available to store statement"; stmt->errormsg = "No memory available to store statement";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -160,13 +172,14 @@ static char *func = "SQLExecDirect"; ...@@ -160,13 +172,14 @@ static char *func = "SQLExecDirect";
/* If an SQLPrepare was performed prior to this, but was left in */ /* If an SQLPrepare was performed prior to this, but was left in */
/* the premature state because an error occurred prior to SQLExecute */ /* the premature state because an error occurred prior to SQLExecute */
/* then set the statement to finished so it can be recycled. */ /* then set the statement to finished so it can be recycled. */
if ( stmt->status == STMT_PREMATURE ) if (stmt->status == STMT_PREMATURE)
stmt->status = STMT_FINISHED; stmt->status = STMT_FINISHED;
stmt->statement_type = statement_type(stmt->statement); stmt->statement_type = statement_type(stmt->statement);
/* Check if connection is onlyread (only selects are allowed) */ /* Check if connection is onlyread (only selects are allowed) */
if ( CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt)) { if (CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt))
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Connection is readonly, only select statements are allowed."; stmt->errormsg = "Connection is readonly, only select statements are allowed.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -182,34 +195,41 @@ static char *func = "SQLExecDirect"; ...@@ -182,34 +195,41 @@ static char *func = "SQLExecDirect";
} }
/* Execute a prepared SQL statement */ /* Execute a prepared SQL statement */
RETCODE SQL_API SQLExecute( RETCODE SQL_API
SQLExecute(
HSTMT hstmt) HSTMT hstmt)
{ {
static char *func="SQLExecute"; static char *func = "SQLExecute";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
ConnectionClass *conn; ConnectionClass *conn;
int i, retval; int i,
retval;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func); mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
/* If the statement is premature, it means we already executed /*
it from an SQLPrepare/SQLDescribeCol type of scenario. So * If the statement is premature, it means we already executed it from
just return success. * an SQLPrepare/SQLDescribeCol type of scenario. So just return
* success.
*/ */
if ( stmt->prepare && stmt->status == STMT_PREMATURE) { if (stmt->prepare && stmt->status == STMT_PREMATURE)
{
stmt->status = STMT_FINISHED; stmt->status = STMT_FINISHED;
if (stmt->errormsg == NULL) { if (stmt->errormsg == NULL)
{
mylog("%s: premature statement but return SQL_SUCCESS\n", func); mylog("%s: premature statement but return SQL_SUCCESS\n", func);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
else { else
{
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
mylog("%s: premature statement so return SQL_ERROR\n", func); mylog("%s: premature statement so return SQL_ERROR\n", func);
return SQL_ERROR; return SQL_ERROR;
...@@ -221,7 +241,8 @@ int i, retval; ...@@ -221,7 +241,8 @@ int i, retval;
SC_clear_error(stmt); SC_clear_error(stmt);
conn = SC_get_conn(stmt); conn = SC_get_conn(stmt);
if (conn->status == CONN_EXECUTING) { if (conn->status == CONN_EXECUTING)
{
stmt->errormsg = "Connection is already in use."; stmt->errormsg = "Connection is already in use.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -229,7 +250,8 @@ int i, retval; ...@@ -229,7 +250,8 @@ int i, retval;
return SQL_ERROR; return SQL_ERROR;
} }
if ( ! stmt->statement) { if (!stmt->statement)
{
stmt->errornumber = STMT_NO_STMTSTRING; stmt->errornumber = STMT_NO_STMTSTRING;
stmt->errormsg = "This handle does not have a SQL statement stored in it"; stmt->errormsg = "This handle does not have a SQL statement stored in it";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -237,18 +259,21 @@ int i, retval; ...@@ -237,18 +259,21 @@ int i, retval;
return SQL_ERROR; return SQL_ERROR;
} }
/* If SQLExecute is being called again, recycle the statement. /*
Note this should have been done by the application in a call * If SQLExecute is being called again, recycle the statement. Note
to SQLFreeStmt(SQL_CLOSE) or SQLCancel. * this should have been done by the application in a call to
* SQLFreeStmt(SQL_CLOSE) or SQLCancel.
*/ */
if (stmt->status == STMT_FINISHED) { if (stmt->status == STMT_FINISHED)
{
mylog("%s: recycling statement (should have been done by app)...\n", func); mylog("%s: recycling statement (should have been done by app)...\n", func);
SC_recycle_statement(stmt); SC_recycle_statement(stmt);
} }
/* Check if the statement is in the correct state */ /* Check if the statement is in the correct state */
if ((stmt->prepare && stmt->status != STMT_READY) || if ((stmt->prepare && stmt->status != STMT_READY) ||
(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY)) { (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
{
stmt->errornumber = STMT_STATUS_ERROR; stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "The handle does not point to a statement that is ready to be executed"; stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
...@@ -258,13 +283,16 @@ int i, retval; ...@@ -258,13 +283,16 @@ int i, retval;
} }
/* The bound parameters could have possibly changed since the last execute /*
of this statement? Therefore check for params and re-copy. * The bound parameters could have possibly changed since the last
* execute of this statement? Therefore check for params and re-copy.
*/ */
stmt->data_at_exec = -1; stmt->data_at_exec = -1;
for (i = 0; i < stmt->parameters_allocated; i++) { for (i = 0; i < stmt->parameters_allocated; i++)
{
/* Check for data at execution parameters */ /* Check for data at execution parameters */
if ( stmt->parameters[i].data_at_exec == TRUE) { if (stmt->parameters[i].data_at_exec == TRUE)
{
if (stmt->data_at_exec < 0) if (stmt->data_at_exec < 0)
stmt->data_at_exec = 1; stmt->data_at_exec = 1;
else else
...@@ -272,7 +300,11 @@ int i, retval; ...@@ -272,7 +300,11 @@ int i, retval;
} }
} }
/* If there are some data at execution parameters, return need data */ /* If there are some data at execution parameters, return need data */
/* SQLParamData and SQLPutData will be used to send params and execute the statement. */
/*
* SQLParamData and SQLPutData will be used to send params and execute
* the statement.
*/
if (stmt->data_at_exec > 0) if (stmt->data_at_exec > 0)
return SQL_NEED_DATA; return SQL_NEED_DATA;
...@@ -281,7 +313,7 @@ int i, retval; ...@@ -281,7 +313,7 @@ int i, retval;
/* Create the statement with parameters substituted. */ /* Create the statement with parameters substituted. */
retval = copy_statement_with_parameters(stmt); retval = copy_statement_with_parameters(stmt);
if( retval != SQL_SUCCESS) if (retval != SQL_SUCCESS)
/* error msg passed from above */ /* error msg passed from above */
return retval; return retval;
...@@ -296,34 +328,40 @@ int i, retval; ...@@ -296,34 +328,40 @@ int i, retval;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLTransact( RETCODE SQL_API
SQLTransact(
HENV henv, HENV henv,
HDBC hdbc, HDBC hdbc,
UWORD fType) UWORD fType)
{ {
static char *func = "SQLTransact"; static char *func = "SQLTransact";
extern ConnectionClass *conns[]; extern ConnectionClass *conns[];
ConnectionClass *conn; ConnectionClass *conn;
QResultClass *res; QResultClass *res;
char ok, *stmt_string; char ok,
int lf; *stmt_string;
int lf;
mylog("entering %s: hdbc=%u, henv=%u\n", func, hdbc, henv); mylog("entering %s: hdbc=%u, henv=%u\n", func, hdbc, henv);
if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV) { if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
/* If hdbc is null and henv is valid, /*
it means transact all connections on that henv. * If hdbc is null and henv is valid, it means transact all
* connections on that henv.
*/ */
if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV) { if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV)
for (lf=0; lf <MAX_CONNECTIONS; lf++) { {
for (lf = 0; lf < MAX_CONNECTIONS; lf++)
{
conn = conns[lf]; conn = conns[lf];
if (conn && conn->henv == henv) if (conn && conn->henv == henv)
if ( SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS) if (SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -332,28 +370,35 @@ int lf; ...@@ -332,28 +370,35 @@ int lf;
conn = (ConnectionClass *) hdbc; conn = (ConnectionClass *) hdbc;
if (fType == SQL_COMMIT) { if (fType == SQL_COMMIT)
{
stmt_string = "COMMIT"; stmt_string = "COMMIT";
} else if (fType == SQL_ROLLBACK) { }
else if (fType == SQL_ROLLBACK)
{
stmt_string = "ROLLBACK"; stmt_string = "ROLLBACK";
} else { }
else
{
conn->errornumber = CONN_INVALID_ARGUMENT_NO; conn->errornumber = CONN_INVALID_ARGUMENT_NO;
conn->errormsg ="SQLTransact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter"; conn->errormsg = "SQLTransact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter";
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
return SQL_ERROR; return SQL_ERROR;
} }
/* If manual commit and in transaction, then proceed. */ /* If manual commit and in transaction, then proceed. */
if ( ! CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) { if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
{
mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string); mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string);
res = CC_send_query(conn, stmt_string, NULL); res = CC_send_query(conn, stmt_string, NULL);
CC_set_no_trans(conn); CC_set_no_trans(conn);
if ( ! res) { if (!res)
{
/* error msg will be in the connection */ /* error msg will be in the connection */
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
return SQL_ERROR; return SQL_ERROR;
...@@ -362,7 +407,8 @@ int lf; ...@@ -362,7 +407,8 @@ int lf;
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -372,48 +418,57 @@ int lf; ...@@ -372,48 +418,57 @@ int lf;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLCancel( RETCODE SQL_API
SQLCancel(
HSTMT hstmt) /* Statement to cancel. */ HSTMT hstmt) /* Statement to cancel. */
{ {
static char *func="SQLCancel"; static char *func = "SQLCancel";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
RETCODE result; RETCODE result;
#ifdef WIN32 #ifdef WIN32
HMODULE hmodule; HMODULE hmodule;
FARPROC addr; FARPROC addr;
#endif #endif
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
/* Check if this can handle canceling in the middle of a SQLPutData? */ /* Check if this can handle canceling in the middle of a SQLPutData? */
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
/* Not in the middle of SQLParamData/SQLPutData so cancel like a close. */ /*
if (stmt->data_at_exec < 0) { * Not in the middle of SQLParamData/SQLPutData so cancel like a
* close.
*/
if (stmt->data_at_exec < 0)
{
/* MAJOR HACK for Windows to reset the driver manager's cursor state: /*
Because of what seems like a bug in the Odbc driver manager, * MAJOR HACK for Windows to reset the driver manager's cursor
SQLCancel does not act like a SQLFreeStmt(CLOSE), as many * state: Because of what seems like a bug in the Odbc driver
applications depend on this behavior. So, this * manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as
brute force method calls the driver manager's function on * many applications depend on this behavior. So, this brute
behalf of the application. * force method calls the driver manager's function on behalf of
* the application.
*/ */
#ifdef WIN32 #ifdef WIN32
if (globals.cancel_as_freestmt) { if (globals.cancel_as_freestmt)
{
hmodule = GetModuleHandle("ODBC32"); hmodule = GetModuleHandle("ODBC32");
addr = GetProcAddress(hmodule, "SQLFreeStmt"); addr = GetProcAddress(hmodule, "SQLFreeStmt");
result = addr( (char *) (stmt->phstmt) - 96, SQL_CLOSE); result = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE);
}
else {
result = SQLFreeStmt( hstmt, SQL_CLOSE);
} }
else
result = SQLFreeStmt(hstmt, SQL_CLOSE);
#else #else
result = SQLFreeStmt( hstmt, SQL_CLOSE); result = SQLFreeStmt(hstmt, SQL_CLOSE);
#endif #endif
mylog("SQLCancel: SQLFreeStmt returned %d\n", result); mylog("SQLCancel: SQLFreeStmt returned %d\n", result);
...@@ -423,7 +478,11 @@ FARPROC addr; ...@@ -423,7 +478,11 @@ FARPROC addr;
} }
/* In the middle of SQLParamData/SQLPutData, so cancel that. */ /* In the middle of SQLParamData/SQLPutData, so cancel that. */
/* Note, any previous data-at-exec buffers will be freed in the recycle */
/*
* Note, any previous data-at-exec buffers will be freed in the
* recycle
*/
/* if they call SQLExecDirect or SQLExecute again. */ /* if they call SQLExecDirect or SQLExecute again. */
stmt->data_at_exec = -1; stmt->data_at_exec = -1;
...@@ -439,24 +498,26 @@ FARPROC addr; ...@@ -439,24 +498,26 @@ FARPROC addr;
/* Returns the SQL string as modified by the driver. */ /* Returns the SQL string as modified by the driver. */
/* Currently, just copy the input string without modification */ /* Currently, just copy the input string without modification */
/* observing buffer limits and truncation. */ /* observing buffer limits and truncation. */
RETCODE SQL_API SQLNativeSql( RETCODE SQL_API
SQLNativeSql(
HDBC hdbc, HDBC hdbc,
UCHAR FAR *szSqlStrIn, UCHAR FAR * szSqlStrIn,
SDWORD cbSqlStrIn, SDWORD cbSqlStrIn,
UCHAR FAR *szSqlStr, UCHAR FAR * szSqlStr,
SDWORD cbSqlStrMax, SDWORD cbSqlStrMax,
SDWORD FAR *pcbSqlStr) SDWORD FAR * pcbSqlStr)
{ {
static char *func="SQLNativeSql"; static char *func = "SQLNativeSql";
int len = 0; int len = 0;
char *ptr; char *ptr;
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
RETCODE result; RETCODE result;
mylog( "%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn); mylog("%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn);
ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL); ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL);
if ( ! ptr) { if (!ptr)
{
conn->errornumber = CONN_NO_MEMORY_ERROR; conn->errornumber = CONN_NO_MEMORY_ERROR;
conn->errormsg = "No memory available to store native sql string"; conn->errormsg = "No memory available to store native sql string";
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
...@@ -466,10 +527,12 @@ RETCODE result; ...@@ -466,10 +527,12 @@ RETCODE result;
result = SQL_SUCCESS; result = SQL_SUCCESS;
len = strlen(ptr); len = strlen(ptr);
if (szSqlStr) { if (szSqlStr)
{
strncpy_null(szSqlStr, ptr, cbSqlStrMax); strncpy_null(szSqlStr, ptr, cbSqlStrMax);
if (len >= cbSqlStrMax) { if (len >= cbSqlStrMax)
{
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
conn->errornumber = STMT_TRUNCATED; conn->errornumber = STMT_TRUNCATED;
conn->errormsg = "The buffer was too small for the result."; conn->errormsg = "The buffer was too small for the result.";
...@@ -489,31 +552,36 @@ RETCODE result; ...@@ -489,31 +552,36 @@ RETCODE result;
/* Supplies parameter data at execution time. Used in conjuction with */ /* Supplies parameter data at execution time. Used in conjuction with */
/* SQLPutData. */ /* SQLPutData. */
RETCODE SQL_API SQLParamData( RETCODE SQL_API
SQLParamData(
HSTMT hstmt, HSTMT hstmt,
PTR FAR *prgbValue) PTR FAR * prgbValue)
{ {
static char *func = "SQLParamData"; static char *func = "SQLParamData";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
int i, retval; int i,
retval;
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated); mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated);
if (stmt->data_at_exec < 0) { if (stmt->data_at_exec < 0)
{
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No execution-time parameters for this statement"; stmt->errormsg = "No execution-time parameters for this statement";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->data_at_exec > stmt->parameters_allocated) { if (stmt->data_at_exec > stmt->parameters_allocated)
{
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Too many execution-time parameters were present"; stmt->errormsg = "Too many execution-time parameters were present";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -521,16 +589,19 @@ int i, retval; ...@@ -521,16 +589,19 @@ int i, retval;
} }
/* close the large object */ /* close the large object */
if ( stmt->lobj_fd >= 0) { if (stmt->lobj_fd >= 0)
{
lo_close(stmt->hdbc, stmt->lobj_fd); lo_close(stmt->hdbc, stmt->lobj_fd);
/* commit transaction if needed */ /* commit transaction if needed */
if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "COMMIT", NULL); res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -538,7 +609,8 @@ int i, retval; ...@@ -538,7 +609,8 @@ int i, retval;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -553,7 +625,8 @@ int i, retval; ...@@ -553,7 +625,8 @@ int i, retval;
/* Done, now copy the params and then execute the statement */ /* Done, now copy the params and then execute the statement */
if (stmt->data_at_exec == 0) { if (stmt->data_at_exec == 0)
{
retval = copy_statement_with_parameters(stmt); retval = copy_statement_with_parameters(stmt);
if (retval != SQL_SUCCESS) if (retval != SQL_SUCCESS)
return retval; return retval;
...@@ -563,14 +636,17 @@ int i, retval; ...@@ -563,14 +636,17 @@ int i, retval;
return SC_execute(stmt); return SC_execute(stmt);
} }
/* Set beginning param; if first time SQLParamData is called , start at 0. /*
Otherwise, start at the last parameter + 1. * Set beginning param; if first time SQLParamData is called , start
* at 0. Otherwise, start at the last parameter + 1.
*/ */
i = stmt->current_exec_param >= 0 ? stmt->current_exec_param+1 : 0; i = stmt->current_exec_param >= 0 ? stmt->current_exec_param + 1 : 0;
/* At least 1 data at execution parameter, so Fill in the token value */ /* At least 1 data at execution parameter, so Fill in the token value */
for ( ; i < stmt->parameters_allocated; i++) { for (; i < stmt->parameters_allocated; i++)
if (stmt->parameters[i].data_at_exec == TRUE) { {
if (stmt->parameters[i].data_at_exec == TRUE)
{
stmt->data_at_exec--; stmt->data_at_exec--;
stmt->current_exec_param = i; stmt->current_exec_param = i;
stmt->put_data = FALSE; stmt->put_data = FALSE;
...@@ -587,26 +663,30 @@ int i, retval; ...@@ -587,26 +663,30 @@ int i, retval;
/* Supplies parameter data at execution time. Used in conjunction with */ /* Supplies parameter data at execution time. Used in conjunction with */
/* SQLParamData. */ /* SQLParamData. */
RETCODE SQL_API SQLPutData( RETCODE SQL_API
SQLPutData(
HSTMT hstmt, HSTMT hstmt,
PTR rgbValue, PTR rgbValue,
SDWORD cbValue) SDWORD cbValue)
{ {
static char *func = "SQLPutData"; static char *func = "SQLPutData";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
int old_pos, retval; int old_pos,
ParameterInfoClass *current_param; retval;
char *buffer; ParameterInfoClass *current_param;
char *buffer;
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if (stmt->current_exec_param < 0) { if (stmt->current_exec_param < 0)
{
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Previous call was not SQLPutData or SQLParamData"; stmt->errormsg = "Previous call was not SQLPutData or SQLParamData";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -615,14 +695,16 @@ char *buffer; ...@@ -615,14 +695,16 @@ char *buffer;
current_param = &(stmt->parameters[stmt->current_exec_param]); current_param = &(stmt->parameters[stmt->current_exec_param]);
if ( ! stmt->put_data) { /* first call */ if (!stmt->put_data)
{ /* first call */
mylog("SQLPutData: (1) cbValue = %d\n", cbValue); mylog("SQLPutData: (1) cbValue = %d\n", cbValue);
stmt->put_data = TRUE; stmt->put_data = TRUE;
current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD)); current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD));
if ( ! current_param->EXEC_used) { if (!current_param->EXEC_used)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (1)"; stmt->errormsg = "Out of memory in SQLPutData (1)";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -636,15 +718,18 @@ char *buffer; ...@@ -636,15 +718,18 @@ char *buffer;
/* Handle Long Var Binary with Large Objects */ /* Handle Long Var Binary with Large Objects */
if ( current_param->SQLType == SQL_LONGVARBINARY) { if (current_param->SQLType == SQL_LONGVARBINARY)
{
/* begin transaction if needed */ /* begin transaction if needed */
if(!CC_is_in_trans(stmt->hdbc)) { if (!CC_is_in_trans(stmt->hdbc))
{
QResultClass *res; QResultClass *res;
char ok; char ok;
res = CC_send_query(stmt->hdbc, "BEGIN", NULL); res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
if (!res) { if (!res)
{
stmt->errormsg = "Could not begin (in-line) a transaction"; stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -652,7 +737,8 @@ char *buffer; ...@@ -652,7 +737,8 @@ char *buffer;
} }
ok = QR_command_successful(res); ok = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
stmt->errormsg = "Could not begin (in-line) a transaction"; stmt->errormsg = "Could not begin (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -664,7 +750,8 @@ char *buffer; ...@@ -664,7 +750,8 @@ char *buffer;
/* store the oid */ /* store the oid */
current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
if (current_param->lobj_oid == 0) { if (current_param->lobj_oid == 0)
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt create large object."; stmt->errormsg = "Couldnt create large object.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -677,7 +764,8 @@ char *buffer; ...@@ -677,7 +764,8 @@ char *buffer;
/* store the fd */ /* store the fd */
stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE); stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE);
if ( stmt->lobj_fd < 0) { if (stmt->lobj_fd < 0)
{
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt open large object for writing."; stmt->errormsg = "Couldnt open large object for writing.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -688,20 +776,26 @@ char *buffer; ...@@ -688,20 +776,26 @@ char *buffer;
mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval); mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
} }
else { /* for handling text fields and small binaries */ else
{ /* for handling text fields and small
* binaries */
if (cbValue == SQL_NTS) { if (cbValue == SQL_NTS)
{
current_param->EXEC_buffer = strdup(rgbValue); current_param->EXEC_buffer = strdup(rgbValue);
if ( ! current_param->EXEC_buffer) { if (!current_param->EXEC_buffer)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (2)"; stmt->errormsg = "Out of memory in SQLPutData (2)";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
} }
else { else
{
current_param->EXEC_buffer = malloc(cbValue + 1); current_param->EXEC_buffer = malloc(cbValue + 1);
if ( ! current_param->EXEC_buffer) { if (!current_param->EXEC_buffer)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (2)"; stmt->errormsg = "Out of memory in SQLPutData (2)";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -713,11 +807,13 @@ char *buffer; ...@@ -713,11 +807,13 @@ char *buffer;
} }
} }
else { /* calling SQLPutData more than once */ else
{ /* calling SQLPutData more than once */
mylog("SQLPutData: (>1) cbValue = %d\n", cbValue); mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);
if (current_param->SQLType == SQL_LONGVARBINARY) { if (current_param->SQLType == SQL_LONGVARBINARY)
{
/* the large object fd is in EXEC_buffer */ /* the large object fd is in EXEC_buffer */
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
...@@ -725,13 +821,17 @@ char *buffer; ...@@ -725,13 +821,17 @@ char *buffer;
*current_param->EXEC_used += cbValue; *current_param->EXEC_used += cbValue;
} else { }
else
{
buffer = current_param->EXEC_buffer; buffer = current_param->EXEC_buffer;
if (cbValue == SQL_NTS) { if (cbValue == SQL_NTS)
{
buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1); buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1);
if ( ! buffer) { if (!buffer)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (3)"; stmt->errormsg = "Out of memory in SQLPutData (3)";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -747,7 +847,8 @@ char *buffer; ...@@ -747,7 +847,8 @@ char *buffer;
current_param->EXEC_buffer = buffer; current_param->EXEC_buffer = buffer;
} }
else if (cbValue > 0) { else if (cbValue > 0)
{
old_pos = *current_param->EXEC_used; old_pos = *current_param->EXEC_used;
...@@ -757,7 +858,8 @@ char *buffer; ...@@ -757,7 +858,8 @@ char *buffer;
/* dont lose the old pointer in case out of memory */ /* dont lose the old pointer in case out of memory */
buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1); buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
if ( ! buffer) { if (!buffer)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (3)"; stmt->errormsg = "Out of memory in SQLPutData (3)";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -771,7 +873,8 @@ char *buffer; ...@@ -771,7 +873,8 @@ char *buffer;
current_param->EXEC_buffer = buffer; current_param->EXEC_buffer = buffer;
} }
else { else
{
SC_log_error(func, "bad cbValue", stmt); SC_log_error(func, "bad cbValue", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
......
...@@ -40,14 +40,18 @@ ...@@ -40,14 +40,18 @@
DWORD DWORD
GetPrivateProfileString(char *theSection, /* section name */ GetPrivateProfileString(char *theSection, /* section name */
char *theKey, /* search key name */ char *theKey, /* search key name */
char *theDefault, /* default value if not found */ char *theDefault, /* default value if not
char *theReturnBuffer, /* return value stored here */ * found */
size_t theReturnBufferLength, /* byte length of return buffer */ char *theReturnBuffer, /* return value stored
char *theIniFileName) /* pathname of ini file to search */ * here */
size_t theReturnBufferLength, /* byte length of return
* buffer */
char *theIniFileName) /* pathname of ini file to
* search */
{ {
char buf[MAXPGPATH]; char buf[MAXPGPATH];
char* ptr = 0; char *ptr = 0;
FILE* aFile = 0; FILE *aFile = 0;
size_t aLength; size_t aLength;
char aLine[2048]; char aLine[2048];
char *aValue; char *aValue;
...@@ -61,56 +65,56 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -61,56 +65,56 @@ GetPrivateProfileString(char *theSection, /* section name */
int j = 0; int j = 0;
j = strlen(theIniFileName) + 1; j = strlen(theIniFileName) + 1;
ptr = (char*)getpwuid(getuid()); /* get user info */ ptr = (char *) getpwuid(getuid()); /* get user info */
if( ptr == NULL) if (ptr == NULL)
{ {
if( MAXPGPATH-1 < j ) if (MAXPGPATH - 1 < j)
theIniFileName[MAXPGPATH-1] = '\0'; theIniFileName[MAXPGPATH - 1] = '\0';
sprintf(buf,"%s",theIniFileName); sprintf(buf, "%s", theIniFileName);
} }
ptr = ((struct passwd*)ptr)->pw_dir; /* get user home dir */ ptr = ((struct passwd *) ptr)->pw_dir; /* get user home dir */
if( ptr == NULL || *ptr == '\0' ) if (ptr == NULL || *ptr == '\0')
ptr = "/home"; 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 * This doesn't make it so we find an ini file but allows normal
* the file won't be found and thus the default value will be * processing to continue further on down. The likelihood is that the
* returned. * file won't be found and thus the default value will be returned.
*/ */
if( MAXPGPATH-1 < strlen(ptr) + j ) if (MAXPGPATH - 1 < strlen(ptr) + j)
{ {
if( MAXPGPATH-1 < strlen(ptr) ) if (MAXPGPATH - 1 < strlen(ptr))
ptr[MAXPGPATH-1] = '\0'; ptr[MAXPGPATH - 1] = '\0';
else else
theIniFileName[MAXPGPATH-1-strlen(ptr)] = '\0'; theIniFileName[MAXPGPATH - 1 - strlen(ptr)] = '\0';
} }
sprintf( buf, "%s/%s",ptr,theIniFileName ); sprintf(buf, "%s/%s", ptr, theIniFileName);
/* This code makes it so that a file in the users home dir /*
* overrides a the "default" file as passed in * This code makes it so that a file in the users home dir overrides a
* the "default" file as passed in
*/ */
aFile = (FILE*)(buf ? fopen(buf, PG_BINARY_R) : NULL); aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
if(!aFile) { if (!aFile)
sprintf(buf,"%s",theIniFileName); {
aFile = (FILE*)(buf ? fopen(buf, PG_BINARY_R) : NULL); sprintf(buf, "%s", theIniFileName);
aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
} }
aLength = (theDefault == NULL) ? 0 : strlen(theDefault); aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
if(theReturnBufferLength == 0 || theReturnBuffer == NULL) if (theReturnBufferLength == 0 || theReturnBuffer == NULL)
{
if(aFile)
{ {
if (aFile)
fclose(aFile); fclose(aFile);
}
return 0; return 0;
} }
if(aFile == NULL) if (aFile == NULL)
{ {
/* no ini file specified, return the default */ /* no ini file specified, return the default */
...@@ -123,15 +127,13 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -123,15 +127,13 @@ GetPrivateProfileString(char *theSection, /* section name */
} }
while(fgets(aLine, sizeof(aLine), aFile) != NULL) while (fgets(aLine, sizeof(aLine), aFile) != NULL)
{ {
aLineLength = strlen(aLine); aLineLength = strlen(aLine);
/* strip final '\n' */ /* strip final '\n' */
if(aLineLength > 0 && aLine[aLineLength - 1] == '\n') if (aLineLength > 0 && aLine[aLineLength - 1] == '\n')
{
aLine[aLineLength - 1] = '\0'; aLine[aLineLength - 1] = '\0';
} switch (*aLine)
switch(*aLine)
{ {
case ' ': /* blank line */ case ' ': /* blank line */
case ';': /* comment line */ case ';': /* comment line */
...@@ -140,21 +142,21 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -140,21 +142,21 @@ GetPrivateProfileString(char *theSection, /* section name */
case '[': /* section marker */ case '[': /* section marker */
if( (aString = strchr(aLine, ']')) ) if ((aString = strchr(aLine, ']')))
{ {
aStart = aLine + 1; aStart = aLine + 1;
aString--; aString--;
while (isspace((unsigned char) *aStart)) aStart++; while (isspace((unsigned char) *aStart))
while (isspace((unsigned char) *aString)) aString--; aStart++;
*(aString+1) = '\0'; while (isspace((unsigned char) *aString))
aString--;
*(aString + 1) = '\0';
/* accept as matched if NULL key or exact match */ /* accept as matched if NULL key or exact match */
if(!theSection || !strcmp(aStart, theSection)) if (!theSection || !strcmp(aStart, theSection))
{
aSectionFound = TRUE; aSectionFound = TRUE;
} }
}
break; break;
...@@ -162,47 +164,40 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -162,47 +164,40 @@ GetPrivateProfileString(char *theSection, /* section name */
/* try to match value keys if in proper section */ /* try to match value keys if in proper section */
if(aSectionFound) if (aSectionFound)
{ {
/* try to match requested key */ /* try to match requested key */
if( (aString = aValue = strchr(aLine, '=')) ) if ((aString = aValue = strchr(aLine, '=')))
{ {
*aValue = '\0'; *aValue = '\0';
++aValue; ++aValue;
/* strip leading blanks in value field */ /* strip leading blanks in value field */
while(*aValue == ' ' && aValue < aLine + sizeof(aLine)) while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
{
*aValue++ = '\0'; *aValue++ = '\0';
} if (aValue >= aLine + sizeof(aLine))
if(aValue >= aLine + sizeof(aLine))
{
aValue = ""; aValue = "";
} }
}
else else
{
aValue = ""; aValue = "";
}
aStart = aLine; aStart = aLine;
while (isspace((unsigned char) *aStart)) aStart++; while (isspace((unsigned char) *aStart))
aStart++;
/* strip trailing blanks from key */ /* strip trailing blanks from key */
if(aString) if (aString)
{
while(--aString >= aStart && *aString == ' ')
{ {
while (--aString >= aStart && *aString == ' ')
*aString = '\0'; *aString = '\0';
} }
}
/* see if key is matched */ /* see if key is matched */
if(theKey == NULL || !strcmp(theKey, aStart)) if (theKey == NULL || !strcmp(theKey, aStart))
{ {
/* matched -- first, terminate value part */ /* matched -- first, terminate value part */
...@@ -213,7 +208,7 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -213,7 +208,7 @@ GetPrivateProfileString(char *theSection, /* section name */
aString = aValue + aLength - 1; aString = aValue + aLength - 1;
while(--aString > aValue && *aString == ' ') while (--aString > aValue && *aString == ' ')
{ {
*aString = '\0'; *aString = '\0';
--aLength; --aLength;
...@@ -221,7 +216,7 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -221,7 +216,7 @@ GetPrivateProfileString(char *theSection, /* section name */
/* unquote value if quoted */ /* unquote value if quoted */
if(aLength >= 2 && aValue[0] == '"' && if (aLength >= 2 && aValue[0] == '"' &&
aValue[aLength - 1] == '"') aValue[aLength - 1] == '"')
{ {
/* string quoted with double quotes */ /* string quoted with double quotes */
...@@ -234,7 +229,7 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -234,7 +229,7 @@ GetPrivateProfileString(char *theSection, /* section name */
{ {
/* single quotes allowed also... */ /* single quotes allowed also... */
if(aLength >= 2 && aValue[0] == '\'' && if (aLength >= 2 && aValue[0] == '\'' &&
aValue[aLength - 1] == '\'') aValue[aLength - 1] == '\'')
{ {
aValue[aLength - 1] = '\0'; aValue[aLength - 1] = '\0';
...@@ -251,18 +246,18 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -251,18 +246,18 @@ GetPrivateProfileString(char *theSection, /* section name */
/* do the copy to return buffer */ /* do the copy to return buffer */
if(aLineLength) if (aLineLength)
{ {
strncpy(&theReturnBuffer[aReturnLength], strncpy(&theReturnBuffer[aReturnLength],
aValue, aLineLength); aValue, aLineLength);
aReturnLength += aLineLength; aReturnLength += aLineLength;
if(aReturnLength < theReturnBufferLength) if (aReturnLength < theReturnBufferLength)
{ {
theReturnBuffer[aReturnLength] = '\0'; theReturnBuffer[aReturnLength] = '\0';
++aReturnLength; ++aReturnLength;
} }
} }
if(aFile) if (aFile)
{ {
fclose(aFile); fclose(aFile);
aFile = NULL; aFile = NULL;
...@@ -276,12 +271,11 @@ GetPrivateProfileString(char *theSection, /* section name */ ...@@ -276,12 +271,11 @@ GetPrivateProfileString(char *theSection, /* section name */
} }
} }
if(aFile) if (aFile)
{
fclose(aFile); fclose(aFile);
}
if(!aKeyFound) { /* key wasn't found return default */ if (!aKeyFound)
{ /* key wasn't found return default */
++aLength; /* room for NULL char */ ++aLength; /* room for NULL char */
aLength = theReturnBufferLength < aLength ? aLength = theReturnBufferLength < aLength ?
theReturnBufferLength : aLength; theReturnBufferLength : aLength;
...@@ -296,7 +290,8 @@ DWORD ...@@ -296,7 +290,8 @@ DWORD
WritePrivateProfileString(char *theSection, /* section name */ WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */ char *theKey, /* write key name */
char *theBuffer, /* input buffer */ char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to write */ char *theIniFileName) /* pathname of ini file to
* write */
{ {
return 0; return 0;
} }
...@@ -310,11 +305,12 @@ DWORD ...@@ -310,11 +305,12 @@ DWORD
WritePrivateProfileString(char *theSection, /* section name */ WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */ char *theKey, /* write key name */
char *theBuffer, /* input buffer */ char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to write */ char *theIniFileName) /* pathname of ini file to
* write */
{ {
char buf[MAXPGPATH]; char buf[MAXPGPATH];
char* ptr = 0; char *ptr = 0;
FILE* aFile = 0; FILE *aFile = 0;
size_t aLength; size_t aLength;
char aLine[2048]; char aLine[2048];
char *aValue; char *aValue;
...@@ -327,24 +323,26 @@ WritePrivateProfileString(char *theSection, /* section name */ ...@@ -327,24 +323,26 @@ WritePrivateProfileString(char *theSection, /* section name */
int j = 0; int j = 0;
/* If this isn't correct processing we'll change it later */ /* If this isn't correct processing we'll change it later */
if(theSection == NULL || theKey == NULL || theBuffer == NULL || if (theSection == NULL || theKey == NULL || theBuffer == NULL ||
theIniFileName == NULL) return 0; theIniFileName == NULL)
return 0;
aLength = strlen(theBuffer); aLength = strlen(theBuffer);
if(aLength == 0) return 0; if (aLength == 0)
return 0;
j = strlen(theIniFileName) + 1; j = strlen(theIniFileName) + 1;
ptr = (char*)getpwuid(getuid()); /* get user info */ ptr = (char *) getpwuid(getuid()); /* get user info */
if( ptr == NULL) if (ptr == NULL)
{ {
if( MAXPGPATH-1 < j ) if (MAXPGPATH - 1 < j)
theIniFileName[MAXPGPATH-1] = '\0'; theIniFileName[MAXPGPATH - 1] = '\0';
sprintf(buf,"%s",theIniFileName); sprintf(buf, "%s", theIniFileName);
} }
ptr = ((struct passwd*)ptr)->pw_dir; /* get user home dir */ ptr = ((struct passwd *) ptr)->pw_dir; /* get user home dir */
if( ptr == NULL || *ptr == '\0' ) if (ptr == NULL || *ptr == '\0')
ptr = "/home"; ptr = "/home";
/* This doesn't make it so we find an ini file but allows normal */ /* This doesn't make it so we find an ini file but allows normal */
...@@ -352,24 +350,26 @@ WritePrivateProfileString(char *theSection, /* section name */ ...@@ -352,24 +350,26 @@ WritePrivateProfileString(char *theSection, /* section name */
/* the file won't be found and thus the default value will be */ /* the file won't be found and thus the default value will be */
/* returned. */ /* returned. */
/* */ /* */
if( MAXPGPATH-1 < strlen(ptr) + j ) if (MAXPGPATH - 1 < strlen(ptr) + j)
{ {
if( MAXPGPATH-1 < strlen(ptr) ) if (MAXPGPATH - 1 < strlen(ptr))
ptr[MAXPGPATH-1] = '\0'; ptr[MAXPGPATH - 1] = '\0';
else else
theIniFileName[MAXPGPATH-1-strlen(ptr)] = '\0'; theIniFileName[MAXPGPATH - 1 - strlen(ptr)] = '\0';
} }
sprintf( buf, "%s/%s",ptr,theIniFileName ); sprintf(buf, "%s/%s", ptr, theIniFileName);
/* This code makes it so that a file in the users home dir */ /* This code makes it so that a file in the users home dir */
/* overrides a the "default" file as passed in */ /* overrides a the "default" file as passed in */
/* */ /* */
aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL); aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
if(!aFile) { if (!aFile)
sprintf(buf,"%s",theIniFileName); {
aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL); sprintf(buf, "%s", theIniFileName);
if(!aFile) return 0; aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
if (!aFile)
return 0;
} }
...@@ -379,15 +379,13 @@ WritePrivateProfileString(char *theSection, /* section name */ ...@@ -379,15 +379,13 @@ WritePrivateProfileString(char *theSection, /* section name */
/* exists we have to overwrite it. If it doesn't exist */ /* exists we have to overwrite it. If it doesn't exist */
/* we just write a new line to the file. */ /* we just write a new line to the file. */
/* */ /* */
while(fgets(aLine, sizeof(aLine), aFile) != NULL) while (fgets(aLine, sizeof(aLine), aFile) != NULL)
{ {
aLineLength = strlen(aLine); aLineLength = strlen(aLine);
/* strip final '\n' */ /* strip final '\n' */
if(aLineLength > 0 && aLine[aLineLength - 1] == '\n') if (aLineLength > 0 && aLine[aLineLength - 1] == '\n')
{
aLine[aLineLength - 1] = '\0'; aLine[aLineLength - 1] = '\0';
} switch (*aLine)
switch(*aLine)
{ {
case ' ': /* blank line */ case ' ': /* blank line */
case ';': /* comment line */ case ';': /* comment line */
...@@ -396,17 +394,15 @@ WritePrivateProfileString(char *theSection, /* section name */ ...@@ -396,17 +394,15 @@ WritePrivateProfileString(char *theSection, /* section name */
case '[': /* section marker */ case '[': /* section marker */
if( (aString = strchr(aLine, ']')) ) if ((aString = strchr(aLine, ']')))
{ {
*aString = '\0'; *aString = '\0';
/* accept as matched if key exact match */ /* accept as matched if key exact match */
if(!strcmp(aLine + 1, theSection)) if (!strcmp(aLine + 1, theSection))
{
aSectionFound = TRUE; aSectionFound = TRUE;
} }
}
break; break;
...@@ -414,69 +410,61 @@ WritePrivateProfileString(char *theSection, /* section name */ ...@@ -414,69 +410,61 @@ WritePrivateProfileString(char *theSection, /* section name */
/* try to match value keys if in proper section */ /* try to match value keys if in proper section */
if(aSectionFound) if (aSectionFound)
{ {
/* try to match requested key */ /* try to match requested key */
if( (aString = aValue = strchr(aLine, '=')) ) if ((aString = aValue = strchr(aLine, '=')))
{ {
*aValue = '\0'; *aValue = '\0';
++aValue; ++aValue;
/* strip leading blanks in value field */ /* strip leading blanks in value field */
while(*aValue == ' ' && aValue < aLine + sizeof(aLine)) while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
{
*aValue++ = '\0'; *aValue++ = '\0';
} if (aValue >= aLine + sizeof(aLine))
if(aValue >= aLine + sizeof(aLine))
{
aValue = ""; aValue = "";
} }
}
else else
{
aValue = ""; aValue = "";
}
/* strip trailing blanks from key */ /* strip trailing blanks from key */
if(aString) if (aString)
{
while(--aString >= aLine && *aString == ' ')
{ {
while (--aString >= aLine && *aString == ' ')
*aString = '\0'; *aString = '\0';
} }
}
/* see if key is matched */ /* see if key is matched */
if(!strcmp(theKey, aLine)) if (!strcmp(theKey, aLine))
{ {
keyFound = TRUE; keyFound = TRUE;
/* matched -- first, terminate value part */ /* matched -- first, terminate value part */
/* overwrite current value */ /* overwrite current value */
fseek(aFile,-aLineLength,SEEK_CUR); fseek(aFile, -aLineLength, SEEK_CUR);
/* overwrite key and value */ /* overwrite key and value */
sprintf(aLine,"%s = %s\n",theKey,theBuffer); sprintf(aLine, "%s = %s\n", theKey, theBuffer);
fputs(aLine,aFile); fputs(aLine, aFile);
} }
} }
} }
break; break;
} }
} }
if(!keyFound) { /* theKey wasn't in file so */ if (!keyFound)
if(aFile) { /* theKey wasn't in file so */
{ if (aFile)
fclose(aFile); fclose(aFile);
}
return aReturnLength > 0 ? aReturnLength - 1 : 0; return aReturnLength > 0 ? aReturnLength - 1 : 0;
} }
#endif #endif
......
...@@ -13,25 +13,32 @@ ...@@ -13,25 +13,32 @@
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
DWORD DWORD
GetPrivateProfileString(char *theSection, /* section name */ GetPrivateProfileString(char *theSection, /* section name */
char *theKey, /* search key name */ char *theKey, /* search key name */
char *theDefault, /* default value if not found */ char *theDefault, /* default value if not
char *theReturnBuffer, /* return valuse stored here */ * found */
size_t theBufferLength, /* byte length of return buffer */ char *theReturnBuffer, /* return valuse stored
char *theIniFileName); /* pathname of ini file to search */ * here */
size_t theBufferLength, /* byte length of return
* buffer */
char *theIniFileName); /* pathname of ini file
* to search */
DWORD DWORD
WritePrivateProfileString(char *theSection, /* section name */ WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */ char *theKey, /* write key name */
char *theBuffer, /* input buffer */ char *theBuffer, /* input buffer */
char *theIniFileName); /* pathname of ini file to write */ char *theIniFileName); /* pathname of ini file
* to write */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#ifndef WIN32 #ifndef WIN32
......
...@@ -58,30 +58,35 @@ extern GLOBAL_VALUES globals; ...@@ -58,30 +58,35 @@ extern GLOBAL_VALUES globals;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLGetInfo( RETCODE SQL_API
SQLGetInfo(
HDBC hdbc, HDBC hdbc,
UWORD fInfoType, UWORD fInfoType,
PTR rgbInfoValue, PTR rgbInfoValue,
SWORD cbInfoValueMax, SWORD cbInfoValueMax,
SWORD FAR *pcbInfoValue) SWORD FAR * pcbInfoValue)
{ {
static char *func = "SQLGetInfo"; static char *func = "SQLGetInfo";
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci; ConnInfo *ci;
char *p = NULL, tmp[MAX_INFO_STRING]; char *p = NULL,
int len = 0, value = 0; tmp[MAX_INFO_STRING];
RETCODE result; int len = 0,
value = 0;
RETCODE result;
mylog( "%s: entering...fInfoType=%d\n", func, fInfoType); mylog("%s: entering...fInfoType=%d\n", func, fInfoType);
if ( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
ci = &conn->connInfo; ci = &conn->connInfo;
switch (fInfoType) { switch (fInfoType)
{
case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */ case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */
p = "N"; p = "N";
break; break;
...@@ -150,8 +155,9 @@ RETCODE result; ...@@ -150,8 +155,9 @@ RETCODE result;
case SQL_CORRELATION_NAME: /* ODBC 1.0 */ case SQL_CORRELATION_NAME: /* ODBC 1.0 */
/* Saying no correlation name makes Query not work right. /*
value = SQL_CN_NONE; * Saying no correlation name makes Query not work right.
* value = SQL_CN_NONE;
*/ */
len = 2; len = 2;
value = SQL_CN_ANY; value = SQL_CN_ANY;
...@@ -175,12 +181,14 @@ RETCODE result; ...@@ -175,12 +181,14 @@ RETCODE result;
p = CC_is_onlyread(conn) ? "Y" : "N"; p = CC_is_onlyread(conn) ? "Y" : "N";
break; break;
case SQL_DATABASE_NAME: /* Support for old ODBC 1.0 Apps */ 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"
p = CC_get_database(conn); /*
* Returning the database name causes problems in MS Query. It
* generates query like: "SELECT DISTINCT a FROM byronncrap3
* crap3"
*
* p = CC_get_database(conn);
*/ */
p = ""; p = "";
break; break;
...@@ -190,7 +198,11 @@ RETCODE result; ...@@ -190,7 +198,11 @@ RETCODE result;
break; break;
case SQL_DBMS_VER: /* ODBC 1.0 */ case SQL_DBMS_VER: /* ODBC 1.0 */
/* The ODBC spec wants ##.##.#### ...whatever... so prepend the driver */
/*
* The ODBC spec wants ##.##.#### ...whatever... so prepend
* the driver
*/
/* version number to the dbms version string */ /* version number to the dbms version string */
sprintf(tmp, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version); sprintf(tmp, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version);
p = tmp; p = tmp;
...@@ -198,7 +210,7 @@ RETCODE result; ...@@ -198,7 +210,7 @@ RETCODE result;
case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */ case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */
len = 4; len = 4;
value = SQL_TXN_READ_COMMITTED; /*SQL_TXN_SERIALIZABLE; */ value = SQL_TXN_READ_COMMITTED; /* SQL_TXN_SERIALIZABLE; */
break; break;
case SQL_DRIVER_NAME: /* ODBC 1.0 */ case SQL_DRIVER_NAME: /* ODBC 1.0 */
...@@ -244,8 +256,10 @@ RETCODE result; ...@@ -244,8 +256,10 @@ RETCODE result;
break; break;
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */ case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
/* are identifiers case-sensitive (yes, but only when quoted. If not quoted, they
default to lowercase) /*
* are identifiers case-sensitive (yes, but only when quoted.
* If not quoted, they default to lowercase)
*/ */
len = 2; len = 2;
value = SQL_IC_LOWER; value = SQL_IC_LOWER;
...@@ -261,8 +275,10 @@ RETCODE result; ...@@ -261,8 +275,10 @@ RETCODE result;
break; break;
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */ 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 /*
* is there a character that escapes '%' and '_' in a LIKE
* clause? not as far as I can tell
*/ */
p = "N"; p = "N";
break; break;
...@@ -339,16 +355,23 @@ RETCODE result; ...@@ -339,16 +355,23 @@ RETCODE result;
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */ case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
len = 4; len = 4;
if (PG_VERSION_GE(conn, 7.1)) { /* Large Rowa in 7.1+ */ if (PG_VERSION_GE(conn, 7.1))
{ /* Large Rowa in 7.1+ */
value = MAX_ROW_SIZE; value = MAX_ROW_SIZE;
} else { /* Without the Toaster we're limited to the blocksize */ }
else
{ /* Without the Toaster we're limited to
* the blocksize */
value = BLCKSZ; value = BLCKSZ;
} }
break; break;
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */ case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
/* does the preceding value include LONGVARCHAR and LONGVARBINARY
fields? Well, it does include longvarchar, but not longvarbinary. /*
* does the preceding value include LONGVARCHAR and
* LONGVARBINARY fields? Well, it does include longvarchar,
* but not longvarbinary.
*/ */
p = "Y"; p = "Y";
break; break;
...@@ -356,11 +379,15 @@ RETCODE result; ...@@ -356,11 +379,15 @@ RETCODE result;
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */ case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
/* maybe this should be 0? */ /* maybe this should be 0? */
len = 4; len = 4;
if (PG_VERSION_GE(conn, 7.0)) { /* Long Queries in 7.0+ */ if (PG_VERSION_GE(conn, 7.0))
{ /* Long Queries in 7.0+ */
value = MAX_STATEMENT_LEN; value = MAX_STATEMENT_LEN;
} else if (PG_VERSION_GE(conn, 6.5)) /* Prior to 7.0 we used 2*BLCKSZ */ }
value = (2*BLCKSZ); else if (PG_VERSION_GE(conn, 6.5)) /* Prior to 7.0 we used
else /* Prior to 6.5 we used BLCKSZ */ * 2*BLCKSZ */
value = (2 * BLCKSZ);
else
/* Prior to 6.5 we used BLCKSZ */
value = BLCKSZ; value = BLCKSZ;
break; break;
...@@ -390,7 +417,11 @@ RETCODE result; ...@@ -390,7 +417,11 @@ RETCODE result;
break; break;
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */ case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
/* Dont need the length, SQLPutData can handle any size and multiple calls */
/*
* Dont need the length, SQLPutData can handle any size and
* multiple calls
*/
p = "N"; p = "N";
break; break;
...@@ -431,7 +462,8 @@ RETCODE result; ...@@ -431,7 +462,8 @@ RETCODE result;
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */ case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
len = 4; len = 4;
if (PG_VERSION_GE(conn, 7.1)) { /* OJs in 7.1+ */ if (PG_VERSION_GE(conn, 7.1))
{ /* OJs in 7.1+ */
value = (SQL_OJ_LEFT | value = (SQL_OJ_LEFT |
SQL_OJ_RIGHT | SQL_OJ_RIGHT |
SQL_OJ_FULL | SQL_OJ_FULL |
...@@ -439,7 +471,9 @@ RETCODE result; ...@@ -439,7 +471,9 @@ RETCODE result;
SQL_OJ_NOT_ORDERED | SQL_OJ_NOT_ORDERED |
SQL_OJ_INNER | SQL_OJ_INNER |
SQL_OJ_ALL_COMPARISON_OPS); SQL_OJ_ALL_COMPARISON_OPS);
} else { /* OJs not in <7.1 */ }
else
{ /* OJs not in <7.1 */
value = 0; value = 0;
} }
break; break;
...@@ -449,9 +483,12 @@ RETCODE result; ...@@ -449,9 +483,12 @@ RETCODE result;
break; break;
case SQL_OUTER_JOINS: /* ODBC 1.0 */ case SQL_OUTER_JOINS: /* ODBC 1.0 */
if (PG_VERSION_GE(conn, 7.1)) { /* OJs in 7.1+ */ if (PG_VERSION_GE(conn, 7.1))
{ /* OJs in 7.1+ */
p = "Y"; p = "Y";
} else { /* OJs not in <7.1 */ }
else
{ /* OJs not in <7.1 */
p = "N"; p = "N";
} }
break; break;
...@@ -510,8 +547,10 @@ RETCODE result; ...@@ -510,8 +547,10 @@ RETCODE result;
break; break;
case SQL_ROW_UPDATES: /* ODBC 1.0 */ 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 /*
* Driver doesn't support keyset-driven or mixed cursors, so
* not much point in saying row updates are supported
*/ */
p = globals.lie ? "Y" : "N"; p = globals.lie ? "Y" : "N";
break; break;
...@@ -596,7 +635,11 @@ RETCODE result; ...@@ -596,7 +635,11 @@ RETCODE result;
break; break;
case SQL_TXN_CAPABLE: /* ODBC 1.0 */ case SQL_TXN_CAPABLE: /* ODBC 1.0 */
/* Postgres can deal with create or drop table statements in a transaction */
/*
* Postgres can deal with create or drop table statements in a
* transaction
*/
len = 2; len = 2;
value = SQL_TC_ALL; value = SQL_TC_ALL;
break; break;
...@@ -626,19 +669,23 @@ RETCODE result; ...@@ -626,19 +669,23 @@ RETCODE result;
result = SQL_SUCCESS; result = SQL_SUCCESS;
mylog("SQLGetInfo: p='%s', len=%d, value=%d, cbMax=%d\n", p?p:"<NULL>", len, value, cbInfoValueMax); mylog("SQLGetInfo: p='%s', len=%d, value=%d, cbMax=%d\n", p ? p : "<NULL>", len, value, cbInfoValueMax);
/* NOTE, that if rgbInfoValue is NULL, then no warnings or errors should /*
result and just pcbInfoValue is returned, which indicates what length * NOTE, that if rgbInfoValue is NULL, then no warnings or errors
would be required if a real buffer had been passed in. * should result and just pcbInfoValue is returned, which indicates
* what length would be required if a real buffer had been passed in.
*/ */
if (p) { /* char/binary data */ if (p)
{ /* char/binary data */
len = strlen(p); len = strlen(p);
if (rgbInfoValue) { if (rgbInfoValue)
strncpy_null((char *)rgbInfoValue, p, (size_t)cbInfoValueMax); {
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
if (len >= cbInfoValueMax) { if (len >= cbInfoValueMax)
{
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
conn->errornumber = STMT_TRUNCATED; conn->errornumber = STMT_TRUNCATED;
conn->errormsg = "The buffer was too small for the result."; conn->errormsg = "The buffer was too small for the result.";
...@@ -646,14 +693,16 @@ RETCODE result; ...@@ -646,14 +693,16 @@ RETCODE result;
} }
} }
else { /* numeric data */ else
{ /* numeric data */
if (rgbInfoValue) { if (rgbInfoValue)
{
if (len == 2 ) if (len == 2)
*((WORD *)rgbInfoValue) = (WORD) value; *((WORD *) rgbInfoValue) = (WORD) value;
else if (len == 4) else if (len == 4)
*((DWORD *)rgbInfoValue) = (DWORD) value; *((DWORD *) rgbInfoValue) = (DWORD) value;
} }
} }
...@@ -666,21 +715,24 @@ RETCODE result; ...@@ -666,21 +715,24 @@ RETCODE result;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLGetTypeInfo( RETCODE SQL_API
SQLGetTypeInfo(
HSTMT hstmt, HSTMT hstmt,
SWORD fSqlType) SWORD fSqlType)
{ {
static char *func = "SQLGetTypeInfo"; static char *func = "SQLGetTypeInfo";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row; TupleNode *row;
int i; int i;
/* Int4 type; */ /* Int4 type; */
Int4 pgType; Int4 pgType;
Int2 sqlType; Int2 sqlType;
mylog("%s: entering...fSqlType = %d\n", func, fSqlType); mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -688,7 +740,8 @@ Int2 sqlType; ...@@ -688,7 +740,8 @@ Int2 sqlType;
stmt->manual_result = TRUE; stmt->manual_result = TRUE;
stmt->result = QR_Constructor(); stmt->result = QR_Constructor();
if( ! stmt->result) { if (!stmt->result)
{
SC_log_error(func, "Error creating result.", stmt); SC_log_error(func, "Error creating result.", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -712,11 +765,13 @@ Int2 sqlType; ...@@ -712,11 +765,13 @@ Int2 sqlType;
QR_set_field_info(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2); QR_set_field_info(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2); QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
for(i=0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i]) { for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
{
pgType = sqltype_to_pgtype(sqlType); pgType = sqltype_to_pgtype(sqlType);
if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType) { if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
row = (TupleNode *)malloc(sizeof(TupleNode) + (15 - 1)*sizeof(TupleField)); {
row = (TupleNode *) malloc(sizeof(TupleNode) + (15 - 1) * sizeof(TupleField));
/* These values can't be NULL */ /* These values can't be NULL */
set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType)); set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType));
...@@ -726,7 +781,10 @@ Int2 sqlType; ...@@ -726,7 +781,10 @@ Int2 sqlType;
set_tuplefield_int2(&row->tuple[8], pgtype_searchable(stmt, pgType)); set_tuplefield_int2(&row->tuple[8], pgtype_searchable(stmt, pgType));
set_tuplefield_int2(&row->tuple[10], pgtype_money(stmt, pgType)); set_tuplefield_int2(&row->tuple[10], pgtype_money(stmt, pgType));
/* Localized data-source dependent data type name (always NULL) */ /*
* Localized data-source dependent data type name (always
* NULL)
*/
set_tuplefield_null(&row->tuple[12]); set_tuplefield_null(&row->tuple[12]);
/* These values can be NULL */ /* These values can be NULL */
...@@ -754,20 +812,24 @@ Int2 sqlType; ...@@ -754,20 +812,24 @@ Int2 sqlType;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLGetFunctions( RETCODE SQL_API
SQLGetFunctions(
HDBC hdbc, HDBC hdbc,
UWORD fFunction, UWORD fFunction,
UWORD FAR *pfExists) UWORD FAR * pfExists)
{ {
static char *func="SQLGetFunctions"; static char *func = "SQLGetFunctions";
mylog( "%s: entering...\n", func); mylog("%s: entering...\n", func);
if (fFunction == SQL_API_ALL_FUNCTIONS) { if (fFunction == SQL_API_ALL_FUNCTIONS)
{
if (globals.lie) { if (globals.lie)
{
int i; int i;
memset(pfExists, 0, sizeof(UWORD)*100);
memset(pfExists, 0, sizeof(UWORD) * 100);
pfExists[SQL_API_SQLALLOCENV] = TRUE; pfExists[SQL_API_SQLALLOCENV] = TRUE;
pfExists[SQL_API_SQLFREEENV] = TRUE; pfExists[SQL_API_SQLFREEENV] = TRUE;
...@@ -776,8 +838,9 @@ static char *func="SQLGetFunctions"; ...@@ -776,8 +838,9 @@ static char *func="SQLGetFunctions";
for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++) for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++)
pfExists[i] = TRUE; pfExists[i] = TRUE;
} }
else { else
memset(pfExists, 0, sizeof(UWORD)*100); {
memset(pfExists, 0, sizeof(UWORD) * 100);
/* ODBC core functions */ /* ODBC core functions */
pfExists[SQL_API_SQLALLOCCONNECT] = TRUE; pfExists[SQL_API_SQLALLOCCONNECT] = TRUE;
...@@ -825,9 +888,12 @@ static char *func="SQLGetFunctions"; ...@@ -825,9 +888,12 @@ static char *func="SQLGetFunctions";
/* ODBC level 2 functions */ /* ODBC level 2 functions */
pfExists[SQL_API_SQLBROWSECONNECT] = FALSE; pfExists[SQL_API_SQLBROWSECONNECT] = FALSE;
pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE; pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
pfExists[SQL_API_SQLDATASOURCES] = FALSE; /* only implemented by DM */ pfExists[SQL_API_SQLDATASOURCES] = FALSE; /* only implemented by
pfExists[SQL_API_SQLDESCRIBEPARAM] = FALSE; /* not properly implemented */ * DM */
pfExists[SQL_API_SQLDRIVERS] = FALSE; /* only implemented by DM */ pfExists[SQL_API_SQLDESCRIBEPARAM] = FALSE; /* not properly
* implemented */
pfExists[SQL_API_SQLDRIVERS] = FALSE; /* only implemented by
* DM */
pfExists[SQL_API_SQLEXTENDEDFETCH] = TRUE; pfExists[SQL_API_SQLEXTENDEDFETCH] = TRUE;
pfExists[SQL_API_SQLFOREIGNKEYS] = TRUE; pfExists[SQL_API_SQLFOREIGNKEYS] = TRUE;
pfExists[SQL_API_SQLMORERESULTS] = TRUE; pfExists[SQL_API_SQLMORERESULTS] = TRUE;
...@@ -841,74 +907,190 @@ static char *func="SQLGetFunctions"; ...@@ -841,74 +907,190 @@ static char *func="SQLGetFunctions";
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */ pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE; pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE;
} }
} else { }
else
{
if (globals.lie) if (globals.lie)
*pfExists = TRUE; *pfExists = TRUE;
else { else
{
switch(fFunction) {
case SQL_API_SQLALLOCCONNECT: *pfExists = TRUE; break; switch (fFunction)
case SQL_API_SQLALLOCENV: *pfExists = TRUE; break; {
case SQL_API_SQLALLOCSTMT: *pfExists = TRUE; break; case SQL_API_SQLALLOCCONNECT:
case SQL_API_SQLBINDCOL: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLCANCEL: *pfExists = TRUE; break; break;
case SQL_API_SQLCOLATTRIBUTES: *pfExists = TRUE; break; case SQL_API_SQLALLOCENV:
case SQL_API_SQLCONNECT: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLDESCRIBECOL: *pfExists = TRUE; break; /* partial */ break;
case SQL_API_SQLDISCONNECT: *pfExists = TRUE; break; case SQL_API_SQLALLOCSTMT:
case SQL_API_SQLERROR: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLEXECDIRECT: *pfExists = TRUE; break; break;
case SQL_API_SQLEXECUTE: *pfExists = TRUE; break; case SQL_API_SQLBINDCOL:
case SQL_API_SQLFETCH: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLFREECONNECT: *pfExists = TRUE; break; break;
case SQL_API_SQLFREEENV: *pfExists = TRUE; break; case SQL_API_SQLCANCEL:
case SQL_API_SQLFREESTMT: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLGETCURSORNAME: *pfExists = TRUE; break; break;
case SQL_API_SQLNUMRESULTCOLS: *pfExists = TRUE; break; case SQL_API_SQLCOLATTRIBUTES:
case SQL_API_SQLPREPARE: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLROWCOUNT: *pfExists = TRUE; break; break;
case SQL_API_SQLSETCURSORNAME: *pfExists = TRUE; break; case SQL_API_SQLCONNECT:
case SQL_API_SQLSETPARAM: *pfExists = FALSE; break; /* odbc 1.0 */ *pfExists = TRUE;
case SQL_API_SQLTRANSACT: *pfExists = TRUE; break; break;
case SQL_API_SQLDESCRIBECOL:
*pfExists = TRUE;
break; /* partial */
case SQL_API_SQLDISCONNECT:
*pfExists = TRUE;
break;
case SQL_API_SQLERROR:
*pfExists = TRUE;
break;
case SQL_API_SQLEXECDIRECT:
*pfExists = TRUE;
break;
case SQL_API_SQLEXECUTE:
*pfExists = TRUE;
break;
case SQL_API_SQLFETCH:
*pfExists = TRUE;
break;
case SQL_API_SQLFREECONNECT:
*pfExists = TRUE;
break;
case SQL_API_SQLFREEENV:
*pfExists = TRUE;
break;
case SQL_API_SQLFREESTMT:
*pfExists = TRUE;
break;
case SQL_API_SQLGETCURSORNAME:
*pfExists = TRUE;
break;
case SQL_API_SQLNUMRESULTCOLS:
*pfExists = TRUE;
break;
case SQL_API_SQLPREPARE:
*pfExists = TRUE;
break;
case SQL_API_SQLROWCOUNT:
*pfExists = TRUE;
break;
case SQL_API_SQLSETCURSORNAME:
*pfExists = TRUE;
break;
case SQL_API_SQLSETPARAM:
*pfExists = FALSE;
break; /* odbc 1.0 */
case SQL_API_SQLTRANSACT:
*pfExists = TRUE;
break;
/* ODBC level 1 functions */ /* ODBC level 1 functions */
case SQL_API_SQLBINDPARAMETER: *pfExists = TRUE; break; case SQL_API_SQLBINDPARAMETER:
case SQL_API_SQLCOLUMNS: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLDRIVERCONNECT: *pfExists = TRUE; break; break;
case SQL_API_SQLGETCONNECTOPTION: *pfExists = TRUE; break; /* partial */ case SQL_API_SQLCOLUMNS:
case SQL_API_SQLGETDATA: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLGETFUNCTIONS: *pfExists = TRUE; break; break;
case SQL_API_SQLGETINFO: *pfExists = TRUE; break; case SQL_API_SQLDRIVERCONNECT:
case SQL_API_SQLGETSTMTOPTION: *pfExists = TRUE; break; /* partial */ *pfExists = TRUE;
case SQL_API_SQLGETTYPEINFO: *pfExists = TRUE; break; break;
case SQL_API_SQLPARAMDATA: *pfExists = TRUE; break; case SQL_API_SQLGETCONNECTOPTION:
case SQL_API_SQLPUTDATA: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLSETCONNECTOPTION: *pfExists = TRUE; break; /* partial */ break; /* partial */
case SQL_API_SQLSETSTMTOPTION: *pfExists = TRUE; break; case SQL_API_SQLGETDATA:
case SQL_API_SQLSPECIALCOLUMNS: *pfExists = TRUE; break; *pfExists = TRUE;
case SQL_API_SQLSTATISTICS: *pfExists = TRUE; break; break;
case SQL_API_SQLTABLES: *pfExists = TRUE; break; case SQL_API_SQLGETFUNCTIONS:
*pfExists = TRUE;
break;
case SQL_API_SQLGETINFO:
*pfExists = TRUE;
break;
case SQL_API_SQLGETSTMTOPTION:
*pfExists = TRUE;
break; /* partial */
case SQL_API_SQLGETTYPEINFO:
*pfExists = TRUE;
break;
case SQL_API_SQLPARAMDATA:
*pfExists = TRUE;
break;
case SQL_API_SQLPUTDATA:
*pfExists = TRUE;
break;
case SQL_API_SQLSETCONNECTOPTION:
*pfExists = TRUE;
break; /* partial */
case SQL_API_SQLSETSTMTOPTION:
*pfExists = TRUE;
break;
case SQL_API_SQLSPECIALCOLUMNS:
*pfExists = TRUE;
break;
case SQL_API_SQLSTATISTICS:
*pfExists = TRUE;
break;
case SQL_API_SQLTABLES:
*pfExists = TRUE;
break;
/* ODBC level 2 functions */ /* ODBC level 2 functions */
case SQL_API_SQLBROWSECONNECT: *pfExists = FALSE; break; case SQL_API_SQLBROWSECONNECT:
case SQL_API_SQLCOLUMNPRIVILEGES: *pfExists = FALSE; break; *pfExists = FALSE;
case SQL_API_SQLDATASOURCES: *pfExists = FALSE; break; /* only implemented by DM */ break;
case SQL_API_SQLDESCRIBEPARAM: *pfExists = FALSE; break; /* not properly implemented */ case SQL_API_SQLCOLUMNPRIVILEGES:
case SQL_API_SQLDRIVERS: *pfExists = FALSE; break; /* only implemented by DM */ *pfExists = FALSE;
case SQL_API_SQLEXTENDEDFETCH: *pfExists = TRUE; break; break;
case SQL_API_SQLFOREIGNKEYS: *pfExists = TRUE; break; case SQL_API_SQLDATASOURCES:
case SQL_API_SQLMORERESULTS: *pfExists = TRUE; break; *pfExists = FALSE;
case SQL_API_SQLNATIVESQL: *pfExists = TRUE; break; break; /* only implemented by DM */
case SQL_API_SQLNUMPARAMS: *pfExists = TRUE; break; case SQL_API_SQLDESCRIBEPARAM:
case SQL_API_SQLPARAMOPTIONS: *pfExists = FALSE; break; *pfExists = FALSE;
case SQL_API_SQLPRIMARYKEYS: *pfExists = TRUE; break; break; /* not properly implemented */
case SQL_API_SQLPROCEDURECOLUMNS: *pfExists = FALSE; break; case SQL_API_SQLDRIVERS:
case SQL_API_SQLPROCEDURES: *pfExists = FALSE; break; *pfExists = FALSE;
case SQL_API_SQLSETPOS: *pfExists = TRUE; break; break; /* only implemented by DM */
case SQL_API_SQLSETSCROLLOPTIONS: *pfExists = TRUE; break; /* odbc 1.0 */ case SQL_API_SQLEXTENDEDFETCH:
case SQL_API_SQLTABLEPRIVILEGES: *pfExists = FALSE; break; *pfExists = TRUE;
break;
case SQL_API_SQLFOREIGNKEYS:
*pfExists = TRUE;
break;
case SQL_API_SQLMORERESULTS:
*pfExists = TRUE;
break;
case SQL_API_SQLNATIVESQL:
*pfExists = TRUE;
break;
case SQL_API_SQLNUMPARAMS:
*pfExists = TRUE;
break;
case SQL_API_SQLPARAMOPTIONS:
*pfExists = FALSE;
break;
case SQL_API_SQLPRIMARYKEYS:
*pfExists = TRUE;
break;
case SQL_API_SQLPROCEDURECOLUMNS:
*pfExists = FALSE;
break;
case SQL_API_SQLPROCEDURES:
*pfExists = FALSE;
break;
case SQL_API_SQLSETPOS:
*pfExists = TRUE;
break;
case SQL_API_SQLSETSCROLLOPTIONS:
*pfExists = TRUE;
break; /* odbc 1.0 */
case SQL_API_SQLTABLEPRIVILEGES:
*pfExists = FALSE;
break;
} }
} }
} }
...@@ -918,7 +1100,8 @@ static char *func="SQLGetFunctions"; ...@@ -918,7 +1100,8 @@ static char *func="SQLGetFunctions";
RETCODE SQL_API SQLTables( RETCODE SQL_API
SQLTables(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -929,26 +1112,35 @@ RETCODE SQL_API SQLTables( ...@@ -929,26 +1112,35 @@ RETCODE SQL_API SQLTables(
UCHAR FAR * szTableType, UCHAR FAR * szTableType,
SWORD cbTableType) SWORD cbTableType)
{ {
static char *func = "SQLTables"; static char *func = "SQLTables";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
StatementClass *tbl_stmt; StatementClass *tbl_stmt;
TupleNode *row; TupleNode *row;
HSTMT htbl_stmt; HSTMT htbl_stmt;
RETCODE result; RETCODE result;
char *tableType; char *tableType;
char tables_query[STD_STATEMENT_LEN]; char tables_query[STD_STATEMENT_LEN];
char table_name[MAX_INFO_STRING], table_owner[MAX_INFO_STRING], relkind_or_hasrules[MAX_INFO_STRING]; char table_name[MAX_INFO_STRING],
ConnectionClass *conn; table_owner[MAX_INFO_STRING],
ConnInfo *ci; relkind_or_hasrules[MAX_INFO_STRING];
char *prefix[32], prefixes[MEDIUM_REGISTRY_LEN]; ConnectionClass *conn;
char *table_type[32], table_types[MAX_INFO_STRING]; ConnInfo *ci;
char show_system_tables, show_regular_tables, show_views; char *prefix[32],
char regular_table, view, systable; prefixes[MEDIUM_REGISTRY_LEN];
int i; char *table_type[32],
table_types[MAX_INFO_STRING];
mylog("%s: entering...stmt=%u\n", func, stmt); char show_system_tables,
show_regular_tables,
if( ! stmt) { show_views;
char regular_table,
view,
systable;
int i;
mylog("%s: entering...stmt=%u\n", func, stmt);
if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -959,8 +1151,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -959,8 +1151,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
conn = (ConnectionClass *) (stmt->hdbc); conn = (ConnectionClass *) (stmt->hdbc);
ci = &stmt->hdbc->connInfo; ci = &stmt->hdbc->connInfo;
result = SQLAllocStmt( stmt->hdbc, &htbl_stmt); result = SQLAllocStmt(stmt->hdbc, &htbl_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLTables result."; stmt->errormsg = "Couldn't allocate statement for SQLTables result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -972,11 +1165,14 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -972,11 +1165,14 @@ mylog("%s: entering...stmt=%u\n", func, 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 */ if (PG_VERSION_GE(conn, 7.1))
{ /* view is represented by its relkind
* since 7.1 */
strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user"); strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
strcat(tables_query, " where relkind in ('r', 'v')"); strcat(tables_query, " where relkind in ('r', 'v')");
} }
else { else
{
strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user"); strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
strcat(tables_query, " where relkind = 'r'"); strcat(tables_query, " where relkind = 'r'");
} }
...@@ -989,7 +1185,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -989,7 +1185,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
strcpy(prefixes, globals.extra_systable_prefixes); strcpy(prefixes, globals.extra_systable_prefixes);
i = 0; i = 0;
prefix[i] = strtok(prefixes, ";"); prefix[i] = strtok(prefixes, ";");
while (prefix[i] && i<32) { while (prefix[i] && i < 32)
{
prefix[++i] = strtok(NULL, ";"); prefix[++i] = strtok(NULL, ";");
} }
...@@ -1000,43 +1197,48 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1000,43 +1197,48 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* make_string mallocs memory */ /* make_string mallocs memory */
tableType = make_string(szTableType, cbTableType, NULL); tableType = make_string(szTableType, cbTableType, NULL);
if (tableType) { if (tableType)
{
strcpy(table_types, tableType); strcpy(table_types, tableType);
free(tableType); free(tableType);
i = 0; i = 0;
table_type[i] = strtok(table_types, ","); table_type[i] = strtok(table_types, ",");
while (table_type[i] && i<32) { while (table_type[i] && i < 32)
table_type[++i] = strtok(NULL, ","); table_type[++i] = strtok(NULL, ",");
}
/* Check for desired table types to return */ /* Check for desired table types to return */
i = 0; i = 0;
while (table_type[i]) { while (table_type[i])
if ( strstr(table_type[i], "SYSTEM TABLE")) {
if (strstr(table_type[i], "SYSTEM TABLE"))
show_system_tables = TRUE; show_system_tables = TRUE;
else if ( strstr(table_type[i], "TABLE")) else if (strstr(table_type[i], "TABLE"))
show_regular_tables = TRUE; show_regular_tables = TRUE;
else if ( strstr(table_type[i], "VIEW")) else if (strstr(table_type[i], "VIEW"))
show_views = TRUE; show_views = TRUE;
i++; i++;
} }
} }
else { else
{
show_regular_tables = TRUE; show_regular_tables = TRUE;
show_views = TRUE; show_views = TRUE;
} }
/* If not interested in SYSTEM TABLES then filter them out /*
to save some time on the query. If treating system tables * If not interested in SYSTEM TABLES then filter them out to save
as regular tables, then dont filter either. * some time on the query. If treating system tables as regular
* tables, then dont filter either.
*/ */
if ( ! atoi(ci->show_system_tables) && ! show_system_tables) { if (!atoi(ci->show_system_tables) && !show_system_tables)
{
strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX); strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX);
/* Also filter out user-defined system table types */ /* Also filter out user-defined system table types */
i = 0; i = 0;
while(prefix[i]) { while (prefix[i])
{
strcat(tables_query, "|^"); strcat(tables_query, "|^");
strcat(tables_query, prefix[i]); strcat(tables_query, prefix[i]);
i++; i++;
...@@ -1047,7 +1249,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1047,7 +1249,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* match users */ /* 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 relname !~ '^xinv[0-9]+'");
strcat(tables_query, " and usesysid = relowner"); strcat(tables_query, " and usesysid = relowner");
...@@ -1056,7 +1259,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1056,7 +1259,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* ********************************************************************** */ /* ********************************************************************** */
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1066,7 +1270,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1066,7 +1270,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
result = SQLBindCol(htbl_stmt, 1, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 1, SQL_C_CHAR,
table_name, MAX_INFO_STRING, NULL); table_name, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1076,7 +1281,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1076,7 +1281,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
result = SQLBindCol(htbl_stmt, 2, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 2, SQL_C_CHAR,
table_owner, MAX_INFO_STRING, NULL); table_owner, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1085,7 +1291,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1085,7 +1291,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
relkind_or_hasrules, MAX_INFO_STRING, NULL); relkind_or_hasrules, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1094,7 +1301,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1094,7 +1301,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
stmt->result = QR_Constructor(); stmt->result = QR_Constructor();
if(!stmt->result) { if (!stmt->result)
{
stmt->errormsg = "Couldn't allocate memory for SQLTables result."; stmt->errormsg = "Couldn't allocate memory for SQLTables result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1103,7 +1311,11 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1103,7 +1311,11 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
/* a statement is actually executed, so we'll have to do this ourselves. */
/*
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
extend_bindings(stmt, 5); extend_bindings(stmt, 5);
/* set the field names */ /* set the field names */
...@@ -1116,23 +1328,28 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1116,23 +1328,28 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* add the tuples */ /* add the tuples */
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { 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 * Determine if this table name is a system table. If treating
no need to do this test. * system tables as regular tables, then no need to do this test.
*/ */
systable = FALSE; systable = FALSE;
if( ! atoi(ci->show_system_tables)) { if (!atoi(ci->show_system_tables))
{
if ( strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0) if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
systable = TRUE; systable = TRUE;
else { /* Check extra system table prefixes */ else
{ /* Check extra system table prefixes */
i = 0; i = 0;
while (prefix[i]) { while (prefix[i])
{
mylog("table_name='%s', prefix[%d]='%s'\n", table_name, i, prefix[i]); mylog("table_name='%s', prefix[%d]='%s'\n", table_name, i, prefix[i]);
if (strncmp(table_name, prefix[i], strlen(prefix[i])) == 0) { if (strncmp(table_name, prefix[i], strlen(prefix[i])) == 0)
{
systable = TRUE; systable = TRUE;
break; break;
} }
...@@ -1142,23 +1359,28 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1142,23 +1359,28 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
/* Determine if the table name is a view */ /* 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'); view = (relkind_or_hasrules[0] == 'v');
else else
view = (relkind_or_hasrules[0] == '1'); view = (relkind_or_hasrules[0] == '1');
/* It must be a regular table */ /* It must be a regular table */
regular_table = ( ! systable && ! view); regular_table = (!systable && !view);
/* Include the row in the result set if meets all criteria */ /* Include the row in the result set if meets all criteria */
/* NOTE: Unsupported table types (i.e., LOCAL TEMPORARY, ALIAS, etc)
will return nothing */ /*
if ( (systable && show_system_tables) || * NOTE: Unsupported table types (i.e., LOCAL TEMPORARY, ALIAS,
* etc) will return nothing
*/
if ((systable && show_system_tables) ||
(view && show_views) || (view && show_views) ||
(regular_table && show_regular_tables)) { (regular_table && show_regular_tables))
{
row = (TupleNode *)malloc(sizeof(TupleNode) + (5 - 1) * sizeof(TupleField)); row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) * sizeof(TupleField));
set_tuplefield_string(&row->tuple[0], ""); set_tuplefield_string(&row->tuple[0], "");
...@@ -1179,7 +1401,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1179,7 +1401,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
} }
if(result != SQL_NO_DATA_FOUND) { if (result != SQL_NO_DATA_FOUND)
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1204,7 +1427,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1204,7 +1427,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
RETCODE SQL_API SQLColumns( RETCODE SQL_API
SQLColumns(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -1215,25 +1439,36 @@ RETCODE SQL_API SQLColumns( ...@@ -1215,25 +1439,36 @@ RETCODE SQL_API SQLColumns(
UCHAR FAR * szColumnName, UCHAR FAR * szColumnName,
SWORD cbColumnName) SWORD cbColumnName)
{ {
static char *func = "SQLColumns"; static char *func = "SQLColumns";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row; TupleNode *row;
HSTMT hcol_stmt; HSTMT hcol_stmt;
StatementClass *col_stmt; StatementClass *col_stmt;
char columns_query[STD_STATEMENT_LEN]; char columns_query[STD_STATEMENT_LEN];
RETCODE result; RETCODE result;
char table_owner[MAX_INFO_STRING], table_name[MAX_INFO_STRING], field_name[MAX_INFO_STRING], field_type_name[MAX_INFO_STRING]; char table_owner[MAX_INFO_STRING],
Int2 field_number, result_cols, scale; table_name[MAX_INFO_STRING],
Int4 field_type, the_type, field_length, mod_length, precision; field_name[MAX_INFO_STRING],
char useStaticPrecision; field_type_name[MAX_INFO_STRING];
char not_null[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING]; Int2 field_number,
ConnInfo *ci; result_cols,
ConnectionClass *conn; scale;
Int4 field_type,
the_type,
field_length,
mod_length,
precision;
char useStaticPrecision;
char not_null[MAX_INFO_STRING],
relhasrules[MAX_INFO_STRING];
ConnInfo *ci;
ConnectionClass *conn;
mylog("%s: entering...stmt=%u\n", func, stmt); mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -1245,7 +1480,11 @@ ConnectionClass *conn; ...@@ -1245,7 +1480,11 @@ ConnectionClass *conn;
ci = &stmt->hdbc->connInfo; ci = &stmt->hdbc->connInfo;
/* ********************************************************************** */ /* ********************************************************************** */
/* Create the query to find out the columns (Note: pre 6.3 did not have the atttypmod field) */
/*
* 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" sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules" ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
...@@ -1263,8 +1502,9 @@ ConnectionClass *conn; ...@@ -1263,8 +1502,9 @@ ConnectionClass *conn;
strcat(columns_query, " order by attnum"); strcat(columns_query, " order by attnum");
/* ********************************************************************** */ /* ********************************************************************** */
result = SQLAllocStmt( stmt->hdbc, &hcol_stmt); result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLColumns result."; stmt->errormsg = "Couldn't allocate statement for SQLColumns result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1276,7 +1516,8 @@ ConnectionClass *conn; ...@@ -1276,7 +1516,8 @@ ConnectionClass *conn;
result = SQLExecDirect(hcol_stmt, columns_query, result = SQLExecDirect(hcol_stmt, columns_query,
strlen(columns_query)); strlen(columns_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(hcol_stmt); stmt->errormsg = SC_create_errormsg(hcol_stmt);
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1286,7 +1527,8 @@ ConnectionClass *conn; ...@@ -1286,7 +1527,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 1, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 1, SQL_C_CHAR,
table_owner, MAX_INFO_STRING, NULL); table_owner, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1296,7 +1538,8 @@ ConnectionClass *conn; ...@@ -1296,7 +1538,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 2, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 2, SQL_C_CHAR,
table_name, MAX_INFO_STRING, NULL); table_name, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1306,7 +1549,8 @@ ConnectionClass *conn; ...@@ -1306,7 +1549,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 3, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 3, SQL_C_CHAR,
field_name, MAX_INFO_STRING, NULL); field_name, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1316,7 +1560,8 @@ ConnectionClass *conn; ...@@ -1316,7 +1560,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 4, SQL_C_LONG, result = SQLBindCol(hcol_stmt, 4, SQL_C_LONG,
&field_type, 4, NULL); &field_type, 4, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1326,7 +1571,8 @@ ConnectionClass *conn; ...@@ -1326,7 +1571,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 5, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 5, SQL_C_CHAR,
field_type_name, MAX_INFO_STRING, NULL); field_type_name, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1336,7 +1582,8 @@ ConnectionClass *conn; ...@@ -1336,7 +1582,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 6, SQL_C_SHORT, result = SQLBindCol(hcol_stmt, 6, SQL_C_SHORT,
&field_number, MAX_INFO_STRING, NULL); &field_number, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1346,7 +1593,8 @@ ConnectionClass *conn; ...@@ -1346,7 +1593,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 7, SQL_C_LONG, result = SQLBindCol(hcol_stmt, 7, SQL_C_LONG,
&field_length, MAX_INFO_STRING, NULL); &field_length, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1356,7 +1604,8 @@ ConnectionClass *conn; ...@@ -1356,7 +1604,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 8, SQL_C_LONG, result = SQLBindCol(hcol_stmt, 8, SQL_C_LONG,
&mod_length, MAX_INFO_STRING, NULL); &mod_length, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1366,7 +1615,8 @@ ConnectionClass *conn; ...@@ -1366,7 +1615,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 9, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 9, SQL_C_CHAR,
not_null, MAX_INFO_STRING, NULL); not_null, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1376,7 +1626,8 @@ ConnectionClass *conn; ...@@ -1376,7 +1626,8 @@ ConnectionClass *conn;
result = SQLBindCol(hcol_stmt, 10, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 10, SQL_C_CHAR,
relhasrules, MAX_INFO_STRING, NULL); relhasrules, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1385,7 +1636,8 @@ ConnectionClass *conn; ...@@ -1385,7 +1636,8 @@ ConnectionClass *conn;
} }
stmt->result = QR_Constructor(); stmt->result = QR_Constructor();
if(!stmt->result) { if (!stmt->result)
{
stmt->errormsg = "Couldn't allocate memory for SQLColumns result."; stmt->errormsg = "Couldn't allocate memory for SQLColumns result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1394,7 +1646,11 @@ ConnectionClass *conn; ...@@ -1394,7 +1646,11 @@ ConnectionClass *conn;
} }
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
/* a statement is actually executed, so we'll have to do this ourselves. */
/*
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
result_cols = 14; result_cols = 14;
extend_bindings(stmt, result_cols); extend_bindings(stmt, result_cols);
...@@ -1421,20 +1677,23 @@ ConnectionClass *conn; ...@@ -1421,20 +1677,23 @@ ConnectionClass *conn;
result = SQLFetch(hcol_stmt); result = SQLFetch(hcol_stmt);
/* Only show oid if option AND there are other columns AND /*
it's not being called by SQLStatistics . * Only show oid if option AND there are other columns AND it's not
Always show OID if it's a system table * being called by SQLStatistics . Always show OID if it's a system
* table
*/ */
if (result != SQL_ERROR && ! stmt->internal) { if (result != SQL_ERROR && !stmt->internal)
{
if (relhasrules[0] != '1' && if (relhasrules[0] != '1' &&
(atoi(ci->show_oid_column) || (atoi(ci->show_oid_column) ||
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)) { strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
{
/* For OID fields */ /* For OID fields */
the_type = PG_TYPE_OID; the_type = PG_TYPE_OID;
row = (TupleNode *)malloc(sizeof(TupleNode) + row = (TupleNode *) malloc(sizeof(TupleNode) +
(result_cols - 1) * sizeof(TupleField)); (result_cols - 1) * sizeof(TupleField));
set_tuplefield_string(&row->tuple[0], ""); set_tuplefield_string(&row->tuple[0], "");
...@@ -1462,8 +1721,9 @@ ConnectionClass *conn; ...@@ -1462,8 +1721,9 @@ ConnectionClass *conn;
} }
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
row = (TupleNode *)malloc(sizeof(TupleNode) + {
row = (TupleNode *) malloc(sizeof(TupleNode) +
(result_cols - 1) * sizeof(TupleField)); (result_cols - 1) * sizeof(TupleField));
...@@ -1477,33 +1737,36 @@ ConnectionClass *conn; ...@@ -1477,33 +1737,36 @@ ConnectionClass *conn;
set_tuplefield_string(&row->tuple[5], field_type_name); set_tuplefield_string(&row->tuple[5], field_type_name);
/* Some Notes about Postgres Data Types: /*
* Some Notes about Postgres Data Types:
VARCHAR - the length is stored in the pg_attribute.atttypmod field *
BPCHAR - the length is also stored as varchar is * VARCHAR - the length is stored in the pg_attribute.atttypmod field
* BPCHAR - the length is also stored as varchar is
NUMERIC - the scale is stored in atttypmod as follows: *
precision = ((atttypmod - VARHDRSZ) >> 16) & 0xffff * NUMERIC - the scale is stored in atttypmod as follows: precision =
scale = (atttypmod - VARHDRSZ) & 0xffff * ((atttypmod - VARHDRSZ) >> 16) & 0xffff scale = (atttypmod
* - VARHDRSZ) & 0xffff
*
*
*/ */
qlog("SQLColumns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n", qlog("SQLColumns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n",
table_name,field_name,field_type,pgtype_to_sqltype,field_type_name); table_name, field_name, field_type, pgtype_to_sqltype, field_type_name);
useStaticPrecision = TRUE; useStaticPrecision = TRUE;
if (field_type == PG_TYPE_NUMERIC) { if (field_type == PG_TYPE_NUMERIC)
{
if (mod_length >= 4) if (mod_length >= 4)
mod_length -= 4; /* the length is in atttypmod - 4 */ mod_length -= 4;/* the length is in atttypmod - 4 */
if (mod_length >= 0) { if (mod_length >= 0)
{
useStaticPrecision = FALSE; useStaticPrecision = FALSE;
precision = (mod_length >> 16) & 0xffff; precision = (mod_length >> 16) & 0xffff;
scale = mod_length & 0xffff; scale = mod_length & 0xffff;
mylog("SQLColumns: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", field_type, mod_length, precision, scale ); mylog("SQLColumns: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", field_type, mod_length, precision, scale);
set_tuplefield_int4(&row->tuple[7], precision + 2); /* sign+dec.point */ set_tuplefield_int4(&row->tuple[7], precision + 2); /* sign+dec.point */
set_tuplefield_int4(&row->tuple[6], precision); set_tuplefield_int4(&row->tuple[6], precision);
...@@ -1513,13 +1776,14 @@ ConnectionClass *conn; ...@@ -1513,13 +1776,14 @@ ConnectionClass *conn;
} }
if((field_type == PG_TYPE_VARCHAR) || if ((field_type == PG_TYPE_VARCHAR) ||
(field_type == PG_TYPE_BPCHAR)) { (field_type == PG_TYPE_BPCHAR))
{
useStaticPrecision = FALSE; useStaticPrecision = FALSE;
if (mod_length >= 4) if (mod_length >= 4)
mod_length -= 4; /* the length is in atttypmod - 4 */ mod_length -= 4;/* the length is in atttypmod - 4 */
if (mod_length > globals.max_varchar_size || mod_length <= 0) if (mod_length > globals.max_varchar_size || mod_length <= 0)
mod_length = globals.max_varchar_size; mod_length = globals.max_varchar_size;
...@@ -1532,7 +1796,8 @@ ConnectionClass *conn; ...@@ -1532,7 +1796,8 @@ ConnectionClass *conn;
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC)); set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC));
} }
if (useStaticPrecision) { if (useStaticPrecision)
{
mylog("SQLColumns: field type is OTHER: field_type = %d, pgtype_length = %d\n", field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC)); mylog("SQLColumns: field type is OTHER: field_type = %d, pgtype_length = %d\n", field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
...@@ -1552,7 +1817,8 @@ ConnectionClass *conn; ...@@ -1552,7 +1817,8 @@ ConnectionClass *conn;
result = SQLFetch(hcol_stmt); result = SQLFetch(hcol_stmt);
} }
if(result != SQL_NO_DATA_FOUND) { if (result != SQL_NO_DATA_FOUND)
{
stmt->errormsg = SC_create_errormsg(hcol_stmt); stmt->errormsg = SC_create_errormsg(hcol_stmt);
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1562,11 +1828,12 @@ ConnectionClass *conn; ...@@ -1562,11 +1828,12 @@ ConnectionClass *conn;
/* Put the row version column at the end so it might not be */ /* Put the row version column at the end so it might not be */
/* mistaken for a key field. */ /* mistaken for a key field. */
if ( relhasrules[0] != '1' && ! stmt->internal && atoi(ci->row_versioning)) { if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
{
/* For Row Versioning fields */ /* For Row Versioning fields */
the_type = PG_TYPE_INT4; the_type = PG_TYPE_INT4;
row = (TupleNode *)malloc(sizeof(TupleNode) + row = (TupleNode *) malloc(sizeof(TupleNode) +
(result_cols - 1) * sizeof(TupleField)); (result_cols - 1) * sizeof(TupleField));
set_tuplefield_string(&row->tuple[0], ""); set_tuplefield_string(&row->tuple[0], "");
...@@ -1601,7 +1868,8 @@ ConnectionClass *conn; ...@@ -1601,7 +1868,8 @@ ConnectionClass *conn;
return SQL_SUCCESS; return SQL_SUCCESS;
} }
RETCODE SQL_API SQLSpecialColumns( RETCODE SQL_API
SQLSpecialColumns(
HSTMT hstmt, HSTMT hstmt,
UWORD fColType, UWORD fColType,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
...@@ -1613,21 +1881,22 @@ RETCODE SQL_API SQLSpecialColumns( ...@@ -1613,21 +1881,22 @@ RETCODE SQL_API SQLSpecialColumns(
UWORD fScope, UWORD fScope,
UWORD fNullable) UWORD fNullable)
{ {
static char *func = "SQLSpecialColumns"; static char *func = "SQLSpecialColumns";
TupleNode *row; TupleNode *row;
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
ConnInfo *ci; ConnInfo *ci;
HSTMT hcol_stmt; HSTMT hcol_stmt;
StatementClass *col_stmt; StatementClass *col_stmt;
char columns_query[STD_STATEMENT_LEN]; char columns_query[STD_STATEMENT_LEN];
RETCODE result; RETCODE result;
char relhasrules[MAX_INFO_STRING]; char relhasrules[MAX_INFO_STRING];
mylog("%s: entering...stmt=%u\n", func, stmt); mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -1647,8 +1916,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1647,8 +1916,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner); my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
result = SQLAllocStmt( stmt->hdbc, &hcol_stmt); result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLSpecialColumns result."; stmt->errormsg = "Couldn't allocate statement for SQLSpecialColumns result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1660,7 +1930,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1660,7 +1930,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
result = SQLExecDirect(hcol_stmt, columns_query, result = SQLExecDirect(hcol_stmt, columns_query,
strlen(columns_query)); strlen(columns_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(hcol_stmt); stmt->errormsg = SC_create_errormsg(hcol_stmt);
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1670,7 +1941,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1670,7 +1941,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
result = SQLBindCol(hcol_stmt, 1, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 1, SQL_C_CHAR,
relhasrules, MAX_INFO_STRING, NULL); relhasrules, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1694,10 +1966,12 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1694,10 +1966,12 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2); QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2); QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
if ( relhasrules[0] != '1' ) { if (relhasrules[0] != '1')
{
/* use the oid value for the rowid */ /* use the oid value for the rowid */
if(fColType == SQL_BEST_ROWID) { if (fColType == SQL_BEST_ROWID)
row = (TupleNode *)malloc(sizeof(TupleNode) + (8 - 1) * sizeof(TupleField)); {
row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) * sizeof(TupleField));
set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION); set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION);
set_tuplefield_string(&row->tuple[1], "oid"); set_tuplefield_string(&row->tuple[1], "oid");
...@@ -1710,12 +1984,15 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1710,12 +1984,15 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
QR_add_tuple(stmt->result, row); QR_add_tuple(stmt->result, row);
} else if(fColType == SQL_ROWVER) { }
else if (fColType == SQL_ROWVER)
{
Int2 the_type = PG_TYPE_INT4; Int2 the_type = PG_TYPE_INT4;
if (atoi(ci->row_versioning)) { if (atoi(ci->row_versioning))
row = (TupleNode *)malloc(sizeof(TupleNode) + (8 - 1) * sizeof(TupleField)); {
row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) * sizeof(TupleField));
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
set_tuplefield_string(&row->tuple[1], "xmin"); set_tuplefield_string(&row->tuple[1], "xmin");
...@@ -1742,7 +2019,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1742,7 +2019,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
RETCODE SQL_API SQLStatistics( RETCODE SQL_API
SQLStatistics(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -1753,31 +2031,36 @@ RETCODE SQL_API SQLStatistics( ...@@ -1753,31 +2031,36 @@ RETCODE SQL_API SQLStatistics(
UWORD fUnique, UWORD fUnique,
UWORD fAccuracy) UWORD fAccuracy)
{ {
static char *func="SQLStatistics"; static char *func = "SQLStatistics";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
char index_query[STD_STATEMENT_LEN]; char index_query[STD_STATEMENT_LEN];
HSTMT hindx_stmt; HSTMT hindx_stmt;
RETCODE result; RETCODE result;
char *table_name; char *table_name;
char index_name[MAX_INFO_STRING]; char index_name[MAX_INFO_STRING];
short fields_vector[8]; short fields_vector[8];
char isunique[10], isclustered[10]; char isunique[10],
SDWORD index_name_len, fields_vector_len; isclustered[10];
TupleNode *row; SDWORD index_name_len,
int i; fields_vector_len;
HSTMT hcol_stmt; TupleNode *row;
StatementClass *col_stmt, *indx_stmt; int i;
char column_name[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING]; HSTMT hcol_stmt;
char **column_names = 0; StatementClass *col_stmt,
Int4 column_name_len; *indx_stmt;
int total_columns = 0; char column_name[MAX_INFO_STRING],
char error = TRUE; relhasrules[MAX_INFO_STRING];
ConnInfo *ci; char **column_names = 0;
char buf[256]; Int4 column_name_len;
int total_columns = 0;
mylog("%s: entering...stmt=%u\n", func, stmt); char error = TRUE;
ConnInfo *ci;
if( ! stmt) { char buf[256];
mylog("%s: entering...stmt=%u\n", func, stmt);
if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -1788,7 +2071,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1788,7 +2071,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
ci = &stmt->hdbc->connInfo; ci = &stmt->hdbc->connInfo;
stmt->result = QR_Constructor(); stmt->result = QR_Constructor();
if(!stmt->result) { if (!stmt->result)
{
stmt->errormsg = "Couldn't allocate memory for SQLStatistics result."; stmt->errormsg = "Couldn't allocate memory for SQLStatistics result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1796,7 +2080,11 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1796,7 +2080,11 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
/* a statement is actually executed, so we'll have to do this ourselves. */
/*
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
extend_bindings(stmt, 13); extend_bindings(stmt, 13);
/* set the field names */ /* set the field names */
...@@ -1819,7 +2107,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1819,7 +2107,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* only use the table name... the owner should be redundant, and */ /* only use the table name... the owner should be redundant, and */
/* we never use qualifiers. */ /* we never use qualifiers. */
table_name = make_string(szTableName, cbTableName, NULL); table_name = make_string(szTableName, cbTableName, NULL);
if ( ! table_name) { if (!table_name)
{
stmt->errormsg = "No table name passed to SQLStatistics."; stmt->errormsg = "No table name passed to SQLStatistics.";
stmt->errornumber = STMT_INTERNAL_ERROR; stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1828,8 +2117,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1828,8 +2117,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* we need to get a list of the field names first, */ /* we need to get a list of the field names first, */
/* so we can return them later. */ /* so we can return them later. */
result = SQLAllocStmt( stmt->hdbc, &hcol_stmt); result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = "SQLAllocStmt failed in SQLStatistics for columns."; stmt->errormsg = "SQLAllocStmt failed in SQLStatistics for columns.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
goto SEEYA; goto SEEYA;
...@@ -1837,23 +2127,27 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1837,23 +2127,27 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
col_stmt = (StatementClass *) hcol_stmt; col_stmt = (StatementClass *) hcol_stmt;
/* "internal" prevents SQLColumns from returning the oid if it is being shown. /*
This would throw everything off. * "internal" prevents SQLColumns from returning the oid if it is
* being shown. This would throw everything off.
*/ */
col_stmt->internal = TRUE; col_stmt->internal = TRUE;
result = SQLColumns(hcol_stmt, "", 0, "", 0, result = SQLColumns(hcol_stmt, "", 0, "", 0,
table_name, (SWORD) strlen(table_name), "", 0); table_name, (SWORD) strlen(table_name), "", 0);
col_stmt->internal = FALSE; col_stmt->internal = FALSE;
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
stmt->errormsg = col_stmt->errormsg; /* "SQLColumns failed in SQLStatistics."; */ {
stmt->errormsg = col_stmt->errormsg; /* "SQLColumns failed in
* SQLStatistics."; */
stmt->errornumber = col_stmt->errornumber; /* STMT_EXEC_ERROR; */ stmt->errornumber = col_stmt->errornumber; /* STMT_EXEC_ERROR; */
SQLFreeStmt(hcol_stmt, SQL_DROP); SQLFreeStmt(hcol_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
} }
result = SQLBindCol(hcol_stmt, 4, SQL_C_CHAR, result = SQLBindCol(hcol_stmt, 4, SQL_C_CHAR,
column_name, MAX_INFO_STRING, &column_name_len); column_name, MAX_INFO_STRING, &column_name_len);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = col_stmt->errormsg; stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SQLFreeStmt(hcol_stmt, SQL_DROP); SQLFreeStmt(hcol_stmt, SQL_DROP);
...@@ -1862,22 +2156,26 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1862,22 +2156,26 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
result = SQLFetch(hcol_stmt); result = SQLFetch(hcol_stmt);
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
total_columns++; total_columns++;
column_names = column_names =
(char **)realloc(column_names, (char **) realloc(column_names,
total_columns * sizeof(char *)); total_columns * sizeof(char *));
column_names[total_columns-1] = column_names[total_columns - 1] =
(char *)malloc(strlen(column_name)+1); (char *) malloc(strlen(column_name) + 1);
strcpy(column_names[total_columns-1], column_name); strcpy(column_names[total_columns - 1], column_name);
mylog("SQLStatistics: column_name = '%s'\n", column_name); mylog("SQLStatistics: column_name = '%s'\n", column_name);
result = SQLFetch(hcol_stmt); result = SQLFetch(hcol_stmt);
} }
if(result != SQL_NO_DATA_FOUND || total_columns == 0) { if (result != SQL_NO_DATA_FOUND || total_columns == 0)
stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column names in SQLStatistics."; */ {
stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column
* names in
* SQLStatistics."; */
stmt->errornumber = col_stmt->errornumber; stmt->errornumber = col_stmt->errornumber;
SQLFreeStmt(hcol_stmt, SQL_DROP); SQLFreeStmt(hcol_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -1887,8 +2185,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1887,8 +2185,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP); SQLFreeStmt(hcol_stmt, SQL_DROP);
/* get a list of indexes on this table */ /* get a list of indexes on this table */
result = SQLAllocStmt( stmt->hdbc, &hindx_stmt); result = SQLAllocStmt(stmt->hdbc, &hindx_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = "SQLAllocStmt failed in SQLStatistics for indices."; stmt->errormsg = "SQLAllocStmt failed in SQLStatistics for indices.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
goto SEEYA; goto SEEYA;
...@@ -1903,8 +2202,12 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1903,8 +2202,12 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
" and d.oid = i.indrelid", table_name); " and d.oid = i.indrelid", table_name);
result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query)); result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { 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."; */ {
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "Couldn't execute
* index query
* (w/SQLExecDirect) in
* SQLStatistics."; */
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -1914,8 +2217,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1914,8 +2217,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* bind the index name column */ /* bind the index name column */
result = SQLBindCol(hindx_stmt, 1, SQL_C_CHAR, result = SQLBindCol(hindx_stmt, 1, SQL_C_CHAR,
index_name, MAX_INFO_STRING, &index_name_len); index_name, MAX_INFO_STRING, &index_name_len);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column in SQLStatistics."; */ {
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column
* in SQLStatistics."; */
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -1924,8 +2229,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1924,8 +2229,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* bind the vector column */ /* bind the vector column */
result = SQLBindCol(hindx_stmt, 2, SQL_C_DEFAULT, result = SQLBindCol(hindx_stmt, 2, SQL_C_DEFAULT,
fields_vector, 16, &fields_vector_len); fields_vector, 16, &fields_vector_len);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column in SQLStatistics."; */ {
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column
* in SQLStatistics."; */
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -1934,8 +2241,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1934,8 +2241,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* bind the "is unique" column */ /* bind the "is unique" column */
result = SQLBindCol(hindx_stmt, 3, SQL_C_CHAR, result = SQLBindCol(hindx_stmt, 3, SQL_C_CHAR,
isunique, sizeof(isunique), NULL); isunique, sizeof(isunique), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column in SQLStatistics."; */ {
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column
* in SQLStatistics."; */
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -1944,8 +2253,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1944,8 +2253,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* bind the "is clustered" column */ /* bind the "is clustered" column */
result = SQLBindCol(hindx_stmt, 4, SQL_C_CHAR, result = SQLBindCol(hindx_stmt, 4, SQL_C_CHAR,
isclustered, sizeof(isclustered), NULL); isclustered, sizeof(isclustered), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column in SQLStatistics."; */ {
stmt->errormsg = indx_stmt->errormsg; /* "Couldn't bind column
* in SQLStatistics."; */
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -1954,7 +2265,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1954,7 +2265,8 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
result = SQLBindCol(hindx_stmt, 5, SQL_C_CHAR, result = SQLBindCol(hindx_stmt, 5, SQL_C_CHAR,
relhasrules, MAX_INFO_STRING, NULL); relhasrules, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = indx_stmt->errormsg; stmt->errormsg = indx_stmt->errormsg;
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
...@@ -1962,8 +2274,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1962,8 +2274,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
/* fake index of OID */ /* fake index of OID */
if ( relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index)) { if (relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index))
row = (TupleNode *)malloc(sizeof(TupleNode) + {
row = (TupleNode *) malloc(sizeof(TupleNode) +
(13 - 1) * sizeof(TupleField)); (13 - 1) * sizeof(TupleField));
/* no table qualifier */ /* no table qualifier */
...@@ -1981,7 +2294,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1981,7 +2294,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
sprintf(buf, "%s_idx_fake_oid", table_name); sprintf(buf, "%s_idx_fake_oid", table_name);
set_tuplefield_string(&row->tuple[5], buf); set_tuplefield_string(&row->tuple[5], buf);
/* Clustered index? I think non-clustered should be type OTHER not HASHED */ /*
* Clustered index? I think non-clustered should be type OTHER
* not HASHED
*/
set_tuplefield_int2(&row->tuple[6], (Int2) SQL_INDEX_OTHER); set_tuplefield_int2(&row->tuple[6], (Int2) SQL_INDEX_OTHER);
set_tuplefield_int2(&row->tuple[7], (Int2) 1); set_tuplefield_int2(&row->tuple[7], (Int2) 1);
...@@ -1995,16 +2311,19 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -1995,16 +2311,19 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
} }
result = SQLFetch(hindx_stmt); result = SQLFetch(hindx_stmt);
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
/* If only requesting unique indexs, then just return those. */ /* If only requesting unique indexs, then just return those. */
if (fUnique == SQL_INDEX_ALL || if (fUnique == SQL_INDEX_ALL ||
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique))) { (fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
{
i = 0; i = 0;
/* add a row in this table for each field in the index */ /* add a row in this table for each field in the index */
while(i < 8 && fields_vector[i] != 0) { while (i < 8 && fields_vector[i] != 0)
{
row = (TupleNode *)malloc(sizeof(TupleNode) + row = (TupleNode *) malloc(sizeof(TupleNode) +
(13 - 1) * sizeof(TupleField)); (13 - 1) * sizeof(TupleField));
/* no table qualifier */ /* no table qualifier */
...@@ -2023,21 +2342,27 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -2023,21 +2342,27 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
set_tuplefield_string(&row->tuple[4], ""); set_tuplefield_string(&row->tuple[4], "");
set_tuplefield_string(&row->tuple[5], index_name); set_tuplefield_string(&row->tuple[5], index_name);
/* Clustered index? I think non-clustered should be type OTHER not HASHED */ /*
* Clustered index? I think non-clustered should be type
* OTHER not HASHED
*/
set_tuplefield_int2(&row->tuple[6], (Int2) (atoi(isclustered) ? SQL_INDEX_CLUSTERED : SQL_INDEX_OTHER)); set_tuplefield_int2(&row->tuple[6], (Int2) (atoi(isclustered) ? SQL_INDEX_CLUSTERED : SQL_INDEX_OTHER));
set_tuplefield_int2(&row->tuple[7], (Int2) (i+1)); set_tuplefield_int2(&row->tuple[7], (Int2) (i + 1));
if(fields_vector[i] == OID_ATTNUM) { if (fields_vector[i] == OID_ATTNUM)
{
set_tuplefield_string(&row->tuple[8], "oid"); set_tuplefield_string(&row->tuple[8], "oid");
mylog("SQLStatistics: column name = oid\n"); mylog("SQLStatistics: column name = oid\n");
} }
else if(fields_vector[i] < 0 || fields_vector[i] > total_columns) { else if (fields_vector[i] < 0 || fields_vector[i] > total_columns)
{
set_tuplefield_string(&row->tuple[8], "UNKNOWN"); set_tuplefield_string(&row->tuple[8], "UNKNOWN");
mylog("SQLStatistics: column name = UNKNOWN\n"); mylog("SQLStatistics: column name = UNKNOWN\n");
} }
else { else
set_tuplefield_string(&row->tuple[8], column_names[fields_vector[i]-1]); {
mylog("SQLStatistics: column name = '%s'\n", column_names[fields_vector[i]-1]); set_tuplefield_string(&row->tuple[8], column_names[fields_vector[i] - 1]);
mylog("SQLStatistics: column name = '%s'\n", column_names[fields_vector[i] - 1]);
} }
set_tuplefield_string(&row->tuple[9], "A"); set_tuplefield_string(&row->tuple[9], "A");
...@@ -2052,8 +2377,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -2052,8 +2377,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
result = SQLFetch(hindx_stmt); result = SQLFetch(hindx_stmt);
} }
if(result != SQL_NO_DATA_FOUND) { if (result != SQL_NO_DATA_FOUND)
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "SQLFetch failed in SQLStatistics."; */ {
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "SQLFetch failed in
* SQLStatistics."; */
stmt->errornumber = indx_stmt->errornumber; stmt->errornumber = indx_stmt->errornumber;
SQLFreeStmt(hindx_stmt, SQL_DROP); SQLFreeStmt(hindx_stmt, SQL_DROP);
goto SEEYA; goto SEEYA;
...@@ -2075,14 +2402,14 @@ mylog("%s: entering...stmt=%u\n", func, stmt); ...@@ -2075,14 +2402,14 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
SEEYA: SEEYA:
/* These things should be freed on any error ALSO! */ /* These things should be freed on any error ALSO! */
free(table_name); free(table_name);
for(i = 0; i < total_columns; i++) { for (i = 0; i < total_columns; i++)
free(column_names[i]); free(column_names[i]);
}
free(column_names); free(column_names);
mylog("SQLStatistics(): EXIT, %s, stmt=%u\n", error ? "error" : "success", stmt); mylog("SQLStatistics(): EXIT, %s, stmt=%u\n", error ? "error" : "success", stmt);
if (error) { if (error)
{
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -2090,7 +2417,8 @@ SEEYA: ...@@ -2090,7 +2417,8 @@ SEEYA:
return SQL_SUCCESS; return SQL_SUCCESS;
} }
RETCODE SQL_API SQLColumnPrivileges( RETCODE SQL_API
SQLColumnPrivileges(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -2101,7 +2429,7 @@ RETCODE SQL_API SQLColumnPrivileges( ...@@ -2101,7 +2429,7 @@ RETCODE SQL_API SQLColumnPrivileges(
UCHAR FAR * szColumnName, UCHAR FAR * szColumnName,
SWORD cbColumnName) SWORD cbColumnName)
{ {
static char *func="SQLColumnPrivileges"; static char *func = "SQLColumnPrivileges";
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -2115,7 +2443,8 @@ static char *func="SQLColumnPrivileges"; ...@@ -2115,7 +2443,8 @@ static char *func="SQLColumnPrivileges";
/* SQLPrimaryKeys() /* SQLPrimaryKeys()
* Retrieve the primary key columns for the specified table. * Retrieve the primary key columns for the specified table.
*/ */
RETCODE SQL_API SQLPrimaryKeys( RETCODE SQL_API
SQLPrimaryKeys(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -2124,22 +2453,23 @@ RETCODE SQL_API SQLPrimaryKeys( ...@@ -2124,22 +2453,23 @@ RETCODE SQL_API SQLPrimaryKeys(
UCHAR FAR * szTableName, UCHAR FAR * szTableName,
SWORD cbTableName) SWORD cbTableName)
{ {
static char *func = "SQLPrimaryKeys"; static char *func = "SQLPrimaryKeys";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row; TupleNode *row;
RETCODE result; RETCODE result;
int seq = 0; int seq = 0;
HSTMT htbl_stmt; HSTMT htbl_stmt;
StatementClass *tbl_stmt; StatementClass *tbl_stmt;
char tables_query[STD_STATEMENT_LEN]; char tables_query[STD_STATEMENT_LEN];
char attname[MAX_INFO_STRING]; char attname[MAX_INFO_STRING];
SDWORD attname_len; SDWORD attname_len;
char pktab[MAX_TABLE_LEN + 1]; char pktab[MAX_TABLE_LEN + 1];
Int2 result_cols; Int2 result_cols;
mylog("%s: entering...stmt=%u\n", func, stmt); mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -2147,7 +2477,8 @@ Int2 result_cols; ...@@ -2147,7 +2477,8 @@ Int2 result_cols;
stmt->errormsg_created = TRUE; stmt->errormsg_created = TRUE;
stmt->result = QR_Constructor(); stmt->result = QR_Constructor();
if(!stmt->result) { if (!stmt->result)
{
stmt->errormsg = "Couldn't allocate memory for SQLPrimaryKeys result."; stmt->errormsg = "Couldn't allocate memory for SQLPrimaryKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2155,7 +2486,11 @@ Int2 result_cols; ...@@ -2155,7 +2486,11 @@ Int2 result_cols;
} }
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
/* a statement is actually executed, so we'll have to do this ourselves. */
/*
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
result_cols = 6; result_cols = 6;
extend_bindings(stmt, result_cols); extend_bindings(stmt, result_cols);
...@@ -2169,8 +2504,9 @@ Int2 result_cols; ...@@ -2169,8 +2504,9 @@ Int2 result_cols;
QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
result = SQLAllocStmt( stmt->hdbc, &htbl_stmt); result = SQLAllocStmt(stmt->hdbc, &htbl_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for Primary Key result."; stmt->errormsg = "Couldn't allocate statement for Primary Key result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2180,7 +2516,8 @@ Int2 result_cols; ...@@ -2180,7 +2516,8 @@ Int2 result_cols;
pktab[0] = '\0'; pktab[0] = '\0';
make_string(szTableName, cbTableName, pktab); make_string(szTableName, cbTableName, pktab);
if ( pktab[0] == '\0') { if (pktab[0] == '\0')
{
stmt->errormsg = "No Table specified to SQLPrimaryKeys."; stmt->errormsg = "No Table specified to SQLPrimaryKeys.";
stmt->errornumber = STMT_INTERNAL_ERROR; stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2191,9 +2528,10 @@ Int2 result_cols; ...@@ -2191,9 +2528,10 @@ Int2 result_cols;
#if 0 #if 0
sprintf(tables_query, "select distinct on (attnum) a2.attname, a2.attnum from pg_attribute a1, pg_attribute a2, pg_class c, pg_index i where c.relname = '%s_pkey' AND c.oid = i.indexrelid AND a1.attrelid = c.oid AND a2.attrelid = c.oid AND (i.indkey[0] = a1.attnum OR i.indkey[1] = a1.attnum OR i.indkey[2] = a1.attnum OR i.indkey[3] = a1.attnum OR i.indkey[4] = a1.attnum OR i.indkey[5] = a1.attnum OR i.indkey[6] = a1.attnum OR i.indkey[7] = a1.attnum) order by a2.attnum", pktab); sprintf(tables_query, "select distinct on (attnum) a2.attname, a2.attnum from pg_attribute a1, pg_attribute a2, pg_class c, pg_index i where c.relname = '%s_pkey' AND c.oid = i.indexrelid AND a1.attrelid = c.oid AND a2.attrelid = c.oid AND (i.indkey[0] = a1.attnum OR i.indkey[1] = a1.attnum OR i.indkey[2] = a1.attnum OR i.indkey[3] = a1.attnum OR i.indkey[4] = a1.attnum OR i.indkey[5] = a1.attnum OR i.indkey[6] = a1.attnum OR i.indkey[7] = a1.attnum) order by a2.attnum", pktab);
#else #else
/* Simplified query to remove assumptions about
* number of possible index columns. /*
* Courtesy of Tom Lane - thomas 2000-03-21 * Simplified query to remove assumptions about number of possible
* index columns. Courtesy of Tom Lane - thomas 2000-03-21
*/ */
sprintf(tables_query, "select ta.attname, ia.attnum" sprintf(tables_query, "select ta.attname, ia.attnum"
" from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i" " from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
...@@ -2209,7 +2547,8 @@ Int2 result_cols; ...@@ -2209,7 +2547,8 @@ Int2 result_cols;
mylog("SQLPrimaryKeys: tables_query='%s'\n", tables_query); mylog("SQLPrimaryKeys: tables_query='%s'\n", tables_query);
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2219,7 +2558,8 @@ Int2 result_cols; ...@@ -2219,7 +2558,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 1, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 1, SQL_C_CHAR,
attname, MAX_INFO_STRING, &attname_len); attname, MAX_INFO_STRING, &attname_len);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2229,16 +2569,18 @@ Int2 result_cols; ...@@ -2229,16 +2569,18 @@ Int2 result_cols;
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) { while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)); row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
/* I have to hide the table owner from Access, otherwise it /*
* insists on referring to the table as 'owner.table'. * I have to hide the table owner from Access, otherwise it
* (this is valid according to the ODBC SQL grammar, but * insists on referring to the table as 'owner.table'. (this is
* Postgres won't support it.) * valid according to the ODBC SQL grammar, but Postgres won't
* support it.)
*/ */
set_tuplefield_string(&row->tuple[1], ""); set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], pktab); set_tuplefield_string(&row->tuple[2], pktab);
...@@ -2253,7 +2595,8 @@ Int2 result_cols; ...@@ -2253,7 +2595,8 @@ Int2 result_cols;
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
} }
if(result != SQL_NO_DATA_FOUND) { if (result != SQL_NO_DATA_FOUND)
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2277,7 +2620,8 @@ Int2 result_cols; ...@@ -2277,7 +2620,8 @@ Int2 result_cols;
return SQL_SUCCESS; return SQL_SUCCESS;
} }
RETCODE SQL_API SQLForeignKeys( RETCODE SQL_API
SQLForeignKeys(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szPkTableQualifier, UCHAR FAR * szPkTableQualifier,
SWORD cbPkTableQualifier, SWORD cbPkTableQualifier,
...@@ -2292,33 +2636,47 @@ RETCODE SQL_API SQLForeignKeys( ...@@ -2292,33 +2636,47 @@ RETCODE SQL_API SQLForeignKeys(
UCHAR FAR * szFkTableName, UCHAR FAR * szFkTableName,
SWORD cbFkTableName) SWORD cbFkTableName)
{ {
static char *func = "SQLForeignKeys"; static char *func = "SQLForeignKeys";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row; TupleNode *row;
HSTMT htbl_stmt, hpkey_stmt; HSTMT htbl_stmt,
StatementClass *tbl_stmt; hpkey_stmt;
RETCODE result, keyresult; StatementClass *tbl_stmt;
char tables_query[STD_STATEMENT_LEN]; RETCODE result,
char trig_deferrable[2]; keyresult;
char trig_initdeferred[2]; char tables_query[STD_STATEMENT_LEN];
char trig_args[1024]; char trig_deferrable[2];
char upd_rule[MAX_TABLE_LEN], del_rule[MAX_TABLE_LEN]; char trig_initdeferred[2];
char pk_table_needed[MAX_TABLE_LEN + 1]; char trig_args[1024];
char fk_table_needed[MAX_TABLE_LEN + 1]; char upd_rule[MAX_TABLE_LEN],
char *pkey_ptr, *fkey_ptr, *pk_table, *fk_table; del_rule[MAX_TABLE_LEN];
int i, j, k, num_keys; char pk_table_needed[MAX_TABLE_LEN + 1];
SWORD trig_nargs, upd_rule_type=0, del_rule_type=0; char fk_table_needed[MAX_TABLE_LEN + 1];
char *pkey_ptr,
*fkey_ptr,
*pk_table,
*fk_table;
int i,
j,
k,
num_keys;
SWORD trig_nargs,
upd_rule_type = 0,
del_rule_type = 0;
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
SWORD defer_type; SWORD defer_type;
#endif #endif
char pkey[MAX_INFO_STRING]; char pkey[MAX_INFO_STRING];
Int2 result_cols; Int2 result_cols;
mylog("%s: entering...stmt=%u\n", func, stmt); mylog("%s: entering...stmt=%u\n", func, stmt);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -2327,7 +2685,8 @@ Int2 result_cols; ...@@ -2327,7 +2685,8 @@ Int2 result_cols;
stmt->errormsg_created = TRUE; stmt->errormsg_created = TRUE;
stmt->result = QR_Constructor(); stmt->result = QR_Constructor();
if(!stmt->result) { if (!stmt->result)
{
stmt->errormsg = "Couldn't allocate memory for SQLForeignKeys result."; stmt->errormsg = "Couldn't allocate memory for SQLForeignKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2335,7 +2694,11 @@ Int2 result_cols; ...@@ -2335,7 +2694,11 @@ Int2 result_cols;
} }
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
/* a statement is actually executed, so we'll have to do this ourselves. */
/*
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
result_cols = 14; result_cols = 14;
extend_bindings(stmt, result_cols); extend_bindings(stmt, result_cols);
...@@ -2369,8 +2732,9 @@ Int2 result_cols; ...@@ -2369,8 +2732,9 @@ Int2 result_cols;
stmt->current_col = -1; stmt->current_col = -1;
result = SQLAllocStmt( stmt->hdbc, &htbl_stmt); result = SQLAllocStmt(stmt->hdbc, &htbl_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLForeignKeys result."; stmt->errormsg = "Couldn't allocate statement for SQLForeignKeys result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2385,10 +2749,12 @@ Int2 result_cols; ...@@ -2385,10 +2749,12 @@ Int2 result_cols;
make_string(szPkTableName, cbPkTableName, pk_table_needed); make_string(szPkTableName, cbPkTableName, pk_table_needed);
make_string(szFkTableName, cbFkTableName, fk_table_needed); make_string(szFkTableName, cbFkTableName, fk_table_needed);
/* Case #2 -- Get the foreign keys in the specified table (fktab) that /*
refer to the primary keys of other table(s). * Case #2 -- Get the foreign keys in the specified table (fktab) that
* refer to the primary keys of other table(s).
*/ */
if (fk_table_needed[0] != '\0') { if (fk_table_needed[0] != '\0')
{
mylog("%s: entering Foreign Key Case #2", func); mylog("%s: entering Foreign Key Case #2", func);
sprintf(tables_query, "SELECT pt.tgargs, " sprintf(tables_query, "SELECT pt.tgargs, "
" pt.tgnargs, " " pt.tgnargs, "
...@@ -2421,7 +2787,8 @@ Int2 result_cols; ...@@ -2421,7 +2787,8 @@ Int2 result_cols;
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2431,7 +2798,8 @@ Int2 result_cols; ...@@ -2431,7 +2798,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY, result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY,
trig_args, sizeof(trig_args), NULL); trig_args, sizeof(trig_args), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2441,7 +2809,8 @@ Int2 result_cols; ...@@ -2441,7 +2809,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT, result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT,
&trig_nargs, 0, NULL); &trig_nargs, 0, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2451,7 +2820,8 @@ Int2 result_cols; ...@@ -2451,7 +2820,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
trig_deferrable, sizeof(trig_deferrable), NULL); trig_deferrable, sizeof(trig_deferrable), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2461,7 +2831,8 @@ Int2 result_cols; ...@@ -2461,7 +2831,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR,
trig_initdeferred, sizeof(trig_initdeferred), NULL); trig_initdeferred, sizeof(trig_initdeferred), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2471,7 +2842,8 @@ Int2 result_cols; ...@@ -2471,7 +2842,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 5, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 5, SQL_C_CHAR,
upd_rule, sizeof(upd_rule), NULL); upd_rule, sizeof(upd_rule), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2481,7 +2853,8 @@ Int2 result_cols; ...@@ -2481,7 +2853,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 6, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 6, SQL_C_CHAR,
del_rule, sizeof(del_rule), NULL); del_rule, sizeof(del_rule), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2493,7 +2866,8 @@ Int2 result_cols; ...@@ -2493,7 +2866,8 @@ Int2 result_cols;
if (result == SQL_NO_DATA_FOUND) if (result == SQL_NO_DATA_FOUND)
return SQL_SUCCESS; return SQL_SUCCESS;
if(result != SQL_SUCCESS) { if (result != SQL_SUCCESS)
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2501,8 +2875,9 @@ Int2 result_cols; ...@@ -2501,8 +2875,9 @@ Int2 result_cols;
return SQL_ERROR; return SQL_ERROR;
} }
keyresult = SQLAllocStmt( stmt->hdbc, &hpkey_stmt); keyresult = SQLAllocStmt(stmt->hdbc, &hpkey_stmt);
if((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO)) { if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO))
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLForeignKeys (pkeys) result."; stmt->errormsg = "Couldn't allocate statement for SQLForeignKeys (pkeys) result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2511,7 +2886,8 @@ Int2 result_cols; ...@@ -2511,7 +2886,8 @@ Int2 result_cols;
keyresult = SQLBindCol(hpkey_stmt, 4, SQL_C_CHAR, keyresult = SQLBindCol(hpkey_stmt, 4, SQL_C_CHAR,
pkey, sizeof(pkey), NULL); pkey, sizeof(pkey), NULL);
if (keyresult != SQL_SUCCESS) { if (keyresult != SQL_SUCCESS)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't bindcol for primary keys for SQLForeignKeys result."; stmt->errormsg = "Couldn't bindcol for primary keys for SQLForeignKeys result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2519,7 +2895,8 @@ Int2 result_cols; ...@@ -2519,7 +2895,8 @@ Int2 result_cols;
return SQL_ERROR; return SQL_ERROR;
} }
while (result == SQL_SUCCESS) { while (result == SQL_SUCCESS)
{
/* Compute the number of keyparts. */ /* Compute the number of keyparts. */
num_keys = (trig_nargs - 4) / 2; num_keys = (trig_nargs - 4) / 2;
...@@ -2533,17 +2910,20 @@ Int2 result_cols; ...@@ -2533,17 +2910,20 @@ Int2 result_cols;
pk_table += strlen(pk_table) + 1; pk_table += strlen(pk_table) + 1;
/* If there is a pk table specified, then check it. */ /* If there is a pk table specified, then check it. */
if (pk_table_needed[0] != '\0') { if (pk_table_needed[0] != '\0')
{
/* If it doesn't match, then continue */ /* If it doesn't match, then continue */
if ( strcmp(pk_table, pk_table_needed)) { if (strcmp(pk_table, pk_table_needed))
{
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
continue; continue;
} }
} }
keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pk_table, SQL_NTS); keyresult = SQLPrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pk_table, SQL_NTS);
if (keyresult != SQL_SUCCESS) { if (keyresult != SQL_SUCCESS)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result."; stmt->errormsg = "Couldn't get primary keys for SQLForeignKeys result.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2560,9 +2940,11 @@ Int2 result_cols; ...@@ -2560,9 +2940,11 @@ Int2 result_cols;
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
pkey_ptr += strlen(pkey_ptr) + 1; pkey_ptr += strlen(pkey_ptr) + 1;
for (k = 0; k < num_keys; k++) { for (k = 0; k < num_keys; k++)
{
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_ptr, pkey); mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_ptr, pkey);
if ( keyresult != SQL_SUCCESS || strcmp(pkey_ptr, pkey)) { if (keyresult != SQL_SUCCESS || strcmp(pkey_ptr, pkey))
{
num_keys = 0; num_keys = 0;
break; break;
} }
...@@ -2580,39 +2962,36 @@ Int2 result_cols; ...@@ -2580,39 +2962,36 @@ Int2 result_cols;
fkey_ptr += strlen(fkey_ptr) + 1; fkey_ptr += strlen(fkey_ptr) + 1;
/* Set update and delete actions for foreign keys */ /* Set update and delete actions for foreign keys */
if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) { if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
upd_rule_type = SQL_CASCADE; upd_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) { else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
upd_rule_type = SQL_NO_ACTION; upd_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) { else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
upd_rule_type = SQL_NO_ACTION; upd_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) { else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
upd_rule_type = SQL_SET_DEFAULT; upd_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) { else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
upd_rule_type = SQL_SET_NULL; upd_rule_type = SQL_SET_NULL;
}
if (!strcmp(upd_rule, "RI_FKey_cascade_del")) { if (!strcmp(upd_rule, "RI_FKey_cascade_del"))
del_rule_type = SQL_CASCADE; del_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) { else if (!strcmp(upd_rule, "RI_FKey_noaction_del"))
del_rule_type = SQL_NO_ACTION; del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) { else if (!strcmp(upd_rule, "RI_FKey_restrict_del"))
del_rule_type = SQL_NO_ACTION; del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) { else if (!strcmp(upd_rule, "RI_FKey_setdefault_del"))
del_rule_type = SQL_SET_DEFAULT; del_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) { else if (!strcmp(upd_rule, "RI_FKey_setnull_del"))
del_rule_type = SQL_SET_NULL; del_rule_type = SQL_SET_NULL;
}
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
/* Set deferrability type */ /* Set deferrability type */
if (!strcmp(trig_initdeferred, "y")) { if (!strcmp(trig_initdeferred, "y"))
defer_type = SQL_INITIALLY_DEFERRED; defer_type = SQL_INITIALLY_DEFERRED;
} else if (!strcmp(trig_deferrable, "y")) { else if (!strcmp(trig_deferrable, "y"))
defer_type = SQL_INITIALLY_IMMEDIATE; defer_type = SQL_INITIALLY_IMMEDIATE;
} else { else
defer_type = SQL_NOT_DEFERRABLE; defer_type = SQL_NOT_DEFERRABLE;
}
#endif /* ODBCVER >= 0x0300 */ #endif /* ODBCVER >= 0x0300 */
/* Get to first primary key */ /* Get to first primary key */
...@@ -2620,9 +2999,10 @@ Int2 result_cols; ...@@ -2620,9 +2999,10 @@ Int2 result_cols;
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
pkey_ptr += strlen(pkey_ptr) + 1; pkey_ptr += strlen(pkey_ptr) + 1;
for (k = 0; k < num_keys; k++) { for (k = 0; k < num_keys; k++)
{
row = (TupleNode *)malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)); row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr); mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
...@@ -2650,7 +3030,8 @@ Int2 result_cols; ...@@ -2650,7 +3030,8 @@ Int2 result_cols;
QR_add_tuple(stmt->result, row); QR_add_tuple(stmt->result, row);
/* next primary/foreign key */ /* next primary/foreign key */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++)
{
fkey_ptr += strlen(fkey_ptr) + 1; fkey_ptr += strlen(fkey_ptr) + 1;
pkey_ptr += strlen(pkey_ptr) + 1; pkey_ptr += strlen(pkey_ptr) + 1;
} }
...@@ -2661,10 +3042,13 @@ Int2 result_cols; ...@@ -2661,10 +3042,13 @@ Int2 result_cols;
SQLFreeStmt(hpkey_stmt, SQL_DROP); SQLFreeStmt(hpkey_stmt, SQL_DROP);
} }
/* Case #1 -- Get the foreign keys in other tables that refer to the primary key /*
in the specified table (pktab). i.e., Who points to me? * Case #1 -- Get the foreign keys in other tables that refer to the
* primary key in the specified table (pktab). i.e., Who points to
* me?
*/ */
else if (pk_table_needed[0] != '\0') { else if (pk_table_needed[0] != '\0')
{
sprintf(tables_query, "SELECT pg_trigger.tgargs, " sprintf(tables_query, "SELECT pg_trigger.tgargs, "
" pg_trigger.tgnargs, " " pg_trigger.tgnargs, "
...@@ -2697,7 +3081,8 @@ Int2 result_cols; ...@@ -2697,7 +3081,8 @@ Int2 result_cols;
pk_table_needed); pk_table_needed);
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query)); result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2707,7 +3092,8 @@ Int2 result_cols; ...@@ -2707,7 +3092,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY, result = SQLBindCol(htbl_stmt, 1, SQL_C_BINARY,
trig_args, sizeof(trig_args), NULL); trig_args, sizeof(trig_args), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2717,7 +3103,8 @@ Int2 result_cols; ...@@ -2717,7 +3103,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT, result = SQLBindCol(htbl_stmt, 2, SQL_C_SHORT,
&trig_nargs, 0, NULL); &trig_nargs, 0, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2727,7 +3114,8 @@ Int2 result_cols; ...@@ -2727,7 +3114,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
trig_deferrable, sizeof(trig_deferrable), NULL); trig_deferrable, sizeof(trig_deferrable), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2737,7 +3125,8 @@ Int2 result_cols; ...@@ -2737,7 +3125,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 4, SQL_C_CHAR,
trig_initdeferred, sizeof(trig_initdeferred), NULL); trig_initdeferred, sizeof(trig_initdeferred), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2747,7 +3136,8 @@ Int2 result_cols; ...@@ -2747,7 +3136,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 5, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 5, SQL_C_CHAR,
upd_rule, sizeof(upd_rule), NULL); upd_rule, sizeof(upd_rule), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2757,7 +3147,8 @@ Int2 result_cols; ...@@ -2757,7 +3147,8 @@ Int2 result_cols;
result = SQLBindCol(htbl_stmt, 6, SQL_C_CHAR, result = SQLBindCol(htbl_stmt, 6, SQL_C_CHAR,
del_rule, sizeof(del_rule), NULL); del_rule, sizeof(del_rule), NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = tbl_stmt->errormsg; stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2769,7 +3160,8 @@ Int2 result_cols; ...@@ -2769,7 +3160,8 @@ Int2 result_cols;
if (result == SQL_NO_DATA_FOUND) if (result == SQL_NO_DATA_FOUND)
return SQL_SUCCESS; return SQL_SUCCESS;
if(result != SQL_SUCCESS) { if (result != SQL_SUCCESS)
{
stmt->errormsg = SC_create_errormsg(htbl_stmt); stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber; stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2777,45 +3169,43 @@ Int2 result_cols; ...@@ -2777,45 +3169,43 @@ Int2 result_cols;
return SQL_ERROR; return SQL_ERROR;
} }
while (result == SQL_SUCCESS) { while (result == SQL_SUCCESS)
{
/* Calculate the number of key parts */ /* Calculate the number of key parts */
num_keys = (trig_nargs - 4) / 2;; num_keys = (trig_nargs - 4) / 2;;
/* Handle action (i.e., 'cascade', 'restrict', 'setnull') */ /* Handle action (i.e., 'cascade', 'restrict', 'setnull') */
if (!strcmp(upd_rule, "RI_FKey_cascade_upd")) { if (!strcmp(upd_rule, "RI_FKey_cascade_upd"))
upd_rule_type = SQL_CASCADE; upd_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_upd")) { else if (!strcmp(upd_rule, "RI_FKey_noaction_upd"))
upd_rule_type = SQL_NO_ACTION; upd_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_upd")) { else if (!strcmp(upd_rule, "RI_FKey_restrict_upd"))
upd_rule_type = SQL_NO_ACTION; upd_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd")) { else if (!strcmp(upd_rule, "RI_FKey_setdefault_upd"))
upd_rule_type = SQL_SET_DEFAULT; upd_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_upd")) { else if (!strcmp(upd_rule, "RI_FKey_setnull_upd"))
upd_rule_type = SQL_SET_NULL; upd_rule_type = SQL_SET_NULL;
}
if (!strcmp(upd_rule, "RI_FKey_cascade_del")) { if (!strcmp(upd_rule, "RI_FKey_cascade_del"))
del_rule_type = SQL_CASCADE; del_rule_type = SQL_CASCADE;
} else if (!strcmp(upd_rule, "RI_FKey_noaction_del")) { else if (!strcmp(upd_rule, "RI_FKey_noaction_del"))
del_rule_type = SQL_NO_ACTION; del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_restrict_del")) { else if (!strcmp(upd_rule, "RI_FKey_restrict_del"))
del_rule_type = SQL_NO_ACTION; del_rule_type = SQL_NO_ACTION;
} else if (!strcmp(upd_rule, "RI_FKey_setdefault_del")) { else if (!strcmp(upd_rule, "RI_FKey_setdefault_del"))
del_rule_type = SQL_SET_DEFAULT; del_rule_type = SQL_SET_DEFAULT;
} else if (!strcmp(upd_rule, "RI_FKey_setnull_del")) { else if (!strcmp(upd_rule, "RI_FKey_setnull_del"))
del_rule_type = SQL_SET_NULL; del_rule_type = SQL_SET_NULL;
}
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
/* Set deferrability type */ /* Set deferrability type */
if (!strcmp(trig_initdeferred, "y")) { if (!strcmp(trig_initdeferred, "y"))
defer_type = SQL_INITIALLY_DEFERRED; defer_type = SQL_INITIALLY_DEFERRED;
} else if (!strcmp(trig_deferrable, "y")) { else if (!strcmp(trig_deferrable, "y"))
defer_type = SQL_INITIALLY_IMMEDIATE; defer_type = SQL_INITIALLY_IMMEDIATE;
} else { else
defer_type = SQL_NOT_DEFERRABLE; defer_type = SQL_NOT_DEFERRABLE;
}
#endif /* ODBCVER >= 0x0300 */ #endif /* ODBCVER >= 0x0300 */
mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys); mylog("Foreign Key Case#1: trig_nargs = %d, num_keys = %d\n", trig_nargs, num_keys);
...@@ -2835,11 +3225,12 @@ Int2 result_cols; ...@@ -2835,11 +3225,12 @@ Int2 result_cols;
for (k = 0; k < 4; k++) for (k = 0; k < 4; k++)
fkey_ptr += strlen(fkey_ptr) + 1; fkey_ptr += strlen(fkey_ptr) + 1;
for (k = 0; k < num_keys; k++) { for (k = 0; k < num_keys; k++)
{
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr); 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)); row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_ptr); mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_ptr);
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
...@@ -2872,7 +3263,8 @@ Int2 result_cols; ...@@ -2872,7 +3263,8 @@ Int2 result_cols;
QR_add_tuple(stmt->result, row); QR_add_tuple(stmt->result, row);
/* next primary/foreign key */ /* next primary/foreign key */
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++)
{
pkey_ptr += strlen(pkey_ptr) + 1; pkey_ptr += strlen(pkey_ptr) + 1;
fkey_ptr += strlen(fkey_ptr) + 1; fkey_ptr += strlen(fkey_ptr) + 1;
} }
...@@ -2881,7 +3273,8 @@ Int2 result_cols; ...@@ -2881,7 +3273,8 @@ Int2 result_cols;
result = SQLFetch(htbl_stmt); result = SQLFetch(htbl_stmt);
} }
} }
else { else
{
stmt->errormsg = "No tables specified to SQLForeignKeys."; stmt->errormsg = "No tables specified to SQLForeignKeys.";
stmt->errornumber = STMT_INTERNAL_ERROR; stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -2897,7 +3290,8 @@ Int2 result_cols; ...@@ -2897,7 +3290,8 @@ Int2 result_cols;
RETCODE SQL_API SQLProcedureColumns( RETCODE SQL_API
SQLProcedureColumns(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szProcQualifier, UCHAR FAR * szProcQualifier,
SWORD cbProcQualifier, SWORD cbProcQualifier,
...@@ -2908,7 +3302,7 @@ RETCODE SQL_API SQLProcedureColumns( ...@@ -2908,7 +3302,7 @@ RETCODE SQL_API SQLProcedureColumns(
UCHAR FAR * szColumnName, UCHAR FAR * szColumnName,
SWORD cbColumnName) SWORD cbColumnName)
{ {
static char *func="SQLProcedureColumns"; static char *func = "SQLProcedureColumns";
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -2916,7 +3310,8 @@ static char *func="SQLProcedureColumns"; ...@@ -2916,7 +3310,8 @@ static char *func="SQLProcedureColumns";
return SQL_ERROR; return SQL_ERROR;
} }
RETCODE SQL_API SQLProcedures( RETCODE SQL_API
SQLProcedures(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szProcQualifier, UCHAR FAR * szProcQualifier,
SWORD cbProcQualifier, SWORD cbProcQualifier,
...@@ -2925,7 +3320,7 @@ RETCODE SQL_API SQLProcedures( ...@@ -2925,7 +3320,7 @@ RETCODE SQL_API SQLProcedures(
UCHAR FAR * szProcName, UCHAR FAR * szProcName,
SWORD cbProcName) SWORD cbProcName)
{ {
static char *func="SQLProcedures"; static char *func = "SQLProcedures";
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -2933,7 +3328,8 @@ static char *func="SQLProcedures"; ...@@ -2933,7 +3328,8 @@ static char *func="SQLProcedures";
return SQL_ERROR; return SQL_ERROR;
} }
RETCODE SQL_API SQLTablePrivileges( RETCODE SQL_API
SQLTablePrivileges(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -2942,7 +3338,7 @@ RETCODE SQL_API SQLTablePrivileges( ...@@ -2942,7 +3338,7 @@ RETCODE SQL_API SQLTablePrivileges(
UCHAR FAR * szTableName, UCHAR FAR * szTableName,
SWORD cbTableName) SWORD cbTableName)
{ {
static char *func="SQLTablePrivileges"; static char *func = "SQLTablePrivileges";
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
......
#ifndef _IODBC_H #ifndef _IODBC_H
#define _IODBC_H #define _IODBC_H
# if !defined(WIN32) && !defined(WIN32_SYSTEM) #if !defined(WIN32) && !defined(WIN32_SYSTEM)
# define _UNIX_ #define _UNIX_
# include <stdlib.h> #include <stdlib.h>
# include <sys/types.h> #include <sys/types.h>
# define MEM_ALLOC(size) (malloc((size_t)(size))) #define MEM_ALLOC(size) (malloc((size_t)(size)))
# define MEM_FREE(ptr) {if(ptr) free(ptr);} #define MEM_FREE(ptr) {if(ptr) free(ptr);}
# define STRCPY(t, s) (strcpy((char*)(t), (char*)(s))) #define STRCPY(t, s) (strcpy((char*)(t), (char*)(s)))
# define STRNCPY(t,s,n) (strncpy((char*)(t), (char*)(s), (size_t)(n))) #define STRNCPY(t,s,n) (strncpy((char*)(t), (char*)(s), (size_t)(n)))
# define STRCAT(t, s) (strcat((char*)(t), (char*)(s))) #define STRCAT(t, s) (strcat((char*)(t), (char*)(s)))
# define STRNCAT(t,s,n) (strncat((char*)(t), (char*)(s), (size_t)(n))) #define STRNCAT(t,s,n) (strncat((char*)(t), (char*)(s), (size_t)(n)))
# define STREQ(a, b) (strcmp((char*)(a), (char*)(b)) == 0) #define STREQ(a, b) (strcmp((char*)(a), (char*)(b)) == 0)
# define STRLEN(str) ((str)? strlen((char*)(str)):0) #define STRLEN(str) ((str)? strlen((char*)(str)):0)
# define EXPORT #define EXPORT
# define CALLBACK #define CALLBACK
# define FAR #define FAR
typedef signed short SSHOR; typedef signed short SSHOR;
typedef short WORD; typedef short WORD;
typedef long DWORD; typedef long DWORD;
typedef WORD WPARAM; typedef WORD WPARAM;
typedef DWORD LPARAM; typedef DWORD LPARAM;
typedef void* HWND; typedef void *HWND;
typedef int BOOL; typedef int BOOL;
# endif /* _UNIX_ */ #endif /* _UNIX_ */
# if defined(WIN32) || defined(WIN32_SYSTEM) #if defined(WIN32) || defined(WIN32_SYSTEM)
# include <windows.h> #include <windows.h>
# include <windowsx.h> #include <windowsx.h>
# ifdef _MSVC_ #ifdef _MSVC_
# define MEM_ALLOC(size) (fmalloc((size_t)(size))) #define MEM_ALLOC(size) (fmalloc((size_t)(size)))
# define MEM_FREE(ptr) ((ptr)? ffree((PTR)(ptr)):0)) #define MEM_FREE(ptr) ((ptr)? ffree((PTR)(ptr)):0))
# define STRCPY(t, s) (fstrcpy((char FAR*)(t), (char FAR*)(s))) #define STRCPY(t, s) (fstrcpy((char FAR*)(t), (char FAR*)(s)))
# define STRNCPY(t,s,n) (fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n))) #define STRNCPY(t,s,n) (fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n)))
# define STRLEN(str) ((str)? fstrlen((char FAR*)(str)):0) #define STRLEN(str) ((str)? fstrlen((char FAR*)(str)):0)
# define STREQ(a, b) (fstrcmp((char FAR*)(a), (char FAR*)(b) == 0) #define STREQ(a, b) (fstrcmp((char FAR*)(a), (char FAR*)(b) == 0)
# endif #endif
# ifdef _BORLAND_ #ifdef _BORLAND_
# define MEM_ALLOC(size) (farmalloc((unsigned long)(size)) #define MEM_ALLOC(size) (farmalloc((unsigned long)(size))
# define MEM_FREE(ptr) ((ptr)? farfree((void far*)(ptr)):0) #define MEM_FREE(ptr) ((ptr)? farfree((void far*)(ptr)):0)
# define STRCPY(t, s) (_fstrcpy((char FAR*)(t), (char FAR*)(s))) #define STRCPY(t, s) (_fstrcpy((char FAR*)(t), (char FAR*)(s)))
# define STRNCPY(t,s,n) (_fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n))) #define STRNCPY(t,s,n) (_fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n)))
# define STRLEN(str) ((str)? _fstrlen((char FAR*)(str)):0) #define STRLEN(str) ((str)? _fstrlen((char FAR*)(str)):0)
# define STREQ(a, b) (_fstrcmp((char FAR*)(a), (char FAR*)(b) == 0) #define STREQ(a, b) (_fstrcmp((char FAR*)(a), (char FAR*)(b) == 0)
# endif #endif
# endif /* WIN32 */ #endif /* WIN32 */
# define SYSERR (-1) #define SYSERR (-1)
# ifndef NULL #ifndef NULL
# define NULL ((void FAR*)0UL) #define NULL ((void FAR*)0UL)
# endif #endif
#endif #endif
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* include path to be used to create ODBC compliant applications. * include path to be used to create ODBC compliant applications.
*/ */
#ifndef _INTRINSIC_SQL_H #ifndef _INTRINSIC_SQL_H
# define _INTRINSIC_SQL_H #define _INTRINSIC_SQL_H
typedef unsigned char UCHAR; typedef unsigned char UCHAR;
typedef long int SDWORD; typedef long int SDWORD;
...@@ -10,86 +10,86 @@ typedef short int SWORD; ...@@ -10,86 +10,86 @@ typedef short int SWORD;
typedef unsigned long int UDWORD; typedef unsigned long int UDWORD;
typedef unsigned short int UWORD; typedef unsigned short int UWORD;
typedef void FAR* PTR; typedef void FAR *PTR;
typedef void FAR* HENV; typedef void FAR *HENV;
typedef void FAR* HDBC; typedef void FAR *HDBC;
typedef void FAR* HSTMT; typedef void FAR *HSTMT;
typedef signed short RETCODE; typedef signed short RETCODE;
# ifdef WIN32 #ifdef WIN32
# define SQL_API __stdcall #define SQL_API __stdcall
# else #else
# define SQL_API EXPORT CALLBACK #define SQL_API EXPORT CALLBACK
# endif #endif
# define ODBCVER 0x0250 #define ODBCVER 0x0250
# define SQL_MAX_MESSAGE_LENGTH 512 #define SQL_MAX_MESSAGE_LENGTH 512
# define SQL_MAX_DSN_LENGTH 32 #define SQL_MAX_DSN_LENGTH 32
/* return code */ /* return code */
# define SQL_INVALID_HANDLE (-2) #define SQL_INVALID_HANDLE (-2)
# define SQL_ERROR (-1) #define SQL_ERROR (-1)
# define SQL_SUCCESS 0 #define SQL_SUCCESS 0
# define SQL_SUCCESS_WITH_INFO 1 #define SQL_SUCCESS_WITH_INFO 1
# define SQL_NO_DATA_FOUND 100 #define SQL_NO_DATA_FOUND 100
/* standard SQL datatypes (agree with ANSI type numbering) */ /* standard SQL datatypes (agree with ANSI type numbering) */
# define SQL_CHAR 1 #define SQL_CHAR 1
# define SQL_NUMERIC 2 #define SQL_NUMERIC 2
# define SQL_DECIMAL 3 #define SQL_DECIMAL 3
# define SQL_INTEGER 4 #define SQL_INTEGER 4
# define SQL_SMALLINT 5 #define SQL_SMALLINT 5
# define SQL_FLOAT 6 #define SQL_FLOAT 6
# define SQL_REAL 7 #define SQL_REAL 7
# define SQL_DOUBLE 8 #define SQL_DOUBLE 8
# define SQL_VARCHAR 12 #define SQL_VARCHAR 12
# define SQL_TYPE_MIN SQL_CHAR #define SQL_TYPE_MIN SQL_CHAR
# define SQL_TYPE_NULL 0 #define SQL_TYPE_NULL 0
# define SQL_TYPE_MAX SQL_VARCHAR #define SQL_TYPE_MAX SQL_VARCHAR
/* C to SQL datatype mapping */ /* C to SQL datatype mapping */
# define SQL_C_CHAR SQL_CHAR #define SQL_C_CHAR SQL_CHAR
# define SQL_C_LONG SQL_INTEGER #define SQL_C_LONG SQL_INTEGER
# define SQL_C_SHORT SQL_SMALLINT #define SQL_C_SHORT SQL_SMALLINT
# define SQL_C_FLOAT SQL_REAL #define SQL_C_FLOAT SQL_REAL
# define SQL_C_DOUBLE SQL_DOUBLE #define SQL_C_DOUBLE SQL_DOUBLE
# define SQL_C_DEFAULT 99 #define SQL_C_DEFAULT 99
# define SQL_NO_NULLS 0 #define SQL_NO_NULLS 0
# define SQL_NULLABLE 1 #define SQL_NULLABLE 1
# define SQL_NULLABLE_UNKNOWN 2 #define SQL_NULLABLE_UNKNOWN 2
/* some special length values */ /* some special length values */
# define SQL_NULL_DATA (-1) #define SQL_NULL_DATA (-1)
# define SQL_DATA_AT_EXEC (-2) #define SQL_DATA_AT_EXEC (-2)
# define SQL_NTS (-3) #define SQL_NTS (-3)
/* SQLFreeStmt flag values */ /* SQLFreeStmt flag values */
# define SQL_CLOSE 0 #define SQL_CLOSE 0
# define SQL_DROP 1 #define SQL_DROP 1
# define SQL_UNBIND 2 #define SQL_UNBIND 2
# define SQL_RESET_PARAMS 3 #define SQL_RESET_PARAMS 3
/* SQLTransact flag values */ /* SQLTransact flag values */
# define SQL_COMMIT 0 #define SQL_COMMIT 0
# define SQL_ROLLBACK 1 #define SQL_ROLLBACK 1
/* SQLColAttributes flag values */ /* SQLColAttributes flag values */
# define SQL_COLUMN_COUNT 0 #define SQL_COLUMN_COUNT 0
# define SQL_COLUMN_LABEL 18 #define SQL_COLUMN_LABEL 18
# define SQL_COLATT_OPT_MAX SQL_COLUMN_LABEL #define SQL_COLATT_OPT_MAX SQL_COLUMN_LABEL
# define SQL_COLUMN_DRIVER_START 1000 #define SQL_COLUMN_DRIVER_START 1000
# define SQL_COLATT_OPT_MIN SQL_COLUMN_COUNT #define SQL_COLATT_OPT_MIN SQL_COLUMN_COUNT
/* Null handles */ /* Null handles */
# define SQL_NULL_HENV 0 #define SQL_NULL_HENV 0
# define SQL_NULL_HDBC 0 #define SQL_NULL_HDBC 0
# define SQL_NULL_HSTMT 0 #define SQL_NULL_HSTMT 0
/* All code below has been added to the original isql.h coming from iodbc */ /* All code below has been added to the original isql.h coming from iodbc */
typedef unsigned char BYTE; typedef unsigned char BYTE;
...@@ -133,21 +133,21 @@ extern "C" ...@@ -133,21 +133,21 @@ extern "C"
{ {
#endif #endif
RETCODE SQL_API SQLAllocConnect (HENV henv, RETCODE SQL_API SQLAllocConnect(HENV henv,
HDBC FAR * phdbc); HDBC FAR * phdbc);
RETCODE SQL_API SQLAllocEnv (HENV FAR * phenv); RETCODE SQL_API SQLAllocEnv(HENV FAR * phenv);
RETCODE SQL_API SQLAllocStmt (HDBC hdbc, RETCODE SQL_API SQLAllocStmt(HDBC hdbc,
HSTMT FAR * phstmt); HSTMT FAR * phstmt);
RETCODE SQL_API SQLBindCol (HSTMT hstmt, RETCODE SQL_API SQLBindCol(HSTMT hstmt,
UWORD icol, UWORD icol,
SWORD fCType, SWORD fCType,
PTR rgbValue, PTR rgbValue,
SDWORD cbValueMax, SDWORD cbValueMax,
SDWORD FAR * pcbValue); SDWORD FAR * pcbValue);
RETCODE SQL_API SQLCancel (HSTMT hstmt); RETCODE SQL_API SQLCancel(HSTMT hstmt);
RETCODE SQL_API SQLColAttributes (HSTMT hstmt, RETCODE SQL_API SQLColAttributes(HSTMT hstmt,
UWORD icol, UWORD icol,
UWORD fDescType, UWORD fDescType,
PTR rgbDesc, PTR rgbDesc,
...@@ -155,7 +155,7 @@ RETCODE SQL_API SQLColAttributes (HSTMT hstmt, ...@@ -155,7 +155,7 @@ RETCODE SQL_API SQLColAttributes (HSTMT hstmt,
SWORD FAR * pcbDesc, SWORD FAR * pcbDesc,
SDWORD FAR * pfDesc); SDWORD FAR * pfDesc);
RETCODE SQL_API SQLConnect (HDBC hdbc, RETCODE SQL_API SQLConnect(HDBC hdbc,
UCHAR FAR * szDSN, UCHAR FAR * szDSN,
SWORD cbDSN, SWORD cbDSN,
UCHAR FAR * szUID, UCHAR FAR * szUID,
...@@ -163,7 +163,7 @@ RETCODE SQL_API SQLConnect (HDBC hdbc, ...@@ -163,7 +163,7 @@ RETCODE SQL_API SQLConnect (HDBC hdbc,
UCHAR FAR * szAuthStr, UCHAR FAR * szAuthStr,
SWORD cbAuthStr); SWORD cbAuthStr);
RETCODE SQL_API SQLDescribeCol (HSTMT hstmt, RETCODE SQL_API SQLDescribeCol(HSTMT hstmt,
UWORD icol, UWORD icol,
UCHAR FAR * szColName, UCHAR FAR * szColName,
SWORD cbColNameMax, SWORD cbColNameMax,
...@@ -173,9 +173,9 @@ RETCODE SQL_API SQLDescribeCol (HSTMT hstmt, ...@@ -173,9 +173,9 @@ RETCODE SQL_API SQLDescribeCol (HSTMT hstmt,
SWORD FAR * pibScale, SWORD FAR * pibScale,
SWORD FAR * pfNullable); SWORD FAR * pfNullable);
RETCODE SQL_API SQLDisconnect (HDBC hdbc); RETCODE SQL_API SQLDisconnect(HDBC hdbc);
RETCODE SQL_API SQLError (HENV henv, RETCODE SQL_API SQLError(HENV henv,
HDBC hdbc, HDBC hdbc,
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR * szSqlState, UCHAR FAR * szSqlState,
...@@ -184,45 +184,45 @@ RETCODE SQL_API SQLError (HENV henv, ...@@ -184,45 +184,45 @@ RETCODE SQL_API SQLError (HENV henv,
SWORD cbErrorMsgMax, SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg); SWORD FAR * pcbErrorMsg);
RETCODE SQL_API SQLExecDirect (HSTMT hstmt, RETCODE SQL_API SQLExecDirect(HSTMT hstmt,
UCHAR FAR * szSqlStr, UCHAR FAR * szSqlStr,
SDWORD cbSqlStr); SDWORD cbSqlStr);
RETCODE SQL_API SQLExecute (HSTMT hstmt); RETCODE SQL_API SQLExecute(HSTMT hstmt);
RETCODE SQL_API SQLFetch (HSTMT hstmt); RETCODE SQL_API SQLFetch(HSTMT hstmt);
RETCODE SQL_API SQLFreeConnect (HDBC hdbc); RETCODE SQL_API SQLFreeConnect(HDBC hdbc);
RETCODE SQL_API SQLFreeEnv (HENV henv); RETCODE SQL_API SQLFreeEnv(HENV henv);
RETCODE SQL_API SQLFreeStmt (HSTMT hstmt, RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
UWORD fOption); UWORD fOption);
RETCODE SQL_API SQLGetCursorName (HSTMT hstmt, RETCODE SQL_API SQLGetCursorName(HSTMT hstmt,
UCHAR FAR * szCursor, UCHAR FAR * szCursor,
SWORD cbCursorMax, SWORD cbCursorMax,
SWORD FAR * pcbCursor); SWORD FAR * pcbCursor);
RETCODE SQL_API SQLNumResultCols (HSTMT hstmt, RETCODE SQL_API SQLNumResultCols(HSTMT hstmt,
SWORD FAR * pccol); SWORD FAR * pccol);
RETCODE SQL_API SQLPrepare (HSTMT hstmt, RETCODE SQL_API SQLPrepare(HSTMT hstmt,
UCHAR FAR * szSqlStr, UCHAR FAR * szSqlStr,
SDWORD cbSqlStr); SDWORD cbSqlStr);
RETCODE SQL_API SQLRowCount (HSTMT hstmt, RETCODE SQL_API SQLRowCount(HSTMT hstmt,
SDWORD FAR * pcrow); SDWORD FAR * pcrow);
RETCODE SQL_API SQLSetCursorName (HSTMT hstmt, RETCODE SQL_API SQLSetCursorName(HSTMT hstmt,
UCHAR FAR * szCursor, UCHAR FAR * szCursor,
SWORD cbCursor); SWORD cbCursor);
RETCODE SQL_API SQLTransact (HENV henv, RETCODE SQL_API SQLTransact(HENV henv,
HDBC hdbc, HDBC hdbc,
UWORD fType); UWORD fType);
RETCODE SQL_API SQLSetParam (HSTMT hstmt, RETCODE SQL_API SQLSetParam(HSTMT hstmt,
UWORD ipar, UWORD ipar,
SWORD fCType, SWORD fCType,
SWORD fSqlType, SWORD fSqlType,
...@@ -233,5 +233,6 @@ RETCODE SQL_API SQLSetParam (HSTMT hstmt, ...@@ -233,5 +233,6 @@ RETCODE SQL_API SQLSetParam (HSTMT hstmt,
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif
...@@ -3,212 +3,212 @@ ...@@ -3,212 +3,212 @@
* to be a drop in replacement for isqlext.h from iodbc. * to be a drop in replacement for isqlext.h from iodbc.
*/ */
#ifndef _INTRINSIC_SQLEXT_H #ifndef _INTRINSIC_SQLEXT_H
# define _INTRINSIC_SQLEXT_H #define _INTRINSIC_SQLEXT_H
# include "isql.h" #include "isql.h"
# define SQL_STILL_EXECUTING 2 #define SQL_STILL_EXECUTING 2
# define SQL_NEED_DATA 99 #define SQL_NEED_DATA 99
/* extend SQL datatypes */ /* extend SQL datatypes */
# define SQL_DATE 9 #define SQL_DATE 9
# define SQL_TIME 10 #define SQL_TIME 10
# define SQL_TIMESTAMP 11 #define SQL_TIMESTAMP 11
# define SQL_LONGVARCHAR (-1) #define SQL_LONGVARCHAR (-1)
# define SQL_BINARY (-2) #define SQL_BINARY (-2)
# define SQL_VARBINARY (-3) #define SQL_VARBINARY (-3)
# define SQL_LONGVARBINARY (-4) #define SQL_LONGVARBINARY (-4)
# define SQL_BIGINT (-5) #define SQL_BIGINT (-5)
# define SQL_TINYINT (-6) #define SQL_TINYINT (-6)
# define SQL_BIT (-7) /* conflict with SQL3 ??? */ #define SQL_BIT (-7) /* conflict with SQL3 ??? */
# define SQL_TYPE_DRIVER_START (-80) #define SQL_TYPE_DRIVER_START (-80)
/* C to SQL datatype mapping */ /* C to SQL datatype mapping */
# define SQL_C_DATE SQL_DATE #define SQL_C_DATE SQL_DATE
# define SQL_C_TIME SQL_TIME #define SQL_C_TIME SQL_TIME
# define SQL_C_TIMESTAMP SQL_TIMESTAMP #define SQL_C_TIMESTAMP SQL_TIMESTAMP
# define SQL_C_BINARY SQL_BINARY #define SQL_C_BINARY SQL_BINARY
# define SQL_C_BIT SQL_BIT #define SQL_C_BIT SQL_BIT
# define SQL_C_TINYINT SQL_TINYINT #define SQL_C_TINYINT SQL_TINYINT
# define SQL_SIGNED_OFFSET (-20) #define SQL_SIGNED_OFFSET (-20)
# define SQL_UNSIGNED_OFFSET (-22) #define SQL_UNSIGNED_OFFSET (-22)
# define SQL_C_SLONG (SQL_C_LONG + SQL_SIGNED_OFFSET) #define SQL_C_SLONG (SQL_C_LONG + SQL_SIGNED_OFFSET)
# define SQL_C_SSHORT (SQL_C_SHORT + SQL_SIGNED_OFFSET) #define SQL_C_SSHORT (SQL_C_SHORT + SQL_SIGNED_OFFSET)
# define SQL_C_STINYINT (SQL_TINYINT + SQL_SIGNED_OFFSET) #define SQL_C_STINYINT (SQL_TINYINT + SQL_SIGNED_OFFSET)
# define SQL_C_ULONG (SQL_C_LONG + SQL_UNSIGNED_OFFSET) #define SQL_C_ULONG (SQL_C_LONG + SQL_UNSIGNED_OFFSET)
# define SQL_C_USHORT (SQL_C_SHORT + SQL_UNSIGNED_OFFSET) #define SQL_C_USHORT (SQL_C_SHORT + SQL_UNSIGNED_OFFSET)
# define SQL_C_UTINYINT (SQL_TINYINT + SQL_UNSIGNED_OFFSET) #define SQL_C_UTINYINT (SQL_TINYINT + SQL_UNSIGNED_OFFSET)
# define SQL_C_BOOKMARK SQL_C_ULONG #define SQL_C_BOOKMARK SQL_C_ULONG
# if defined(SQL_TYPE_MIN) #if defined(SQL_TYPE_MIN)
# undef SQL_TYPE_MIN #undef SQL_TYPE_MIN
# define SQL_TYPE_MIN SQL_BIT #define SQL_TYPE_MIN SQL_BIT
/* Note:If SQL_BIT uses SQL3 value (i.e. 14) then, /* Note:If SQL_BIT uses SQL3 value (i.e. 14) then,
* SQL_TYPE_MIN need to be defined as SQL_TINYINT * SQL_TYPE_MIN need to be defined as SQL_TINYINT
* (i.e. -6). * (i.e. -6).
*/ */
# endif #endif
# define SQL_ALL_TYPES 0 #define SQL_ALL_TYPES 0
/* SQLDriverConnect flag values */ /* SQLDriverConnect flag values */
# define SQL_DRIVER_NOPROMPT 0 #define SQL_DRIVER_NOPROMPT 0
# define SQL_DRIVER_COMPLETE 1 #define SQL_DRIVER_COMPLETE 1
# define SQL_DRIVER_PROMPT 2 #define SQL_DRIVER_PROMPT 2
# define SQL_DRIVER_COMPLETE_REQUIRED 3 #define SQL_DRIVER_COMPLETE_REQUIRED 3
/* SQLSetParam extensions */ /* SQLSetParam extensions */
# define SQL_DEFAULT_PARAM (-5) #define SQL_DEFAULT_PARAM (-5)
# define SQL_IGNORE (-6) #define SQL_IGNORE (-6)
/* function number for SQLGetFunctions and _iodbcdm_getproc */ /* function number for SQLGetFunctions and _iodbcdm_getproc */
# define SQL_API_SQLALLOCCONNECT 1 #define SQL_API_SQLALLOCCONNECT 1
# define SQL_API_SQLALLOCENV 2 #define SQL_API_SQLALLOCENV 2
# define SQL_API_SQLALLOCSTMT 3 #define SQL_API_SQLALLOCSTMT 3
# define SQL_API_SQLBINDCOL 4 #define SQL_API_SQLBINDCOL 4
# define SQL_API_SQLCANCEL 5 #define SQL_API_SQLCANCEL 5
# define SQL_API_SQLCOLATTRIBUTES 6 #define SQL_API_SQLCOLATTRIBUTES 6
# define SQL_API_SQLCONNECT 7 #define SQL_API_SQLCONNECT 7
# define SQL_API_SQLDESCRIBECOL 8 #define SQL_API_SQLDESCRIBECOL 8
# define SQL_API_SQLDISCONNECT 9 #define SQL_API_SQLDISCONNECT 9
# define SQL_API_SQLERROR 10 #define SQL_API_SQLERROR 10
# define SQL_API_SQLEXECDIRECT 11 #define SQL_API_SQLEXECDIRECT 11
# define SQL_API_SQLEXECUTE 12 #define SQL_API_SQLEXECUTE 12
# define SQL_API_SQLFETCH 13 #define SQL_API_SQLFETCH 13
# define SQL_API_SQLFREECONNECT 14 #define SQL_API_SQLFREECONNECT 14
# define SQL_API_SQLFREEENV 15 #define SQL_API_SQLFREEENV 15
# define SQL_API_SQLFREESTMT 16 #define SQL_API_SQLFREESTMT 16
# define SQL_API_SQLGETCURSORNAME 17 #define SQL_API_SQLGETCURSORNAME 17
# define SQL_API_SQLNUMRESULTCOLS 18 #define SQL_API_SQLNUMRESULTCOLS 18
# define SQL_API_SQLPREPARE 19 #define SQL_API_SQLPREPARE 19
# define SQL_API_SQLROWCOUNT 20 #define SQL_API_SQLROWCOUNT 20
# define SQL_API_SQLSETCURSORNAME 21 #define SQL_API_SQLSETCURSORNAME 21
# define SQL_API_SQLSETPARAM 22 #define SQL_API_SQLSETPARAM 22
# define SQL_API_SQLTRANSACT 23 #define SQL_API_SQLTRANSACT 23
# define SQL_NUM_FUNCTIONS 23 #define SQL_NUM_FUNCTIONS 23
# define SQL_EXT_API_START 40 #define SQL_EXT_API_START 40
# define SQL_API_SQLCOLUMNS 40 #define SQL_API_SQLCOLUMNS 40
# define SQL_API_SQLDRIVERCONNECT 41 #define SQL_API_SQLDRIVERCONNECT 41
# define SQL_API_SQLGETCONNECTOPTION 42 #define SQL_API_SQLGETCONNECTOPTION 42
# define SQL_API_SQLGETDATA 43 #define SQL_API_SQLGETDATA 43
# define SQL_API_SQLGETFUNCTIONS 44 #define SQL_API_SQLGETFUNCTIONS 44
# define SQL_API_SQLGETINFO 45 #define SQL_API_SQLGETINFO 45
# define SQL_API_SQLGETSTMTOPTION 46 #define SQL_API_SQLGETSTMTOPTION 46
# define SQL_API_SQLGETTYPEINFO 47 #define SQL_API_SQLGETTYPEINFO 47
# define SQL_API_SQLPARAMDATA 48 #define SQL_API_SQLPARAMDATA 48
# define SQL_API_SQLPUTDATA 49 #define SQL_API_SQLPUTDATA 49
# define SQL_API_SQLSETCONNECTOPTION 50 #define SQL_API_SQLSETCONNECTOPTION 50
# define SQL_API_SQLSETSTMTOPTION 51 #define SQL_API_SQLSETSTMTOPTION 51
# define SQL_API_SQLSPECIALCOLUMNS 52 #define SQL_API_SQLSPECIALCOLUMNS 52
# define SQL_API_SQLSTATISTICS 53 #define SQL_API_SQLSTATISTICS 53
# define SQL_API_SQLTABLES 54 #define SQL_API_SQLTABLES 54
# define SQL_API_SQLBROWSECONNECT 55 #define SQL_API_SQLBROWSECONNECT 55
# define SQL_API_SQLCOLUMNPRIVILEGES 56 #define SQL_API_SQLCOLUMNPRIVILEGES 56
# define SQL_API_SQLDATASOURCES 57 #define SQL_API_SQLDATASOURCES 57
# define SQL_API_SQLDESCRIBEPARAM 58 #define SQL_API_SQLDESCRIBEPARAM 58
# define SQL_API_SQLEXTENDEDFETCH 59 #define SQL_API_SQLEXTENDEDFETCH 59
# define SQL_API_SQLFOREIGNKEYS 60 #define SQL_API_SQLFOREIGNKEYS 60
# define SQL_API_SQLMORERESULTS 61 #define SQL_API_SQLMORERESULTS 61
# define SQL_API_SQLNATIVESQL 62 #define SQL_API_SQLNATIVESQL 62
# define SQL_API_SQLNUMPARAMS 63 #define SQL_API_SQLNUMPARAMS 63
# define SQL_API_SQLPARAMOPTIONS 64 #define SQL_API_SQLPARAMOPTIONS 64
# define SQL_API_SQLPRIMARYKEYS 65 #define SQL_API_SQLPRIMARYKEYS 65
# define SQL_API_SQLPROCEDURECOLUMNS 66 #define SQL_API_SQLPROCEDURECOLUMNS 66
# define SQL_API_SQLPROCEDURES 67 #define SQL_API_SQLPROCEDURES 67
# define SQL_API_SQLSETPOS 68 #define SQL_API_SQLSETPOS 68
# define SQL_API_SQLSETSCROLLOPTIONS 69 #define SQL_API_SQLSETSCROLLOPTIONS 69
# define SQL_API_SQLTABLEPRIVILEGES 70 #define SQL_API_SQLTABLEPRIVILEGES 70
# define SQL_API_SQLDRIVERS 71 #define SQL_API_SQLDRIVERS 71
# define SQL_API_SQLBINDPARAMETER 72 #define SQL_API_SQLBINDPARAMETER 72
# define SQL_EXT_API_LAST SQL_API_SQLBINDPARAMETER #define SQL_EXT_API_LAST SQL_API_SQLBINDPARAMETER
#define SQL_NUM_EXTENSIONS (SQL_EXT_API_LAST - SQL_EXT_API_START + 1) #define SQL_NUM_EXTENSIONS (SQL_EXT_API_LAST - SQL_EXT_API_START + 1)
# define SQL_API_ALL_FUNCTIONS 0 #define SQL_API_ALL_FUNCTIONS 0
/* SQLGetInfo infor number */ /* SQLGetInfo infor number */
# define SQL_INFO_FIRST 0 #define SQL_INFO_FIRST 0
# define SQL_DRIVER_HDBC 3 #define SQL_DRIVER_HDBC 3
# define SQL_DRIVER_HENV 4 #define SQL_DRIVER_HENV 4
# define SQL_DRIVER_HSTMT 5 #define SQL_DRIVER_HSTMT 5
# define SQL_DRIVER_NAME 6 #define SQL_DRIVER_NAME 6
# define SQL_ODBC_VER 10 #define SQL_ODBC_VER 10
# define SQL_CURSOR_COMMIT_BEHAVIOR 23 #define SQL_CURSOR_COMMIT_BEHAVIOR 23
# define SQL_CURSOR_ROLLBACK_BEHAVIOR 24 #define SQL_CURSOR_ROLLBACK_BEHAVIOR 24
# define SQL_DEFAULT_TXN_ISOLATION 26 #define SQL_DEFAULT_TXN_ISOLATION 26
# define SQL_TXN_ISOLATION_OPTION 72 #define SQL_TXN_ISOLATION_OPTION 72
# define SQL_NON_NULLABLE_COLUMNS 75 #define SQL_NON_NULLABLE_COLUMNS 75
# define SQL_DRIVER_HLIB 76 #define SQL_DRIVER_HLIB 76
# define SQL_DRIVER_ODBC_VER 77 #define SQL_DRIVER_ODBC_VER 77
# define SQL_QUALIFIER_LOCATION 114 #define SQL_QUALIFIER_LOCATION 114
# define SQL_INFO_LAST SQL_QUALIFIER_LOCATION #define SQL_INFO_LAST SQL_QUALIFIER_LOCATION
# define SQL_INFO_DRIVER_START 1000 #define SQL_INFO_DRIVER_START 1000
/* SQL_TXN_ISOLATION_OPTION masks */ /* SQL_TXN_ISOLATION_OPTION masks */
# define SQL_TXN_READ_UNCOMMITTED 0x00000001L #define SQL_TXN_READ_UNCOMMITTED 0x00000001L
# define SQL_TXN_READ_COMMITTED 0x00000002L #define SQL_TXN_READ_COMMITTED 0x00000002L
# define SQL_TXN_REPEATABLE_READ 0x00000004L #define SQL_TXN_REPEATABLE_READ 0x00000004L
# define SQL_TXN_SERIALIZABLE 0x00000008L #define SQL_TXN_SERIALIZABLE 0x00000008L
# define SQL_TXN_VERSIONING 0x00000010L #define SQL_TXN_VERSIONING 0x00000010L
/* SQL_CURSOR_COMMIT_BEHAVIOR and SQL_CURSOR_ROLLBACK_BEHAVIOR values */ /* SQL_CURSOR_COMMIT_BEHAVIOR and SQL_CURSOR_ROLLBACK_BEHAVIOR values */
# define SQL_CB_DELETE 0x0000 #define SQL_CB_DELETE 0x0000
# define SQL_CB_CLOSE 0x0001 #define SQL_CB_CLOSE 0x0001
# define SQL_CB_PRESERVE 0x0002 #define SQL_CB_PRESERVE 0x0002
/* options for SQLGetStmtOption/SQLSetStmtOption */ /* options for SQLGetStmtOption/SQLSetStmtOption */
# define SQL_QUERY_TIMEOUT 0 #define SQL_QUERY_TIMEOUT 0
# define SQL_MAX_ROWS 1 #define SQL_MAX_ROWS 1
# define SQL_NOSCAN 2 #define SQL_NOSCAN 2
# define SQL_MAX_LENGTH 3 #define SQL_MAX_LENGTH 3
# define SQL_ASYNC_ENABLE 4 #define SQL_ASYNC_ENABLE 4
# define SQL_BIND_TYPE 5 #define SQL_BIND_TYPE 5
# define SQL_CURSOR_TYPE 6 #define SQL_CURSOR_TYPE 6
# define SQL_CONCURRENCY 7 #define SQL_CONCURRENCY 7
# define SQL_KEYSET_SIZE 8 #define SQL_KEYSET_SIZE 8
# define SQL_ROWSET_SIZE 9 #define SQL_ROWSET_SIZE 9
# define SQL_SIMULATE_CURSOR 10 #define SQL_SIMULATE_CURSOR 10
# define SQL_RETRIEVE_DATA 11 #define SQL_RETRIEVE_DATA 11
# define SQL_USE_BOOKMARKS 12 #define SQL_USE_BOOKMARKS 12
# define SQL_GET_BOOKMARK 13 /* GetStmtOption Only */ #define SQL_GET_BOOKMARK 13 /* GetStmtOption Only */
# define SQL_ROW_NUMBER 14 /* GetStmtOption Only */ #define SQL_ROW_NUMBER 14 /* GetStmtOption Only */
# define SQL_STMT_OPT_MAX SQL_ROW_NUMBER #define SQL_STMT_OPT_MAX SQL_ROW_NUMBER
# define SQL_STMT_OPT_MIN SQL_QUERY_TIMEOUT #define SQL_STMT_OPT_MIN SQL_QUERY_TIMEOUT
/* /*
* ODBC 3.0 renames the above to SQL_ATTR_ values. At this time I don't * ODBC 3.0 renames the above to SQL_ATTR_ values. At this time I don't
* know if they have also been renumbered or not, I will assume not. * know if they have also been renumbered or not, I will assume not.
*/ */
# define SQL_ATTR_QUERY_TIMEOUT 0 #define SQL_ATTR_QUERY_TIMEOUT 0
# define SQL_ATTR_MAX_ROWS 1 #define SQL_ATTR_MAX_ROWS 1
# define SQL_ATTR_NOSCAN 2 #define SQL_ATTR_NOSCAN 2
# define SQL_ATTR_MAX_LENGTH 3 #define SQL_ATTR_MAX_LENGTH 3
# define SQL_ATTR_ASYNC_ENABLE 4 #define SQL_ATTR_ASYNC_ENABLE 4
# define SQL_ATTR_BIND_TYPE 5 #define SQL_ATTR_BIND_TYPE 5
# define SQL_ATTR_CURSOR_TYPE 6 #define SQL_ATTR_CURSOR_TYPE 6
# define SQL_ATTR_CONCURRENCY 7 #define SQL_ATTR_CONCURRENCY 7
# define SQL_ATTR_KEYSET_SIZE 8 #define SQL_ATTR_KEYSET_SIZE 8
# define SQL_ATTR_ROWSET_SIZE 9 #define SQL_ATTR_ROWSET_SIZE 9
# define SQL_ATTR_SIMULATE_CURSOR 10 #define SQL_ATTR_SIMULATE_CURSOR 10
# define SQL_ATTR_RETRIEVE_DATA 11 #define SQL_ATTR_RETRIEVE_DATA 11
# define SQL_ATTR_USE_BOOKMARKS 12 #define SQL_ATTR_USE_BOOKMARKS 12
# define SQL_ATTR_GET_BOOKMARK 13 /* GetStmtOption Only */ #define SQL_ATTR_GET_BOOKMARK 13 /* GetStmtOption Only */
# define SQL_ATTR_ROW_NUMBER 14 /* GetStmtOption Only */ #define SQL_ATTR_ROW_NUMBER 14 /* GetStmtOption Only */
/* New in ODBC 3.0 */ /* New in ODBC 3.0 */
#define SQL_ATTR_APP_PARAM_DESC 15 #define SQL_ATTR_APP_PARAM_DESC 15
...@@ -236,80 +236,80 @@ ...@@ -236,80 +236,80 @@
#define SQL_STMT_ATTR_MAX SQL_ATTR_ROWS_FETCHED_PTR #define SQL_STMT_ATTR_MAX SQL_ATTR_ROWS_FETCHED_PTR
/* SQL_QUERY_TIMEOUT options */ /* SQL_QUERY_TIMEOUT options */
# define SQL_QUERY_TIMEOUT_DEFAULT 0UL #define SQL_QUERY_TIMEOUT_DEFAULT 0UL
/* SQL_MAX_ROWS options */ /* SQL_MAX_ROWS options */
# define SQL_MAX_ROWS_DEFAULT 0UL #define SQL_MAX_ROWS_DEFAULT 0UL
/* SQL_MAX_LENGTH options */ /* SQL_MAX_LENGTH options */
# define SQL_MAX_LENGTH_DEFAULT 0UL #define SQL_MAX_LENGTH_DEFAULT 0UL
/* SQL_CONCURRENCY options */ /* SQL_CONCURRENCY options */
# define SQL_CONCUR_READ_ONLY 1 #define SQL_CONCUR_READ_ONLY 1
# define SQL_CONCUR_LOCK 2 #define SQL_CONCUR_LOCK 2
# define SQL_CONCUR_ROWVER 3 #define SQL_CONCUR_ROWVER 3
# define SQL_CONCUR_VALUES 4 #define SQL_CONCUR_VALUES 4
/* options for SQLSetConnectOption/SQLGetConnectOption */ /* options for SQLSetConnectOption/SQLGetConnectOption */
# define SQL_ACCESS_MODE 101 #define SQL_ACCESS_MODE 101
# define SQL_AUTOCOMMIT 102 #define SQL_AUTOCOMMIT 102
# define SQL_LOGIN_TIMEOUT 103 #define SQL_LOGIN_TIMEOUT 103
# define SQL_OPT_TRACE 104 #define SQL_OPT_TRACE 104
# define SQL_OPT_TRACEFILE 105 #define SQL_OPT_TRACEFILE 105
# define SQL_TRANSLATE_DLL 106 #define SQL_TRANSLATE_DLL 106
# define SQL_TRANSLATE_OPTION 107 #define SQL_TRANSLATE_OPTION 107
# define SQL_TXN_ISOLATION 108 #define SQL_TXN_ISOLATION 108
# define SQL_CURRENT_QUALIFIER 109 #define SQL_CURRENT_QUALIFIER 109
# define SQL_ODBC_CURSORS 110 #define SQL_ODBC_CURSORS 110
# define SQL_QUIET_MODE 111 #define SQL_QUIET_MODE 111
# define SQL_PACKET_SIZE 112 #define SQL_PACKET_SIZE 112
# define SQL_CONN_OPT_MAX SQL_PACKET_SIZE #define SQL_CONN_OPT_MAX SQL_PACKET_SIZE
# define SQL_CONNECT_OPT_DRVR_START 1000 #define SQL_CONNECT_OPT_DRVR_START 1000
# define SQL_CONN_OPT_MIN SQL_ACCESS_MODE #define SQL_CONN_OPT_MIN SQL_ACCESS_MODE
/* SQL_ACCESS_MODE options */ /* SQL_ACCESS_MODE options */
# define SQL_MODE_READ_WRITE 0UL #define SQL_MODE_READ_WRITE 0UL
# define SQL_MODE_READ_ONLY 1UL #define SQL_MODE_READ_ONLY 1UL
# define SQL_MODE_DEFAULT SQL_MODE_READ_WRITE #define SQL_MODE_DEFAULT SQL_MODE_READ_WRITE
/* SQL_AUTOCOMMIT options */ /* SQL_AUTOCOMMIT options */
# define SQL_AUTOCOMMIT_OFF 0UL #define SQL_AUTOCOMMIT_OFF 0UL
# define SQL_AUTOCOMMIT_ON 1UL #define SQL_AUTOCOMMIT_ON 1UL
# define SQL_AUTOCOMMIT_DEFAULT SQL_AUTOCOMMIT_ON #define SQL_AUTOCOMMIT_DEFAULT SQL_AUTOCOMMIT_ON
/* SQL_LOGIN_TIMEOUT options */ /* SQL_LOGIN_TIMEOUT options */
# define SQL_LOGIN_TIMEOUT_DEFAULT 15UL #define SQL_LOGIN_TIMEOUT_DEFAULT 15UL
/* SQL_OPT_TRACE options */ /* SQL_OPT_TRACE options */
# define SQL_OPT_TRACE_OFF 0UL #define SQL_OPT_TRACE_OFF 0UL
# define SQL_OPT_TRACE_ON 1UL #define SQL_OPT_TRACE_ON 1UL
# define SQL_OPT_TRACE_DEFAULT SQL_OPT_TRACE_OFF #define SQL_OPT_TRACE_DEFAULT SQL_OPT_TRACE_OFF
# define SQL_OPT_TRACE_FILE_DEFAULT "odbc.log" #define SQL_OPT_TRACE_FILE_DEFAULT "odbc.log"
/* SQL_ODBC_CURSORS options */ /* SQL_ODBC_CURSORS options */
# define SQL_CUR_USE_IF_NEEDED 0UL #define SQL_CUR_USE_IF_NEEDED 0UL
# define SQL_CUR_USE_ODBC 1UL #define SQL_CUR_USE_ODBC 1UL
# define SQL_CUR_USE_DRIVER 2UL #define SQL_CUR_USE_DRIVER 2UL
# define SQL_CUR_DEFAULT SQL_CUR_USE_DRIVER #define SQL_CUR_DEFAULT SQL_CUR_USE_DRIVER
/* Column types and scopes in SQLSpecialColumns. */ /* Column types and scopes in SQLSpecialColumns. */
# define SQL_BEST_ROWID 1 #define SQL_BEST_ROWID 1
# define SQL_ROWVER 2 #define SQL_ROWVER 2
# define SQL_SCOPE_CURROW 0 #define SQL_SCOPE_CURROW 0
# define SQL_SCOPE_TRANSACTION 1 #define SQL_SCOPE_TRANSACTION 1
# define SQL_SCOPE_SESSION 2 #define SQL_SCOPE_SESSION 2
/* SQLExtendedFetch flag values */ /* SQLExtendedFetch flag values */
# define SQL_FETCH_NEXT 1 #define SQL_FETCH_NEXT 1
# define SQL_FETCH_FIRST 2 #define SQL_FETCH_FIRST 2
# define SQL_FETCH_LAST 3 #define SQL_FETCH_LAST 3
# define SQL_FETCH_PRIOR 4 #define SQL_FETCH_PRIOR 4
# define SQL_FETCH_ABSOLUTE 5 #define SQL_FETCH_ABSOLUTE 5
# define SQL_FETCH_RELATIVE 6 #define SQL_FETCH_RELATIVE 6
# define SQL_FETCH_BOOKMARK 8 #define SQL_FETCH_BOOKMARK 8
/* Defines for SQLBindParameter/SQLProcedureColumns */ /* Defines for SQLBindParameter/SQLProcedureColumns */
#define SQL_PARAM_TYPE_UNKNOWN 0 #define SQL_PARAM_TYPE_UNKNOWN 0
...@@ -320,21 +320,21 @@ ...@@ -320,21 +320,21 @@
#define SQL_RETURN_VALUE 5 #define SQL_RETURN_VALUE 5
/* Defines used by Driver Manager for mapping SQLSetParam to SQLBindParameter */ /* Defines used by Driver Manager for mapping SQLSetParam to SQLBindParameter */
# define SQL_PARAM_TYPE_DEFAULT SQL_PARAM_INPUT_OUTPUT #define SQL_PARAM_TYPE_DEFAULT SQL_PARAM_INPUT_OUTPUT
# define SQL_SETPARAM_VALUE_MAX (-1L) #define SQL_SETPARAM_VALUE_MAX (-1L)
/* SQLStatistics flag values */ /* SQLStatistics flag values */
# define SQL_INDEX_UNIQUE 0 #define SQL_INDEX_UNIQUE 0
# define SQL_INDEX_ALL 1 #define SQL_INDEX_ALL 1
# define SQL_QUICK 0 #define SQL_QUICK 0
# define SQL_ENSURE 1 #define SQL_ENSURE 1
/* SQLSetScrollOption flag values */ /* SQLSetScrollOption flag values */
# define SQL_SCROLL_FORWARD_ONLY 0L #define SQL_SCROLL_FORWARD_ONLY 0L
# define SQL_SCROLL_KEYSET_DRIVEN (-1L) #define SQL_SCROLL_KEYSET_DRIVEN (-1L)
# define SQL_SCROLL_DYNAMIC (-2L) #define SQL_SCROLL_DYNAMIC (-2L)
# define SQL_SCROLL_STATIC (-3L) #define SQL_SCROLL_STATIC (-3L)
/* Everything below has been added to the original isqlext.h that comes /* Everything below has been added to the original isqlext.h that comes
* with iodbc. * with iodbc.
...@@ -362,33 +362,39 @@ typedef long long int ODBCINT64; ...@@ -362,33 +362,39 @@ typedef long long int ODBCINT64;
typedef unsigned ODBCINT64 SQLUBIGINT; typedef unsigned ODBCINT64 SQLUBIGINT;
typedef ODBCINT64 SQLBIGINT; typedef ODBCINT64 SQLBIGINT;
#else /* Used even on platforms with 64 bit ints but not GCC */ #else /* Used even on platforms with 64 bit ints
* but not GCC */
typedef struct { typedef struct
{
SQLUINTEGER dwLowWord; SQLUINTEGER dwLowWord;
SQLUINTEGER dwHighWord; SQLUINTEGER dwHighWord;
} SQLUBIGINT; } SQLUBIGINT;
typedef struct { typedef struct
{
SQLUINTEGER dwLowWord; SQLUINTEGER dwLowWord;
SQLINTEGER dwHighWord; SQLINTEGER dwHighWord;
} SQLBIGINT; } SQLBIGINT;
#endif /* GCC */ #endif /* GCC */
typedef struct tagDATE_STRUCT { typedef struct tagDATE_STRUCT
{
SQLSMALLINT year; SQLSMALLINT year;
SQLUSMALLINT month; SQLUSMALLINT month;
SQLUSMALLINT day; SQLUSMALLINT day;
} DATE_STRUCT,SQL_DATE_STRUCT; } DATE_STRUCT, SQL_DATE_STRUCT;
typedef struct tagTIME_STRUCT { typedef struct tagTIME_STRUCT
{
SQLUSMALLINT hour; SQLUSMALLINT hour;
SQLUSMALLINT minute; SQLUSMALLINT minute;
SQLUSMALLINT second; SQLUSMALLINT second;
} TIME_STRUCT,SQL_TIME_STRUCT; } TIME_STRUCT, SQL_TIME_STRUCT;
typedef struct tagTIMESTAMP_STRUCT { typedef struct tagTIMESTAMP_STRUCT
{
SQLSMALLINT year; SQLSMALLINT year;
SQLUSMALLINT month; SQLUSMALLINT month;
SQLUSMALLINT day; SQLUSMALLINT day;
...@@ -396,7 +402,7 @@ typedef struct tagTIMESTAMP_STRUCT { ...@@ -396,7 +402,7 @@ typedef struct tagTIMESTAMP_STRUCT {
SQLUSMALLINT minute; SQLUSMALLINT minute;
SQLUSMALLINT second; SQLUSMALLINT second;
SQLUINTEGER fraction; SQLUINTEGER fraction;
} TIMESTAMP_STRUCT,SQL_TIMESTAMP_STRUCT; } TIMESTAMP_STRUCT, SQL_TIMESTAMP_STRUCT;
/* postodbc doesn't use these but what the heck */ /* postodbc doesn't use these but what the heck */
/* Don't know what SQL_MAX_NUMERIC_LEN should be so I can't include this. It's /* Don't know what SQL_MAX_NUMERIC_LEN should be so I can't include this. It's
...@@ -411,14 +417,16 @@ typedef struct tagSQL_NUMERIC_STRUCT { ...@@ -411,14 +417,16 @@ typedef struct tagSQL_NUMERIC_STRUCT {
*/ */
typedef struct tagSQLGUID { typedef struct tagSQLGUID
{
DWORD Data1; DWORD Data1;
WORD Data2; WORD Data2;
WORD Data3; WORD Data3;
BYTE Data4[8]; BYTE Data4[8];
} SQLGUID; } SQLGUID;
typedef enum { typedef enum
{
SQL_IS_YEAR = 1, SQL_IS_YEAR = 1,
SQL_IS_MONTH = 2, SQL_IS_MONTH = 2,
SQL_IS_DAY = 3, SQL_IS_DAY = 3,
...@@ -434,12 +442,14 @@ typedef enum { ...@@ -434,12 +442,14 @@ typedef enum {
SQL_IS_MINUTE_TO_SECOND = 13 SQL_IS_MINUTE_TO_SECOND = 13
} SQLINTERVAL; } SQLINTERVAL;
typedef struct tagSQL_YEAR_MONTH { typedef struct tagSQL_YEAR_MONTH
{
SQLUINTEGER year; SQLUINTEGER year;
SQLUINTEGER month; SQLUINTEGER month;
} SQL_YEAR_MONTH_STRUCT; } SQL_YEAR_MONTH_STRUCT;
typedef struct tagSQL_DAY_SECOND { typedef struct tagSQL_DAY_SECOND
{
SQLUINTEGER day; SQLUINTEGER day;
SQLUINTEGER hour; SQLUINTEGER hour;
SQLUINTEGER minute; SQLUINTEGER minute;
...@@ -447,10 +457,12 @@ typedef struct tagSQL_DAY_SECOND { ...@@ -447,10 +457,12 @@ typedef struct tagSQL_DAY_SECOND {
SQLUINTEGER fraction; SQLUINTEGER fraction;
} SQL_DAY_SECOND_STRUCT; } SQL_DAY_SECOND_STRUCT;
typedef struct tagSQL_INTERVAL_STRUCT { typedef struct tagSQL_INTERVAL_STRUCT
{
SQLINTERVAL interval_type; SQLINTERVAL interval_type;
SQLSMALLINT interval_sign; SQLSMALLINT interval_sign;
union { union
{
SQL_YEAR_MONTH_STRUCT year_month; SQL_YEAR_MONTH_STRUCT year_month;
SQL_DAY_SECOND_STRUCT day_second; SQL_DAY_SECOND_STRUCT day_second;
} intval; } intval;
...@@ -1317,17 +1329,18 @@ typedef struct tagSQL_INTERVAL_STRUCT { ...@@ -1317,17 +1329,18 @@ typedef struct tagSQL_INTERVAL_STRUCT {
"UNION,UNIQUE,UNKNOWN,UPDATE,UPPER,USAGE,USER,USING,"\ "UNION,UNIQUE,UNKNOWN,UPDATE,UPPER,USAGE,USER,USING,"\
"VALUE,,VARCHAR,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,YEAR" "VALUE,,VARCHAR,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,YEAR"
# ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
# endif {
#endif
RETCODE SQL_API SQLSetConnectOption (HDBC, UWORD, UDWORD); RETCODE SQL_API SQLSetConnectOption(HDBC, UWORD, UDWORD);
RETCODE SQL_API SQLNumResultCols ( HSTMT, SWORD FAR* ); RETCODE SQL_API SQLNumResultCols(HSTMT, SWORD FAR *);
/* /*
* function prototypes previously missing from isqlext.h * function prototypes previously missing from isqlext.h
*/ */
RETCODE SQL_API SQLColumns (HSTMT hstmt, RETCODE SQL_API SQLColumns(HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
...@@ -1337,7 +1350,7 @@ RETCODE SQL_API SQLColumns (HSTMT hstmt, ...@@ -1337,7 +1350,7 @@ RETCODE SQL_API SQLColumns (HSTMT hstmt,
UCHAR FAR * szColumnName, UCHAR FAR * szColumnName,
SWORD cbColumnName); SWORD cbColumnName);
RETCODE SQL_API SQLDriverConnect (HDBC hdbc, RETCODE SQL_API SQLDriverConnect(HDBC hdbc,
HWND hwnd, HWND hwnd,
UCHAR FAR * szConnStrIn, UCHAR FAR * szConnStrIn,
SWORD cbConnStrIn, SWORD cbConnStrIn,
...@@ -1346,46 +1359,46 @@ RETCODE SQL_API SQLDriverConnect (HDBC hdbc, ...@@ -1346,46 +1359,46 @@ RETCODE SQL_API SQLDriverConnect (HDBC hdbc,
SWORD FAR * pcbConnStrOut, SWORD FAR * pcbConnStrOut,
UWORD fDriverCompletion); UWORD fDriverCompletion);
RETCODE SQL_API SQLGetConnectOption (HDBC hdbc, RETCODE SQL_API SQLGetConnectOption(HDBC hdbc,
UWORD fOption, UWORD fOption,
PTR pvParam); PTR pvParam);
RETCODE SQL_API SQLGetData (HSTMT hstmt, RETCODE SQL_API SQLGetData(HSTMT hstmt,
UWORD icol, UWORD icol,
SWORD fCType, SWORD fCType,
PTR rgbValue, PTR rgbValue,
SDWORD cbValueMax, SDWORD cbValueMax,
SDWORD FAR * pcbValue); SDWORD FAR * pcbValue);
RETCODE SQL_API SQLGetFunctions (HDBC hdbc, RETCODE SQL_API SQLGetFunctions(HDBC hdbc,
UWORD fFunction, UWORD fFunction,
UWORD FAR * pfExists); UWORD FAR * pfExists);
RETCODE SQL_API SQLGetInfo (HDBC hdbc, RETCODE SQL_API SQLGetInfo(HDBC hdbc,
UWORD fInfoType, UWORD fInfoType,
PTR rgbInfoValue, PTR rgbInfoValue,
SWORD cbInfoValueMax, SWORD cbInfoValueMax,
SWORD FAR * pcbInfoValue); SWORD FAR * pcbInfoValue);
RETCODE SQL_API SQLGetStmtOption (HSTMT hstmt, RETCODE SQL_API SQLGetStmtOption(HSTMT hstmt,
UWORD fOption, UWORD fOption,
PTR pvParam); PTR pvParam);
RETCODE SQL_API SQLGetTypeInfo (HSTMT hstmt, RETCODE SQL_API SQLGetTypeInfo(HSTMT hstmt,
SWORD fSqlType); SWORD fSqlType);
RETCODE SQL_API SQLParamData (HSTMT hstmt, RETCODE SQL_API SQLParamData(HSTMT hstmt,
PTR FAR * prgbValue); PTR FAR * prgbValue);
RETCODE SQL_API SQLPutData (HSTMT hstmt, RETCODE SQL_API SQLPutData(HSTMT hstmt,
PTR rgbValue, PTR rgbValue,
SDWORD cbValue); SDWORD cbValue);
RETCODE SQL_API SQLSetStmtOption (HSTMT hstmt, RETCODE SQL_API SQLSetStmtOption(HSTMT hstmt,
UWORD fOption, UWORD fOption,
UDWORD vParam); UDWORD vParam);
RETCODE SQL_API SQLSpecialColumns (HSTMT hstmt, RETCODE SQL_API SQLSpecialColumns(HSTMT hstmt,
UWORD fColType, UWORD fColType,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
...@@ -1396,7 +1409,7 @@ RETCODE SQL_API SQLSpecialColumns (HSTMT hstmt, ...@@ -1396,7 +1409,7 @@ RETCODE SQL_API SQLSpecialColumns (HSTMT hstmt,
UWORD fScope, UWORD fScope,
UWORD fNullable); UWORD fNullable);
RETCODE SQL_API SQLStatistics (HSTMT hstmt, RETCODE SQL_API SQLStatistics(HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
...@@ -1406,7 +1419,7 @@ RETCODE SQL_API SQLStatistics (HSTMT hstmt, ...@@ -1406,7 +1419,7 @@ RETCODE SQL_API SQLStatistics (HSTMT hstmt,
UWORD fUnique, UWORD fUnique,
UWORD fAccuracy); UWORD fAccuracy);
RETCODE SQL_API SQLTables (HSTMT hstmt, RETCODE SQL_API SQLTables(HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
...@@ -1416,14 +1429,14 @@ RETCODE SQL_API SQLTables (HSTMT hstmt, ...@@ -1416,14 +1429,14 @@ RETCODE SQL_API SQLTables (HSTMT hstmt,
UCHAR FAR * szTableType, UCHAR FAR * szTableType,
SWORD cbTableType); SWORD cbTableType);
RETCODE SQL_API SQLBrowseConnect (HDBC hdbc, RETCODE SQL_API SQLBrowseConnect(HDBC hdbc,
UCHAR FAR * szConnStrIn, UCHAR FAR * szConnStrIn,
SWORD cbConnStrIn, SWORD cbConnStrIn,
UCHAR FAR * szConnStrOut, UCHAR FAR * szConnStrOut,
SWORD cbConnStrOutMax, SWORD cbConnStrOutMax,
SWORD FAR * pcbConnStrOut); SWORD FAR * pcbConnStrOut);
RETCODE SQL_API SQLColumnPrivileges (HSTMT hstmt, RETCODE SQL_API SQLColumnPrivileges(HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
...@@ -1433,20 +1446,20 @@ RETCODE SQL_API SQLColumnPrivileges (HSTMT hstmt, ...@@ -1433,20 +1446,20 @@ RETCODE SQL_API SQLColumnPrivileges (HSTMT hstmt,
UCHAR FAR * szColumnName, UCHAR FAR * szColumnName,
SWORD cbColumnName); SWORD cbColumnName);
RETCODE SQL_API SQLDescribeParam (HSTMT hstmt, RETCODE SQL_API SQLDescribeParam(HSTMT hstmt,
UWORD ipar, UWORD ipar,
SWORD FAR * pfSqlType, SWORD FAR * pfSqlType,
UDWORD FAR * pcbColDef, UDWORD FAR * pcbColDef,
SWORD FAR * pibScale, SWORD FAR * pibScale,
SWORD FAR * pfNullable); SWORD FAR * pfNullable);
RETCODE SQL_API SQLExtendedFetch (HSTMT hstmt, RETCODE SQL_API SQLExtendedFetch(HSTMT hstmt,
UWORD fFetchType, UWORD fFetchType,
SDWORD irow, SDWORD irow,
UDWORD FAR * pcrow, UDWORD FAR * pcrow,
UWORD FAR * rgfRowStatus); UWORD FAR * rgfRowStatus);
RETCODE SQL_API SQLForeignKeys (HSTMT hstmt, RETCODE SQL_API SQLForeignKeys(HSTMT hstmt,
UCHAR FAR * szPkTableQualifier, UCHAR FAR * szPkTableQualifier,
SWORD cbPkTableQualifier, SWORD cbPkTableQualifier,
UCHAR FAR * szPkTableOwner, UCHAR FAR * szPkTableOwner,
...@@ -1460,23 +1473,23 @@ RETCODE SQL_API SQLForeignKeys (HSTMT hstmt, ...@@ -1460,23 +1473,23 @@ RETCODE SQL_API SQLForeignKeys (HSTMT hstmt,
UCHAR FAR * szFkTableName, UCHAR FAR * szFkTableName,
SWORD cbFkTableName); SWORD cbFkTableName);
RETCODE SQL_API SQLMoreResults (HSTMT hstmt); RETCODE SQL_API SQLMoreResults(HSTMT hstmt);
RETCODE SQL_API SQLNativeSql (HDBC hdbc, RETCODE SQL_API SQLNativeSql(HDBC hdbc,
UCHAR FAR * szSqlStrIn, UCHAR FAR * szSqlStrIn,
SDWORD cbSqlStrIn, SDWORD cbSqlStrIn,
UCHAR FAR * szSqlStr, UCHAR FAR * szSqlStr,
SDWORD cbSqlStrMax, SDWORD cbSqlStrMax,
SDWORD FAR * pcbSqlStr); SDWORD FAR * pcbSqlStr);
RETCODE SQL_API SQLNumParams (HSTMT hstmt, RETCODE SQL_API SQLNumParams(HSTMT hstmt,
SWORD FAR * pcpar); SWORD FAR * pcpar);
RETCODE SQL_API SQLParamOptions (HSTMT hstmt, RETCODE SQL_API SQLParamOptions(HSTMT hstmt,
UDWORD crow, UDWORD crow,
UDWORD FAR * pirow); UDWORD FAR * pirow);
RETCODE SQL_API SQLPrimaryKeys (HSTMT hstmt, RETCODE SQL_API SQLPrimaryKeys(HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
...@@ -1484,7 +1497,7 @@ RETCODE SQL_API SQLPrimaryKeys (HSTMT hstmt, ...@@ -1484,7 +1497,7 @@ RETCODE SQL_API SQLPrimaryKeys (HSTMT hstmt,
UCHAR FAR * szTableName, UCHAR FAR * szTableName,
SWORD cbTableName); SWORD cbTableName);
RETCODE SQL_API SQLProcedureColumns (HSTMT hstmt, RETCODE SQL_API SQLProcedureColumns(HSTMT hstmt,
UCHAR FAR * szProcQualifier, UCHAR FAR * szProcQualifier,
SWORD cbProcQualifier, SWORD cbProcQualifier,
UCHAR FAR * szProcOwner, UCHAR FAR * szProcOwner,
...@@ -1494,7 +1507,7 @@ RETCODE SQL_API SQLProcedureColumns (HSTMT hstmt, ...@@ -1494,7 +1507,7 @@ RETCODE SQL_API SQLProcedureColumns (HSTMT hstmt,
UCHAR FAR * szColumnName, UCHAR FAR * szColumnName,
SWORD cbColumnName); SWORD cbColumnName);
RETCODE SQL_API SQLProcedures (HSTMT hstmt, RETCODE SQL_API SQLProcedures(HSTMT hstmt,
UCHAR FAR * szProcQualifier, UCHAR FAR * szProcQualifier,
SWORD cbProcQualifier, SWORD cbProcQualifier,
UCHAR FAR * szProcOwner, UCHAR FAR * szProcOwner,
...@@ -1502,12 +1515,12 @@ RETCODE SQL_API SQLProcedures (HSTMT hstmt, ...@@ -1502,12 +1515,12 @@ RETCODE SQL_API SQLProcedures (HSTMT hstmt,
UCHAR FAR * szProcName, UCHAR FAR * szProcName,
SWORD cbProcName); SWORD cbProcName);
RETCODE SQL_API SQLSetPos (HSTMT hstmt, RETCODE SQL_API SQLSetPos(HSTMT hstmt,
UWORD irow, UWORD irow,
UWORD fOption, UWORD fOption,
UWORD fLock); UWORD fLock);
RETCODE SQL_API SQLTablePrivileges (HSTMT hstmt, RETCODE SQL_API SQLTablePrivileges(HSTMT hstmt,
UCHAR FAR * szTableQualifier, UCHAR FAR * szTableQualifier,
SWORD cbTableQualifier, SWORD cbTableQualifier,
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
...@@ -1515,7 +1528,7 @@ RETCODE SQL_API SQLTablePrivileges (HSTMT hstmt, ...@@ -1515,7 +1528,7 @@ RETCODE SQL_API SQLTablePrivileges (HSTMT hstmt,
UCHAR FAR * szTableName, UCHAR FAR * szTableName,
SWORD cbTableName); SWORD cbTableName);
RETCODE SQL_API SQLBindParameter (HSTMT hstmt, RETCODE SQL_API SQLBindParameter(HSTMT hstmt,
UWORD ipar, UWORD ipar,
SWORD fParamType, SWORD fParamType,
SWORD fCType, SWORD fCType,
...@@ -1526,14 +1539,15 @@ RETCODE SQL_API SQLBindParameter (HSTMT hstmt, ...@@ -1526,14 +1539,15 @@ RETCODE SQL_API SQLBindParameter (HSTMT hstmt,
SDWORD cbValueMax, SDWORD cbValueMax,
SDWORD FAR * pcbValue); SDWORD FAR * pcbValue);
RETCODE SQL_API SQLSetScrollOptions (HSTMT hstmt, RETCODE SQL_API SQLSetScrollOptions(HSTMT hstmt,
UWORD fConcurrency, UWORD fConcurrency,
SDWORD crowKeyset, SDWORD crowKeyset,
UWORD crowRowset); UWORD crowRowset);
# ifdef __cplusplus #ifdef __cplusplus
} }
# endif
#endif
#endif #endif
...@@ -16,16 +16,17 @@ ...@@ -16,16 +16,17 @@
#include "connection.h" #include "connection.h"
Oid Oid
lo_creat(ConnectionClass *conn, int mode) lo_creat(ConnectionClass * conn, int mode)
{ {
LO_ARG argv[1]; LO_ARG argv[1];
int retval, result_len; int retval,
result_len;
argv[0].isint = 1; argv[0].isint = 1;
argv[0].len = 4; argv[0].len = 4;
argv[0].u.integer = mode; argv[0].u.integer = mode;
if ( ! CC_send_function(conn, LO_CREAT, &retval, &result_len, 1, argv, 1)) if (!CC_send_function(conn, LO_CREAT, &retval, &result_len, 1, argv, 1))
return 0; /* invalid oid */ return 0; /* invalid oid */
else else
return retval; return retval;
...@@ -34,11 +35,11 @@ int retval, result_len; ...@@ -34,11 +35,11 @@ int retval, result_len;
} }
int int
lo_open(ConnectionClass *conn, int lobjId, int mode) lo_open(ConnectionClass * conn, int lobjId, int mode)
{ {
int fd; int fd;
int result_len; int result_len;
LO_ARG argv[2]; LO_ARG argv[2];
argv[0].isint = 1; argv[0].isint = 1;
...@@ -49,7 +50,7 @@ LO_ARG argv[2]; ...@@ -49,7 +50,7 @@ LO_ARG argv[2];
argv[1].len = 4; argv[1].len = 4;
argv[1].u.integer = mode; argv[1].u.integer = mode;
if ( ! CC_send_function(conn, LO_OPEN, &fd, &result_len, 1, argv, 2)) if (!CC_send_function(conn, LO_OPEN, &fd, &result_len, 1, argv, 2))
return -1; return -1;
if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0) if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0)
...@@ -59,17 +60,18 @@ LO_ARG argv[2]; ...@@ -59,17 +60,18 @@ LO_ARG argv[2];
} }
int int
lo_close(ConnectionClass *conn, int fd) lo_close(ConnectionClass * conn, int fd)
{ {
LO_ARG argv[1]; LO_ARG argv[1];
int retval, result_len; int retval,
result_len;
argv[0].isint = 1; argv[0].isint = 1;
argv[0].len = 4; argv[0].len = 4;
argv[0].u.integer = fd; argv[0].u.integer = fd;
if ( ! CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1)) if (!CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1))
return -1; return -1;
else else
...@@ -79,10 +81,10 @@ int retval, result_len; ...@@ -79,10 +81,10 @@ int retval, result_len;
int int
lo_read(ConnectionClass *conn, int fd, char *buf, int len) lo_read(ConnectionClass * conn, int fd, char *buf, int len)
{ {
LO_ARG argv[2]; LO_ARG argv[2];
int result_len; int result_len;
argv[0].isint = 1; argv[0].isint = 1;
...@@ -93,7 +95,7 @@ int result_len; ...@@ -93,7 +95,7 @@ int result_len;
argv[1].len = 4; argv[1].len = 4;
argv[1].u.integer = len; argv[1].u.integer = len;
if ( ! CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2)) if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2))
return -1; return -1;
else else
...@@ -101,10 +103,11 @@ int result_len; ...@@ -101,10 +103,11 @@ int result_len;
} }
int int
lo_write(ConnectionClass *conn, int fd, char *buf, int len) lo_write(ConnectionClass * conn, int fd, char *buf, int len)
{ {
LO_ARG argv[2]; LO_ARG argv[2];
int retval, result_len; int retval,
result_len;
if (len <= 0) if (len <= 0)
...@@ -118,7 +121,7 @@ int retval, result_len; ...@@ -118,7 +121,7 @@ int retval, result_len;
argv[1].len = len; argv[1].len = len;
argv[1].u.ptr = (char *) buf; argv[1].u.ptr = (char *) buf;
if ( ! CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2)) if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2))
return -1; return -1;
else else
...@@ -126,10 +129,11 @@ int retval, result_len; ...@@ -126,10 +129,11 @@ int retval, result_len;
} }
int int
lo_lseek(ConnectionClass *conn, int fd, int offset, int whence) lo_lseek(ConnectionClass * conn, int fd, int offset, int whence)
{ {
LO_ARG argv[3]; LO_ARG argv[3];
int retval, result_len; int retval,
result_len;
argv[0].isint = 1; argv[0].isint = 1;
...@@ -144,7 +148,7 @@ int retval, result_len; ...@@ -144,7 +148,7 @@ int retval, result_len;
argv[2].len = 4; argv[2].len = 4;
argv[2].u.integer = whence; argv[2].u.integer = whence;
if ( ! CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3)) if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3))
return -1; return -1;
else else
...@@ -152,17 +156,18 @@ int retval, result_len; ...@@ -152,17 +156,18 @@ int retval, result_len;
} }
int int
lo_tell(ConnectionClass *conn, int fd) lo_tell(ConnectionClass * conn, int fd)
{ {
LO_ARG argv[1]; LO_ARG argv[1];
int retval, result_len; int retval,
result_len;
argv[0].isint = 1; argv[0].isint = 1;
argv[0].len = 4; argv[0].len = 4;
argv[0].u.integer = fd; argv[0].u.integer = fd;
if ( ! CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1)) if (!CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1))
return -1; return -1;
else else
...@@ -170,27 +175,20 @@ int retval, result_len; ...@@ -170,27 +175,20 @@ int retval, result_len;
} }
int int
lo_unlink(ConnectionClass *conn, Oid lobjId) lo_unlink(ConnectionClass * conn, Oid lobjId)
{ {
LO_ARG argv[1]; LO_ARG argv[1];
int retval, result_len; int retval,
result_len;
argv[0].isint = 1; argv[0].isint = 1;
argv[0].len = 4; argv[0].len = 4;
argv[0].u.integer = lobjId; argv[0].u.integer = lobjId;
if ( ! CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1)) if (!CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1))
return -1; return -1;
else else
return retval; return retval;
} }
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
#include "psqlodbc.h" #include "psqlodbc.h"
struct lo_arg { struct lo_arg
{
int isint; int isint;
int len; int len;
union union
...@@ -35,14 +36,13 @@ struct lo_arg { ...@@ -35,14 +36,13 @@ struct lo_arg {
#define INV_WRITE 0x00020000 #define INV_WRITE 0x00020000
#define INV_READ 0x00040000 #define INV_READ 0x00040000
Oid lo_creat(ConnectionClass *conn, int mode); Oid lo_creat(ConnectionClass * conn, int mode);
int lo_open(ConnectionClass *conn, int lobjId, int mode); int lo_open(ConnectionClass * conn, int lobjId, int mode);
int lo_close(ConnectionClass *conn, int fd); int lo_close(ConnectionClass * conn, int fd);
int lo_read(ConnectionClass *conn, int fd, char *buf, int len); int lo_read(ConnectionClass * conn, int fd, char *buf, int len);
int lo_write(ConnectionClass *conn, int fd, char *buf, int len); int lo_write(ConnectionClass * conn, int fd, char *buf, int len);
int lo_lseek(ConnectionClass *conn, int fd, int offset, int len); int lo_lseek(ConnectionClass * conn, int fd, int offset, int len);
int lo_tell(ConnectionClass *conn, int fd); int lo_tell(ConnectionClass * conn, int fd);
int lo_unlink(ConnectionClass *conn, Oid lobjId); int lo_unlink(ConnectionClass * conn, Oid lobjId);
#endif #endif
...@@ -24,49 +24,54 @@ ...@@ -24,49 +24,54 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#else #else
#include <process.h> /* Byron: is this where Windows keeps def. of getpid ? */ #include <process.h> /* Byron: is this where Windows keeps def.
* of getpid ? */
#endif #endif
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
void generate_filename(char*,char*,char*); void generate_filename(char *, char *, char *);
void void
generate_filename(char* dirname,char* prefix,char* filename) generate_filename(char *dirname, char *prefix, char *filename)
{ {
int pid = 0; int pid = 0;
#ifndef WIN32 #ifndef WIN32
struct passwd *ptr = 0; struct passwd *ptr = 0;
ptr = getpwuid(getuid()); ptr = getpwuid(getuid());
#endif #endif
pid = getpid(); pid = getpid();
if(dirname == 0 || filename == 0) if (dirname == 0 || filename == 0)
return; return;
strcpy(filename,dirname); strcpy(filename, dirname);
strcat(filename,DIRSEPARATOR); strcat(filename, DIRSEPARATOR);
if(prefix != 0) if (prefix != 0)
strcat(filename,prefix); strcat(filename, prefix);
#ifndef WIN32 #ifndef WIN32
strcat(filename,ptr->pw_name); strcat(filename, ptr->pw_name);
#endif #endif
sprintf(filename,"%s%u%s",filename,pid,".log"); sprintf(filename, "%s%u%s", filename, pid, ".log");
return; return;
} }
#ifdef MY_LOG #ifdef MY_LOG
void void
mylog(char * fmt, ...) mylog(char *fmt,...)
{ {
va_list args; va_list args;
char filebuf[80]; char filebuf[80];
FILE* LOGFP = globals.mylogFP; FILE *LOGFP = globals.mylogFP;
if ( globals.debug) { if (globals.debug)
{
va_start(args, fmt); va_start(args, fmt);
if (! LOGFP) { if (!LOGFP)
generate_filename(MYLOGDIR,MYLOGFILE,filebuf); {
generate_filename(MYLOGDIR, MYLOGFILE, filebuf);
LOGFP = fopen(filebuf, PG_BINARY_W); LOGFP = fopen(filebuf, PG_BINARY_W);
globals.mylogFP = LOGFP; globals.mylogFP = LOGFP;
setbuf(LOGFP, NULL); setbuf(LOGFP, NULL);
...@@ -78,23 +83,26 @@ mylog(char * fmt, ...) ...@@ -78,23 +83,26 @@ mylog(char * fmt, ...)
va_end(args); va_end(args);
} }
} }
#endif #endif
#ifdef Q_LOG #ifdef Q_LOG
void void
qlog(char * fmt, ...) qlog(char *fmt,...)
{ {
va_list args; va_list args;
char filebuf[80]; char filebuf[80];
FILE* LOGFP = globals.qlogFP; FILE *LOGFP = globals.qlogFP;
if ( globals.commlog) { if (globals.commlog)
{
va_start(args, fmt); va_start(args, fmt);
if (! LOGFP) { if (!LOGFP)
generate_filename(QLOGDIR,QLOGFILE,filebuf); {
generate_filename(QLOGDIR, QLOGFILE, filebuf);
LOGFP = fopen(filebuf, PG_BINARY_W); LOGFP = fopen(filebuf, PG_BINARY_W);
globals.qlogFP = LOGFP; globals.qlogFP = LOGFP;
setbuf(LOGFP, NULL); setbuf(LOGFP, NULL);
...@@ -106,6 +114,7 @@ qlog(char * fmt, ...) ...@@ -106,6 +114,7 @@ qlog(char * fmt, ...)
va_end(args); va_end(args);
} }
} }
#endif #endif
/* Undefine these because windows.h will redefine and cause a warning */ /* Undefine these because windows.h will redefine and cause a warning */
...@@ -135,7 +144,8 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len) ...@@ -135,7 +144,8 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
if (dst_len <= 0) if (dst_len <= 0)
return STRCPY_FAIL; return STRCPY_FAIL;
if (src_len == SQL_NULL_DATA) { if (src_len == SQL_NULL_DATA)
{
dst[0] = '\0'; dst[0] = '\0';
return STRCPY_NULL; return STRCPY_NULL;
} }
...@@ -145,14 +155,17 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len) ...@@ -145,14 +155,17 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
if (src_len <= 0) if (src_len <= 0)
return STRCPY_FAIL; return STRCPY_FAIL;
else { else
if (src_len < dst_len) { {
if (src_len < dst_len)
{
memcpy(dst, src, src_len); memcpy(dst, src, src_len);
dst[src_len] = '\0'; dst[src_len] = '\0';
} }
else { else
memcpy(dst, src, dst_len-1); {
dst[dst_len-1] = '\0'; /* truncated */ memcpy(dst, src, dst_len - 1);
dst[dst_len - 1] = '\0'; /* truncated */
return STRCPY_TRUNCATED; return STRCPY_TRUNCATED;
} }
} }
...@@ -164,29 +177,30 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len) ...@@ -164,29 +177,30 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
/* the destination string if src has len characters or more. */ /* the destination string if src has len characters or more. */
/* instead, I want it to copy up to len-1 characters and always */ /* instead, I want it to copy up to len-1 characters and always */
/* terminate the destination string. */ /* terminate the destination string. */
char *strncpy_null(char *dst, const char *src, int len) char *
strncpy_null(char *dst, const char *src, int len)
{ {
int i; int i;
if (NULL != dst) { if (NULL != dst)
{
/* Just in case, check for special lengths */ /* Just in case, check for special lengths */
if (len == SQL_NULL_DATA) { if (len == SQL_NULL_DATA)
{
dst[0] = '\0'; dst[0] = '\0';
return NULL; return NULL;
} }
else if (len == SQL_NTS) else if (len == SQL_NTS)
len = strlen(src) + 1; len = strlen(src) + 1;
for(i = 0; src[i] && i < len - 1; i++) { for (i = 0; src[i] && i < len - 1; i++)
dst[i] = src[i]; dst[i] = src[i];
}
if(len > 0) { if (len > 0)
dst[i] = '\0'; dst[i] = '\0';
} }
}
return dst; return dst;
} }
...@@ -196,22 +210,24 @@ int i; ...@@ -196,22 +210,24 @@ int i;
char * char *
make_string(char *s, int len, char *buf) make_string(char *s, int len, char *buf)
{ {
int length; int length;
char *str; char *str;
if(s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) { if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
{
length = (len > 0) ? len : strlen(s); length = (len > 0) ? len : strlen(s);
if (buf) { if (buf)
strncpy_null(buf, s, length+1); {
strncpy_null(buf, s, length + 1);
return buf; return buf;
} }
str = malloc(length + 1); str = malloc(length + 1);
if ( ! str) if (!str)
return NULL; return NULL;
strncpy_null(str, s, length+1); strncpy_null(str, s, length + 1);
return str; return str;
} }
...@@ -226,7 +242,8 @@ char * ...@@ -226,7 +242,8 @@ char *
my_strcat(char *buf, char *fmt, char *s, int len) my_strcat(char *buf, char *fmt, char *s, int len)
{ {
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) { if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
{
int length = (len > 0) ? len : strlen(s); int length = (len > 0) ? len : strlen(s);
int pos = strlen(buf); int pos = strlen(buf);
...@@ -237,16 +254,17 @@ my_strcat(char *buf, char *fmt, char *s, int len) ...@@ -237,16 +254,17 @@ my_strcat(char *buf, char *fmt, char *s, int len)
return NULL; return NULL;
} }
void remove_newlines(char *string) void
remove_newlines(char *string)
{ {
unsigned int i; unsigned int i;
for(i=0; i < strlen(string); i++) { for (i = 0; i < strlen(string); i++)
if((string[i] == '\n') || {
(string[i] == '\r')) { if ((string[i] == '\n') ||
(string[i] == '\r'))
string[i] = ' '; string[i] = ' ';
} }
}
} }
char * char *
...@@ -254,7 +272,8 @@ trim(char *s) ...@@ -254,7 +272,8 @@ trim(char *s)
{ {
int i; int i;
for (i = strlen(s) - 1; i >= 0; i--) { for (i = strlen(s) - 1; i >= 0; i--)
{
if (s[i] == ' ') if (s[i] == ' ')
s[i] = '\0'; s[i] = '\0';
else else
......
...@@ -39,35 +39,37 @@ ...@@ -39,35 +39,37 @@
#ifdef MY_LOG #ifdef MY_LOG
#define MYLOGFILE "mylog_" #define MYLOGFILE "mylog_"
#ifndef WIN32 #ifndef WIN32
#define MYLOGDIR "/tmp" #define MYLOGDIR "/tmp"
#else #else
#define MYLOGDIR "c:" #define MYLOGDIR "c:"
#endif #endif
extern void mylog(char * fmt, ...); extern void mylog(char *fmt,...);
#else #else
#ifndef WIN32 #ifndef WIN32
#define mylog(args...) /* GNU convention for variable arguments */ #define mylog(args...) /* GNU convention for variable arguments */
#else #else
#define mylog /* mylog */ #define mylog /* mylog */
#endif #endif
#endif #endif
#ifdef Q_LOG #ifdef Q_LOG
#define QLOGFILE "psqlodbc_" #define QLOGFILE "psqlodbc_"
#ifndef WIN32 #ifndef WIN32
#define QLOGDIR "/tmp" #define QLOGDIR "/tmp"
#else #else
#define QLOGDIR "c:" #define QLOGDIR "c:"
#endif #endif
extern void qlog(char * fmt, ...); extern void qlog(char *fmt,...);
#else #else
#ifndef WIN32 #ifndef WIN32
#define qlog(args...) /* GNU convention for variable arguments */ #define qlog(args...) /* GNU convention for variable arguments */
#else #else
#define qlog /* qlog */ #define qlog /* qlog */
#endif #endif
#endif #endif
#ifndef WIN32 #ifndef WIN32
......
...@@ -37,86 +37,108 @@ ...@@ -37,86 +37,108 @@
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
RETCODE set_statement_option(ConnectionClass *conn, RETCODE set_statement_option(ConnectionClass * conn,
StatementClass *stmt, StatementClass * stmt,
UWORD fOption, UWORD fOption,
UDWORD vParam); UDWORD vParam);
RETCODE set_statement_option(ConnectionClass *conn, RETCODE
StatementClass *stmt, set_statement_option(ConnectionClass * conn,
StatementClass * stmt,
UWORD fOption, UWORD fOption,
UDWORD vParam) UDWORD vParam)
{ {
static char *func="set_statement_option"; static char *func = "set_statement_option";
char changed = FALSE; char changed = FALSE;
switch(fOption) { switch (fOption)
case SQL_ASYNC_ENABLE:/* ignored */ {
case SQL_ASYNC_ENABLE: /* ignored */
break; break;
case SQL_BIND_TYPE: case SQL_BIND_TYPE:
/* now support multi-column and multi-row binding */ /* now support multi-column and multi-row binding */
if (conn) conn->stmtOptions.bind_size = vParam; if (conn)
if (stmt) stmt->options.bind_size = vParam; conn->stmtOptions.bind_size = vParam;
if (stmt)
stmt->options.bind_size = vParam;
break; break;
case SQL_CONCURRENCY: case SQL_CONCURRENCY:
/* positioned update isn't supported so cursor concurrency is read-only */
if (conn) conn->stmtOptions.scroll_concurrency = vParam;
if (stmt) stmt->options.scroll_concurrency = vParam;
break;
/* /*
if (globals.lie) { * positioned update isn't supported so cursor concurrency is
if (conn) conn->stmtOptions.scroll_concurrency = vParam; * read-only
if (stmt) stmt->options.scroll_concurrency = vParam; */
}
else {
if (conn) conn->stmtOptions.scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (stmt) stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (vParam != SQL_CONCUR_READ_ONLY) if (conn)
changed = TRUE; conn->stmtOptions.scroll_concurrency = vParam;
} if (stmt)
stmt->options.scroll_concurrency = vParam;
break; break;
/*
* if (globals.lie) { if (conn)
* conn->stmtOptions.scroll_concurrency = vParam; if (stmt)
* stmt->options.scroll_concurrency = vParam; } else {
*
* if (conn) conn->stmtOptions.scroll_concurrency =
* SQL_CONCUR_READ_ONLY; if (stmt)
* stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
*
* if (vParam != SQL_CONCUR_READ_ONLY) changed = TRUE; } break;
*/ */
case SQL_CURSOR_TYPE: case SQL_CURSOR_TYPE:
/* if declare/fetch, then type can only be forward.
otherwise, it can only be forward or static. /*
* if declare/fetch, then type can only be forward. otherwise,
* it can only be forward or static.
*/ */
mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam); mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);
if (globals.lie) { if (globals.lie)
{
if (conn) conn->stmtOptions.cursor_type = vParam; if (conn)
if (stmt) stmt->options.cursor_type = vParam; conn->stmtOptions.cursor_type = vParam;
if (stmt)
stmt->options.cursor_type = vParam;
} }
else { else
if (globals.use_declarefetch) { {
if (globals.use_declarefetch)
{
if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY; if (conn)
if (stmt) stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY; conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
if (stmt)
stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
if (vParam != SQL_CURSOR_FORWARD_ONLY) if (vParam != SQL_CURSOR_FORWARD_ONLY)
changed = TRUE; changed = TRUE;
} }
else { else
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC) { {
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
{
if (conn) conn->stmtOptions.cursor_type = vParam; /* valid type */ if (conn)
if (stmt) stmt->options.cursor_type = vParam; /* valid type */ conn->stmtOptions.cursor_type = vParam; /* valid type */
if (stmt)
stmt->options.cursor_type = vParam; /* valid type */
} }
else { else
{
if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC; if (conn)
if (stmt) stmt->options.cursor_type = SQL_CURSOR_STATIC; conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
if (stmt)
stmt->options.cursor_type = SQL_CURSOR_STATIC;
changed = TRUE; changed = TRUE;
} }
...@@ -127,78 +149,88 @@ char changed = FALSE; ...@@ -127,78 +149,88 @@ char changed = FALSE;
case SQL_KEYSET_SIZE: /* ignored, but saved and returned */ case SQL_KEYSET_SIZE: /* ignored, but saved and returned */
mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %d\n", vParam); mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %d\n", vParam);
if (conn) conn->stmtOptions.keyset_size = vParam; if (conn)
if (stmt) stmt->options.keyset_size = vParam; conn->stmtOptions.keyset_size = vParam;
if (stmt)
stmt->options.keyset_size = vParam;
break; break;
/* /*
if (globals.lie) * if (globals.lie) stmt->keyset_size = vParam; else {
stmt->keyset_size = vParam; * stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
else { * stmt->errormsg = "Driver does not support keyset size
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; * option"; SC_log_error(func, "", stmt); return SQL_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); mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam);
if (conn) conn->stmtOptions.maxLength = vParam; if (conn)
if (stmt) stmt->options.maxLength = vParam; conn->stmtOptions.maxLength = vParam;
if (stmt)
stmt->options.maxLength = vParam;
break; break;
case SQL_MAX_ROWS: /* ignored, but saved */ case SQL_MAX_ROWS: /* ignored, but saved */
mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam); mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam);
if (conn) conn->stmtOptions.maxRows = vParam; if (conn)
if (stmt) stmt->options.maxRows = vParam; conn->stmtOptions.maxRows = vParam;
if (stmt)
stmt->options.maxRows = vParam;
break; break;
case SQL_NOSCAN: /* ignored */ case SQL_NOSCAN: /* ignored */
mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam); mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam);
break; break;
case SQL_QUERY_TIMEOUT: /* ignored */ case SQL_QUERY_TIMEOUT:/* ignored */
mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam); mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam);
/* "0" returned in SQLGetStmtOption */ /* "0" returned in SQLGetStmtOption */
break; break;
case SQL_RETRIEVE_DATA: /* ignored, but saved */ case SQL_RETRIEVE_DATA:/* ignored, but saved */
mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam); mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam);
if (conn) conn->stmtOptions.retrieve_data = vParam; if (conn)
if (stmt) stmt->options.retrieve_data = vParam; conn->stmtOptions.retrieve_data = vParam;
if (stmt)
stmt->options.retrieve_data = vParam;
break; break;
case SQL_ROWSET_SIZE: case SQL_ROWSET_SIZE:
mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam); 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 * Save old rowset size for SQLExtendedFetch purposes If the
to fetch rows. * rowset_size is being changed since the last call to fetch
* rows.
*/ */
if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0 ) if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0)
stmt->save_rowset_size = stmt->options.rowset_size; stmt->save_rowset_size = stmt->options.rowset_size;
if (vParam < 1) { if (vParam < 1)
{
vParam = 1; vParam = 1;
changed = TRUE; changed = TRUE;
} }
if (conn) conn->stmtOptions.rowset_size = vParam; if (conn)
if (stmt) stmt->options.rowset_size = vParam; conn->stmtOptions.rowset_size = vParam;
if (stmt)
stmt->options.rowset_size = vParam;
break; break;
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */ case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
if (stmt) { if (stmt)
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library."; stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
} }
if (conn) { if (conn)
{
conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR; conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
conn->errormsg = "Simulated positioned update/delete not supported. Use the cursor library."; conn->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
...@@ -207,21 +239,25 @@ char changed = FALSE; ...@@ -207,21 +239,25 @@ char changed = FALSE;
case SQL_USE_BOOKMARKS: case SQL_USE_BOOKMARKS:
if (stmt) stmt->options.use_bookmarks = vParam; if (stmt)
if (conn) conn->stmtOptions.use_bookmarks = vParam; stmt->options.use_bookmarks = vParam;
if (conn)
conn->stmtOptions.use_bookmarks = vParam;
break; break;
default: default:
{ {
char option[64]; char option[64];
if (stmt) { if (stmt)
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Unknown statement option (Set)"; stmt->errormsg = "Unknown statement option (Set)";
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
SC_log_error(func, option, stmt); SC_log_error(func, option, stmt);
} }
if (conn) { if (conn)
{
conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR; conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
conn->errormsg = "Unknown statement option (Set)"; conn->errormsg = "Unknown statement option (Set)";
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
...@@ -232,12 +268,15 @@ char changed = FALSE; ...@@ -232,12 +268,15 @@ char changed = FALSE;
} }
} }
if (changed) { if (changed)
if (stmt) { {
if (stmt)
{
stmt->errormsg = "Requested value changed."; stmt->errormsg = "Requested value changed.";
stmt->errornumber = STMT_OPTION_VALUE_CHANGED; stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
} }
if (conn) { if (conn)
{
conn->errormsg = "Requested value changed."; conn->errormsg = "Requested value changed.";
conn->errornumber = STMT_OPTION_VALUE_CHANGED; conn->errornumber = STMT_OPTION_VALUE_CHANGED;
} }
...@@ -250,28 +289,33 @@ char changed = FALSE; ...@@ -250,28 +289,33 @@ char changed = FALSE;
/* Implements only SQL_AUTOCOMMIT */ /* Implements only SQL_AUTOCOMMIT */
RETCODE SQL_API SQLSetConnectOption( RETCODE SQL_API
SQLSetConnectOption(
HDBC hdbc, HDBC hdbc,
UWORD fOption, UWORD fOption,
UDWORD vParam) UDWORD vParam)
{ {
static char *func="SQLSetConnectOption"; static char *func = "SQLSetConnectOption";
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
char changed = FALSE; char changed = FALSE;
RETCODE retval; RETCODE retval;
int i; int i;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
switch (fOption) { 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_ASYNC_ENABLE:
case SQL_BIND_TYPE: case SQL_BIND_TYPE:
...@@ -288,13 +332,16 @@ int i; ...@@ -288,13 +332,16 @@ int i;
case SQL_USE_BOOKMARKS: case SQL_USE_BOOKMARKS:
/* Affect all current Statements */ /* Affect all current Statements */
for (i = 0; i < conn->num_stmts; i++) { for (i = 0; i < conn->num_stmts; i++)
if ( conn->stmts[i]) { {
if (conn->stmts[i])
set_statement_option(NULL, conn->stmts[i], fOption, vParam); set_statement_option(NULL, conn->stmts[i], fOption, vParam);
} }
}
/* Become the default for all future statements on this connection */ /*
* Become the default for all future statements on this
* connection
*/
retval = set_statement_option(conn, NULL, fOption, vParam); retval = set_statement_option(conn, NULL, fOption, vParam);
if (retval == SQL_SUCCESS_WITH_INFO) if (retval == SQL_SUCCESS_WITH_INFO)
...@@ -313,7 +360,8 @@ int i; ...@@ -313,7 +360,8 @@ int i;
case SQL_AUTOCOMMIT: case SQL_AUTOCOMMIT:
if (CC_is_in_trans(conn)) { if (CC_is_in_trans(conn))
{
conn->errormsg = "Cannot switch commit mode while a transaction is in progress"; conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
conn->errornumber = CONN_TRANSACT_IN_PROGRES; conn->errornumber = CONN_TRANSACT_IN_PROGRES;
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
...@@ -322,7 +370,8 @@ int i; ...@@ -322,7 +370,8 @@ int i;
mylog("SQLSetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam); mylog("SQLSetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);
switch(vParam) { switch (vParam)
{
case SQL_AUTOCOMMIT_OFF: case SQL_AUTOCOMMIT_OFF:
CC_set_autocommit_off(conn); CC_set_autocommit_off(conn);
break; break;
...@@ -343,7 +392,7 @@ int i; ...@@ -343,7 +392,7 @@ int i;
case SQL_CURRENT_QUALIFIER: /* ignored */ case SQL_CURRENT_QUALIFIER: /* ignored */
break; break;
case SQL_LOGIN_TIMEOUT: /* ignored */ case SQL_LOGIN_TIMEOUT:/* ignored */
break; break;
case SQL_PACKET_SIZE: /* ignored */ case SQL_PACKET_SIZE: /* ignored */
...@@ -352,7 +401,7 @@ int i; ...@@ -352,7 +401,7 @@ int i;
case SQL_QUIET_MODE: /* ignored */ case SQL_QUIET_MODE: /* ignored */
break; break;
case SQL_TXN_ISOLATION: /* ignored */ case SQL_TXN_ISOLATION:/* ignored */
break; break;
/* These options should be handled by driver manager */ /* These options should be handled by driver manager */
...@@ -367,6 +416,7 @@ int i; ...@@ -367,6 +416,7 @@ int i;
default: default:
{ {
char option[64]; char option[64];
conn->errormsg = "Unknown connect option (Set)"; conn->errormsg = "Unknown connect option (Set)";
conn->errornumber = CONN_UNSUPPORTED_OPTION; conn->errornumber = CONN_UNSUPPORTED_OPTION;
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
...@@ -376,7 +426,8 @@ int i; ...@@ -376,7 +426,8 @@ int i;
} }
if (changed) { if (changed)
{
conn->errornumber = CONN_OPTION_VALUE_CHANGED; conn->errornumber = CONN_OPTION_VALUE_CHANGED;
conn->errormsg = "Requested value changed."; conn->errormsg = "Requested value changed.";
return SQL_SUCCESS_WITH_INFO; return SQL_SUCCESS_WITH_INFO;
...@@ -388,38 +439,41 @@ int i; ...@@ -388,38 +439,41 @@ int i;
/* - - - - - - - - - */ /* - - - - - - - - - */
/* This function just can tell you whether you are in Autcommit mode or not */ /* This function just can tell you whether you are in Autcommit mode or not */
RETCODE SQL_API SQLGetConnectOption( RETCODE SQL_API
SQLGetConnectOption(
HDBC hdbc, HDBC hdbc,
UWORD fOption, UWORD fOption,
PTR pvParam) PTR pvParam)
{ {
static char *func="SQLGetConnectOption"; static char *func = "SQLGetConnectOption";
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if (! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
switch (fOption) { switch (fOption)
case SQL_ACCESS_MODE:/* NOT SUPPORTED */ {
case SQL_ACCESS_MODE: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = SQL_MODE_READ_WRITE; *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
break; break;
case SQL_AUTOCOMMIT: case SQL_AUTOCOMMIT:
*((UDWORD *)pvParam) = (UDWORD)( CC_is_in_autocommit(conn) ? *((UDWORD *) pvParam) = (UDWORD) (CC_is_in_autocommit(conn) ?
SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF); SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
break; break;
case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */ case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */
if(pvParam) if (pvParam)
strcpy(pvParam, ""); strcpy(pvParam, "");
break; break;
case SQL_LOGIN_TIMEOUT: /* NOT SUPPORTED */ case SQL_LOGIN_TIMEOUT:/* NOT SUPPORTED */
*((UDWORD *) pvParam) = 0; *((UDWORD *) pvParam) = 0;
break; break;
...@@ -427,7 +481,7 @@ ConnectionClass *conn = (ConnectionClass *) hdbc; ...@@ -427,7 +481,7 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
*((UDWORD *) pvParam) = globals.socket_buffersize; *((UDWORD *) pvParam) = globals.socket_buffersize;
break; break;
case SQL_QUIET_MODE:/* NOT SUPPORTED */ case SQL_QUIET_MODE: /* NOT SUPPORTED */
*((UDWORD *) pvParam) = (UDWORD) NULL; *((UDWORD *) pvParam) = (UDWORD) NULL;
break; break;
...@@ -447,6 +501,7 @@ ConnectionClass *conn = (ConnectionClass *) hdbc; ...@@ -447,6 +501,7 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
default: default:
{ {
char option[64]; char option[64];
conn->errormsg = "Unknown connect option (Get)"; conn->errormsg = "Unknown connect option (Get)";
conn->errornumber = CONN_UNSUPPORTED_OPTION; conn->errornumber = CONN_UNSUPPORTED_OPTION;
sprintf(option, "fOption=%d", fOption); sprintf(option, "fOption=%d", fOption);
...@@ -462,13 +517,14 @@ ConnectionClass *conn = (ConnectionClass *) hdbc; ...@@ -462,13 +517,14 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLSetStmtOption( RETCODE SQL_API
SQLSetStmtOption(
HSTMT hstmt, HSTMT hstmt,
UWORD fOption, UWORD fOption,
UDWORD vParam) UDWORD vParam)
{ {
static char *func="SQLSetStmtOption"; static char *func = "SQLSetStmtOption";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -476,7 +532,8 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -476,7 +532,8 @@ StatementClass *stmt = (StatementClass *) hstmt;
/* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */ /* 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 */ /* and expects the driver to reduce it to the real value */
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -487,14 +544,15 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -487,14 +544,15 @@ StatementClass *stmt = (StatementClass *) hstmt;
/* - - - - - - - - - */ /* - - - - - - - - - */
RETCODE SQL_API SQLGetStmtOption( RETCODE SQL_API
SQLGetStmtOption(
HSTMT hstmt, HSTMT hstmt,
UWORD fOption, UWORD fOption,
PTR pvParam) PTR pvParam)
{ {
static char *func="SQLGetStmtOption"; static char *func = "SQLGetStmtOption";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -502,29 +560,35 @@ QResultClass *res; ...@@ -502,29 +560,35 @@ QResultClass *res;
/* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */ /* 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 */ /* and expects the driver to reduce it to the real value */
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
switch(fOption) { switch (fOption)
{
case SQL_GET_BOOKMARK: case SQL_GET_BOOKMARK:
case SQL_ROW_NUMBER: case SQL_ROW_NUMBER:
res = stmt->result; res = stmt->result;
if ( stmt->manual_result || ! globals.use_declarefetch) { if (stmt->manual_result || !globals.use_declarefetch)
{
/* make sure we're positioned on a valid row */ /* make sure we're positioned on a valid row */
if((stmt->currTuple < 0) || if ((stmt->currTuple < 0) ||
(stmt->currTuple >= QR_get_num_tuples(res))) { (stmt->currTuple >= QR_get_num_tuples(res)))
{
stmt->errormsg = "Not positioned on a valid row."; stmt->errormsg = "Not positioned on a valid row.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
} }
else { else
if (stmt->currTuple == -1 || ! res || ! res->tupleField) { {
if (stmt->currTuple == -1 || !res || !res->tupleField)
{
stmt->errormsg = "Not positioned on a valid row."; stmt->errormsg = "Not positioned on a valid row.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -532,7 +596,8 @@ QResultClass *res; ...@@ -532,7 +596,8 @@ QResultClass *res;
} }
} }
if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF) { if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF)
{
stmt->errormsg = "Operation invalid because use bookmarks not enabled."; stmt->errormsg = "Operation invalid because use bookmarks not enabled.";
stmt->errornumber = STMT_OPERATION_INVALID; stmt->errornumber = STMT_OPERATION_INVALID;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -553,37 +618,37 @@ QResultClass *res; ...@@ -553,37 +618,37 @@ QResultClass *res;
case SQL_CONCURRENCY: /* NOT REALLY SUPPORTED */ case SQL_CONCURRENCY: /* NOT REALLY SUPPORTED */
mylog("GetStmtOption(): SQL_CONCURRENCY\n"); mylog("GetStmtOption(): SQL_CONCURRENCY\n");
*((SDWORD *)pvParam) = stmt->options.scroll_concurrency; *((SDWORD *) pvParam) = stmt->options.scroll_concurrency;
break; break;
case SQL_CURSOR_TYPE: /* PARTIAL SUPPORT */ case SQL_CURSOR_TYPE: /* PARTIAL SUPPORT */
mylog("GetStmtOption(): SQL_CURSOR_TYPE\n"); mylog("GetStmtOption(): SQL_CURSOR_TYPE\n");
*((SDWORD *)pvParam) = stmt->options.cursor_type; *((SDWORD *) pvParam) = stmt->options.cursor_type;
break; break;
case SQL_KEYSET_SIZE: /* NOT SUPPORTED, but saved */ case SQL_KEYSET_SIZE: /* NOT SUPPORTED, but saved */
mylog("GetStmtOption(): SQL_KEYSET_SIZE\n"); mylog("GetStmtOption(): SQL_KEYSET_SIZE\n");
*((SDWORD *)pvParam) = stmt->options.keyset_size; *((SDWORD *) pvParam) = stmt->options.keyset_size;
break; break;
case SQL_MAX_LENGTH: /* NOT SUPPORTED, but saved */ case SQL_MAX_LENGTH: /* NOT SUPPORTED, but saved */
*((SDWORD *)pvParam) = stmt->options.maxLength; *((SDWORD *) pvParam) = stmt->options.maxLength;
break; break;
case SQL_MAX_ROWS: /* NOT SUPPORTED, but saved */ case SQL_MAX_ROWS: /* NOT SUPPORTED, but saved */
*((SDWORD *)pvParam) = stmt->options.maxRows; *((SDWORD *) pvParam) = stmt->options.maxRows;
mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->options.maxRows); mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->options.maxRows);
break; break;
case SQL_NOSCAN:/* NOT SUPPORTED */ case SQL_NOSCAN: /* NOT SUPPORTED */
*((SDWORD *) pvParam) = SQL_NOSCAN_ON; *((SDWORD *) pvParam) = SQL_NOSCAN_ON;
break; break;
case SQL_QUERY_TIMEOUT: /* NOT SUPPORTED */ case SQL_QUERY_TIMEOUT:/* NOT SUPPORTED */
*((SDWORD *) pvParam) = 0; *((SDWORD *) pvParam) = 0;
break; break;
case SQL_RETRIEVE_DATA: /* NOT SUPPORTED, but saved */ case SQL_RETRIEVE_DATA:/* NOT SUPPORTED, but saved */
*((SDWORD *) pvParam) = stmt->options.retrieve_data; *((SDWORD *) pvParam) = stmt->options.retrieve_data;
break; break;
...@@ -591,7 +656,7 @@ QResultClass *res; ...@@ -591,7 +656,7 @@ QResultClass *res;
*((SDWORD *) pvParam) = stmt->options.rowset_size; *((SDWORD *) pvParam) = stmt->options.rowset_size;
break; break;
case SQL_SIMULATE_CURSOR:/* NOT SUPPORTED */ case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
*((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE; *((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE;
break; break;
...@@ -602,6 +667,7 @@ QResultClass *res; ...@@ -602,6 +667,7 @@ QResultClass *res;
default: default:
{ {
char option[64]; char option[64];
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Unknown statement option (Get)"; stmt->errormsg = "Unknown statement option (Get)";
sprintf(option, "fOption=%d", fOption); sprintf(option, "fOption=%d", fOption);
......
...@@ -38,15 +38,16 @@ ...@@ -38,15 +38,16 @@
#define COL_INCR 16 #define COL_INCR 16
char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric); char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k); void getColInfo(COL_INFO * col_info, FIELD_INFO * fi, int k);
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi); char searchColInfo(COL_INFO * col_info, FIELD_INFO * fi);
char * char *
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric) getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
{ {
int i = 0; int i = 0;
int out = 0; int out = 0;
char qc, in_escape = FALSE; char qc,
in_escape = FALSE;
if (smax <= 1) if (smax <= 1)
return NULL; return NULL;
...@@ -54,43 +55,54 @@ char qc, in_escape = FALSE; ...@@ -54,43 +55,54 @@ char qc, in_escape = FALSE;
smax--; smax--;
/* skip leading delimiters */ /* skip leading delimiters */
while (isspace((unsigned char) s[i]) || s[i] == ',') { while (isspace((unsigned char) s[i]) || s[i] == ',')
{
/* mylog("skipping '%c'\n", s[i]); */ /* mylog("skipping '%c'\n", s[i]); */
i++; i++;
} }
if (s[0] == '\0') { if (s[0] == '\0')
{
token[0] = '\0'; token[0] = '\0';
return NULL; return NULL;
} }
if (quote) *quote = FALSE; if (quote)
if (dquote) *dquote = FALSE; *quote = FALSE;
if (numeric) *numeric = FALSE; if (dquote)
*dquote = FALSE;
if (numeric)
*numeric = FALSE;
/* get the next token */ /* get the next token */
while ( ! isspace((unsigned char) s[i]) && s[i] != ',' && while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
s[i] != '\0' && out != smax) { s[i] != '\0' && out != smax)
{
/* Handle quoted stuff */ /* Handle quoted stuff */
if ( out == 0 && (s[i] == '\"' || s[i] == '\'')) { if (out == 0 && (s[i] == '\"' || s[i] == '\''))
{
qc = s[i]; qc = s[i];
if (qc == '\"') { if (qc == '\"')
if (dquote) *dquote = TRUE; {
if (dquote)
*dquote = TRUE;
} }
if (qc == '\'') { if (qc == '\'')
if (quote) *quote = TRUE; {
if (quote)
*quote = TRUE;
} }
i++; /* dont return the quote */ i++; /* dont return the quote */
while (s[i] != '\0' && out != smax) { while (s[i] != '\0' && out != smax)
if (s[i] == qc && ! in_escape) { {
if (s[i] == qc && !in_escape)
break; break;
} if (s[i] == '\\' && !in_escape)
if (s[i] == '\\' && ! in_escape) {
in_escape = TRUE; in_escape = TRUE;
} else
else { {
in_escape = FALSE; in_escape = FALSE;
token[out++] = s[i]; token[out++] = s[i];
} }
...@@ -102,19 +114,23 @@ char qc, in_escape = FALSE; ...@@ -102,19 +114,23 @@ char qc, in_escape = FALSE;
} }
/* Check for numeric literals */ /* Check for numeric literals */
if ( out == 0 && isdigit((unsigned char) s[i])) { if (out == 0 && isdigit((unsigned char) s[i]))
if (numeric) *numeric = TRUE; {
if (numeric)
*numeric = TRUE;
token[out++] = s[i++]; token[out++] = s[i++];
while ( isalnum((unsigned char) s[i]) || s[i] == '.') while (isalnum((unsigned char) s[i]) || s[i] == '.')
token[out++] = s[i++]; token[out++] = s[i++];
break; break;
} }
if ( ispunct((unsigned char) s[i]) && s[i] != '_') { if (ispunct((unsigned char) s[i]) && s[i] != '_')
{
mylog("got ispunct: s[%d] = '%c'\n", i, s[i]); mylog("got ispunct: s[%d] = '%c'\n", i, s[i]);
if (out == 0) { if (out == 0)
{
token[out++] = s[i++]; token[out++] = s[i++];
break; break;
} }
...@@ -133,24 +149,29 @@ char qc, in_escape = FALSE; ...@@ -133,24 +149,29 @@ char qc, in_escape = FALSE;
token[out] = '\0'; token[out] = '\0';
/* find the delimiter */ /* find the delimiter */
while ( isspace((unsigned char) s[i])) while (isspace((unsigned char) s[i]))
i++; i++;
/* return the most priority delimiter */ /* return the most priority delimiter */
if (s[i] == ',') { if (s[i] == ',')
if (delim) *delim = s[i]; {
if (delim)
*delim = s[i];
} }
else if (s[i] == '\0') { else if (s[i] == '\0')
if (delim) *delim = '\0'; {
if (delim)
*delim = '\0';
} }
else { else
if (delim) *delim = ' '; {
if (delim)
*delim = ' ';
} }
/* skip trailing blanks */ /* skip trailing blanks */
while ( isspace((unsigned char) s[i])) { while (isspace((unsigned char) s[i]))
i++; i++;
}
return &s[i]; return &s[i];
} }
...@@ -176,28 +197,30 @@ QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4); ...@@ -176,28 +197,30 @@ QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
#endif #endif
void void
getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k) getColInfo(COL_INFO * col_info, FIELD_INFO * fi, int k)
{ {
if (fi->name[0] == '\0') if (fi->name[0] == '\0')
strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3)); strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3));
fi->type = atoi( QR_get_value_manual(col_info->result, k, 13)); fi->type = atoi(QR_get_value_manual(col_info->result, k, 13));
fi->precision = atoi( QR_get_value_manual(col_info->result, k, 6)); fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6));
fi->length = atoi( QR_get_value_manual(col_info->result, k, 7)); fi->length = atoi(QR_get_value_manual(col_info->result, k, 7));
fi->nullable = atoi( QR_get_value_manual(col_info->result, k, 10)); fi->nullable = atoi(QR_get_value_manual(col_info->result, k, 10));
fi->display_size = atoi( QR_get_value_manual(col_info->result, k, 12)); fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
} }
char char
searchColInfo(COL_INFO *col_info, FIELD_INFO *fi) searchColInfo(COL_INFO * col_info, FIELD_INFO * fi)
{ {
int k; int k;
char *col; char *col;
for (k = 0; k < QR_get_num_tuples(col_info->result); k++) { for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
{
col = QR_get_value_manual(col_info->result, k, 3); col = QR_get_value_manual(col_info->result, k, 3);
if ( ! strcmp(col, fi->name)) { if (!strcmp(col, fi->name))
{
getColInfo(col_info, fi, k); getColInfo(col_info, fi, k);
mylog("PARSE: searchColInfo: \n"); mylog("PARSE: searchColInfo: \n");
...@@ -210,22 +233,39 @@ char *col; ...@@ -210,22 +233,39 @@ char *col;
char char
parse_statement(StatementClass *stmt) parse_statement(StatementClass * stmt)
{ {
static char *func="parse_statement"; static char *func = "parse_statement";
char token[256]; char token[256];
char delim, quote, dquote, numeric, unquoted; char delim,
char *ptr; quote,
char in_select = FALSE, in_distinct = FALSE, in_on = FALSE, in_from = FALSE, in_where = FALSE, in_table = FALSE; dquote,
char in_field = FALSE, in_expr = FALSE, in_func = FALSE, in_dot = FALSE, in_as = FALSE; numeric,
int j, i, k = 0, n, blevel = 0; unquoted;
FIELD_INFO **fi; char *ptr;
TABLE_INFO **ti; char in_select = FALSE,
char parse; in_distinct = FALSE,
ConnectionClass *conn = stmt->hdbc; in_on = FALSE,
HSTMT hcol_stmt; in_from = FALSE,
StatementClass *col_stmt; in_where = FALSE,
RETCODE result; in_table = FALSE;
char in_field = FALSE,
in_expr = FALSE,
in_func = FALSE,
in_dot = FALSE,
in_as = FALSE;
int j,
i,
k = 0,
n,
blevel = 0;
FIELD_INFO **fi;
TABLE_INFO **ti;
char parse;
ConnectionClass *conn = stmt->hdbc;
HSTMT hcol_stmt;
StatementClass *col_stmt;
RETCODE result;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
...@@ -237,34 +277,39 @@ RETCODE result; ...@@ -237,34 +277,39 @@ RETCODE result;
stmt->nfld = 0; stmt->nfld = 0;
stmt->ntab = 0; stmt->ntab = 0;
while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL) { while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
{
unquoted = ! ( quote || dquote ); 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); mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr);
if ( unquoted && ! stricmp(token, "select")) { if (unquoted && !stricmp(token, "select"))
{
in_select = TRUE; in_select = TRUE;
mylog("SELECT\n"); mylog("SELECT\n");
continue; continue;
} }
if ( unquoted && in_select && ! stricmp(token, "distinct")) { if (unquoted && in_select && !stricmp(token, "distinct"))
{
in_distinct = TRUE; in_distinct = TRUE;
mylog("DISTINCT\n"); mylog("DISTINCT\n");
continue; continue;
} }
if ( unquoted && ! stricmp(token, "into")) { if (unquoted && !stricmp(token, "into"))
{
in_select = FALSE; in_select = FALSE;
mylog("INTO\n"); mylog("INTO\n");
continue; continue;
} }
if ( unquoted && ! stricmp(token, "from")) { if (unquoted && !stricmp(token, "from"))
{
in_select = FALSE; in_select = FALSE;
in_from = TRUE; in_from = TRUE;
...@@ -272,11 +317,12 @@ RETCODE result; ...@@ -272,11 +317,12 @@ RETCODE result;
continue; continue;
} }
if ( unquoted && (! stricmp(token, "where") || if (unquoted && (!stricmp(token, "where") ||
! stricmp(token, "union") || !stricmp(token, "union") ||
! stricmp(token, "order") || !stricmp(token, "order") ||
! stricmp(token, "group") || !stricmp(token, "group") ||
! stricmp(token, "having"))) { !stricmp(token, "having")))
{
in_select = FALSE; in_select = FALSE;
in_from = FALSE; in_from = FALSE;
...@@ -286,17 +332,21 @@ RETCODE result; ...@@ -286,17 +332,21 @@ RETCODE result;
break; break;
} }
if (in_select) { if (in_select)
{
if ( in_distinct) { if (in_distinct)
{
mylog("in distinct\n"); mylog("in distinct\n");
if (unquoted && ! stricmp(token, "on")) { if (unquoted && !stricmp(token, "on"))
{
in_on = TRUE; in_on = TRUE;
mylog("got on\n"); mylog("got on\n");
continue; continue;
} }
if (in_on) { if (in_on)
{
in_distinct = FALSE; in_distinct = FALSE;
in_on = FALSE; in_on = FALSE;
continue; /* just skip the unique on field */ continue; /* just skip the unique on field */
...@@ -305,25 +355,30 @@ RETCODE result; ...@@ -305,25 +355,30 @@ RETCODE result;
in_distinct = FALSE; in_distinct = FALSE;
} }
if ( in_expr || in_func) { /* just eat the expression */ if (in_expr || in_func)
{ /* just eat the expression */
mylog("in_expr=%d or func=%d\n", in_expr, in_func); mylog("in_expr=%d or func=%d\n", in_expr, in_func);
if (quote || dquote) if (quote || dquote)
continue; continue;
if (in_expr && blevel == 0 && delim == ',') { if (in_expr && blevel == 0 && delim == ',')
{
mylog("**** in_expr and Got comma\n"); mylog("**** in_expr and Got comma\n");
in_expr = FALSE; in_expr = FALSE;
in_field = FALSE; in_field = FALSE;
} }
else if (token[0] == '(') { else if (token[0] == '(')
{
blevel++; blevel++;
mylog("blevel++ = %d\n", blevel); mylog("blevel++ = %d\n", blevel);
} }
else if (token[0] == ')') { else if (token[0] == ')')
{
blevel--; blevel--;
mylog("blevel-- = %d\n", blevel); mylog("blevel-- = %d\n", blevel);
if (delim==',') { if (delim == ',')
{
in_func = FALSE; in_func = FALSE;
in_expr = FALSE; in_expr = FALSE;
in_field = FALSE; in_field = FALSE;
...@@ -332,23 +387,27 @@ RETCODE result; ...@@ -332,23 +387,27 @@ RETCODE result;
continue; continue;
} }
if ( ! in_field) { if (!in_field)
{
if ( ! token[0]) if (!token[0])
continue; continue;
if ( ! (stmt->nfld % FLD_INCR)) { if (!(stmt->nfld % FLD_INCR))
{
mylog("reallocing at nfld=%d\n", stmt->nfld); mylog("reallocing at nfld=%d\n", stmt->nfld);
fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *)); fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *));
if ( ! fi) { if (!fi)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
stmt->fi = fi; stmt->fi = fi;
} }
fi[stmt->nfld] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO)); fi[stmt->nfld] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO));
if (fi[stmt->nfld] == NULL) { if (fi[stmt->nfld] == NULL)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
...@@ -360,15 +419,18 @@ RETCODE result; ...@@ -360,15 +419,18 @@ RETCODE result;
if (dquote) if (dquote)
fi[stmt->nfld]->dquote = TRUE; fi[stmt->nfld]->dquote = TRUE;
if (quote) { if (quote)
{
fi[stmt->nfld++]->quote = TRUE; fi[stmt->nfld++]->quote = TRUE;
continue; continue;
} }
else if (numeric) { else if (numeric)
{
mylog("**** got numeric: nfld = %d\n", stmt->nfld); mylog("**** got numeric: nfld = %d\n", stmt->nfld);
fi[stmt->nfld]->numeric = TRUE; fi[stmt->nfld]->numeric = TRUE;
} }
else if (token[0] == '(') { /* expression */ else if (token[0] == '(')
{ /* expression */
mylog("got EXPRESSION\n"); mylog("got EXPRESSION\n");
fi[stmt->nfld++]->expr = TRUE; fi[stmt->nfld++]->expr = TRUE;
in_expr = TRUE; in_expr = TRUE;
...@@ -376,18 +438,17 @@ RETCODE result; ...@@ -376,18 +438,17 @@ RETCODE result;
continue; continue;
} }
else { else
{
strcpy(fi[stmt->nfld]->name, token); strcpy(fi[stmt->nfld]->name, token);
fi[stmt->nfld]->dot[0] = '\0'; fi[stmt->nfld]->dot[0] = '\0';
} }
mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot); mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot);
if (delim == ',') { if (delim == ',')
mylog("comma (1)\n"); mylog("comma (1)\n");
} else
else {
in_field = TRUE; in_field = TRUE;
}
stmt->nfld++; stmt->nfld++;
continue; continue;
} }
...@@ -395,14 +456,16 @@ RETCODE result; ...@@ -395,14 +456,16 @@ RETCODE result;
/**************************/ /**************************/
/* We are in a field now */ /* We are in a field now */
/**************************/ /**************************/
if (in_dot) { if (in_dot)
{
stmt->nfld--; stmt->nfld--;
strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name); strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name);
strcpy(fi[stmt->nfld]->name, token); strcpy(fi[stmt->nfld]->name, token);
stmt->nfld++; stmt->nfld++;
in_dot = FALSE; in_dot = FALSE;
if (delim == ',') { if (delim == ',')
{
mylog("in_dot: got comma\n"); mylog("in_dot: got comma\n");
in_field = FALSE; in_field = FALSE;
} }
...@@ -410,7 +473,8 @@ RETCODE result; ...@@ -410,7 +473,8 @@ RETCODE result;
continue; continue;
} }
if (in_as) { if (in_as)
{
stmt->nfld--; stmt->nfld--;
strcpy(fi[stmt->nfld]->alias, token); strcpy(fi[stmt->nfld]->alias, token);
mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias); mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias);
...@@ -419,29 +483,35 @@ RETCODE result; ...@@ -419,29 +483,35 @@ RETCODE result;
stmt->nfld++; stmt->nfld++;
if (delim == ',') { if (delim == ',')
mylog("comma(2)\n"); mylog("comma(2)\n");
}
continue; continue;
} }
/* Function */ /* Function */
if (token[0] == '(') { if (token[0] == '(')
{
in_func = TRUE; in_func = TRUE;
blevel = 1; blevel = 1;
fi[stmt->nfld-1]->func = TRUE; fi[stmt->nfld - 1]->func = TRUE;
/* name will have the function name -- maybe useful some day */
mylog("**** got function = '%s'\n", fi[stmt->nfld-1]->name); /*
* name will have the function name -- maybe useful some
* day
*/
mylog("**** got function = '%s'\n", fi[stmt->nfld - 1]->name);
continue; continue;
} }
if (token[0] == '.') { if (token[0] == '.')
{
in_dot = TRUE; in_dot = TRUE;
mylog("got dot\n"); mylog("got dot\n");
continue; continue;
} }
if ( ! stricmp(token, "as")) { if (!stricmp(token, "as"))
{
in_as = TRUE; in_as = TRUE;
mylog("got AS\n"); mylog("got AS\n");
continue; continue;
...@@ -449,28 +519,33 @@ RETCODE result; ...@@ -449,28 +519,33 @@ RETCODE result;
/* otherwise, it's probably an expression */ /* otherwise, it's probably an expression */
in_expr = TRUE; in_expr = TRUE;
fi[stmt->nfld-1]->expr = TRUE; fi[stmt->nfld - 1]->expr = TRUE;
fi[stmt->nfld-1]->name[0] = '\0'; fi[stmt->nfld - 1]->name[0] = '\0';
mylog("*** setting expression\n"); mylog("*** setting expression\n");
} }
if (in_from) { if (in_from)
{
if ( ! in_table) { if (!in_table)
if ( ! token[0]) {
if (!token[0])
continue; continue;
if ( ! (stmt->ntab % TAB_INCR)) { if (!(stmt->ntab % TAB_INCR))
{
ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *)); ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *));
if ( ! ti) { if (!ti)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
stmt->ti = ti; stmt->ti = ti;
} }
ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO)); ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO));
if (ti[stmt->ntab] == NULL) { if (ti[stmt->ntab] == NULL)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
...@@ -480,24 +555,21 @@ RETCODE result; ...@@ -480,24 +555,21 @@ RETCODE result;
strcpy(ti[stmt->ntab]->name, token); strcpy(ti[stmt->ntab]->name, token);
mylog("got table = '%s'\n", ti[stmt->ntab]->name); mylog("got table = '%s'\n", ti[stmt->ntab]->name);
if (delim == ',') { if (delim == ',')
mylog("more than 1 tables\n"); mylog("more than 1 tables\n");
} else
else {
in_table = TRUE; in_table = TRUE;
}
stmt->ntab++; stmt->ntab++;
continue; continue;
} }
strcpy(ti[stmt->ntab-1]->alias, token); strcpy(ti[stmt->ntab - 1]->alias, token);
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab-1]->name, ti[stmt->ntab-1]->alias); mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias);
in_table = FALSE; in_table = FALSE;
if (delim == ',') { if (delim == ',')
mylog("more than 1 tables\n"); mylog("more than 1 tables\n");
} }
} }
}
/*************************************************/ /*************************************************/
...@@ -507,16 +579,19 @@ RETCODE result; ...@@ -507,16 +579,19 @@ RETCODE result;
parse = TRUE; parse = TRUE;
/* Resolve field names with tables */ /* Resolve field names with tables */
for (i = 0; i < stmt->nfld; i++) { for (i = 0; i < stmt->nfld; i++)
{
if (fi[i]->func || fi[i]->expr || fi[i]->numeric) { if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
{
fi[i]->ti = NULL; fi[i]->ti = NULL;
fi[i]->type = -1; fi[i]->type = -1;
parse = FALSE; parse = FALSE;
continue; continue;
} }
else if (fi[i]->quote) { /* handle as text */ else if (fi[i]->quote)
{ /* handle as text */
fi[i]->ti = NULL; fi[i]->ti = NULL;
fi[i]->type = PG_TYPE_TEXT; fi[i]->type = PG_TYPE_TEXT;
fi[i]->precision = 0; fi[i]->precision = 0;
...@@ -524,13 +599,17 @@ RETCODE result; ...@@ -524,13 +599,17 @@ RETCODE result;
} }
/* it's a dot, resolve to table or alias */ /* it's a dot, resolve to table or alias */
else if (fi[i]->dot[0]) { else if (fi[i]->dot[0])
for (k = 0; k < stmt->ntab; k++) { {
if ( ! stricmp(ti[k]->name, fi[i]->dot)) { for (k = 0; k < stmt->ntab; k++)
{
if (!stricmp(ti[k]->name, fi[i]->dot))
{
fi[i]->ti = ti[k]; fi[i]->ti = ti[k];
break; break;
} }
else if ( ! stricmp(ti[k]->alias, fi[i]->dot)) { else if (!stricmp(ti[k]->alias, fi[i]->dot))
{
fi[i]->ti = ti[k]; fi[i]->ti = ti[k];
break; break;
} }
...@@ -543,15 +622,15 @@ RETCODE result; ...@@ -543,15 +622,15 @@ RETCODE result;
mylog("--------------------------------------------\n"); mylog("--------------------------------------------\n");
mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab); mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab);
for (i=0; i < stmt->nfld; i++) { for (i = 0; i < stmt->nfld; i++)
{
mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot); mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot);
if (fi[i]->ti) if (fi[i]->ti)
mylog(" ----> table_name='%s', table_alias='%s'\n", fi[i]->ti->name, fi[i]->ti->alias); mylog(" ----> table_name='%s', table_alias='%s'\n", fi[i]->ti->name, fi[i]->ti->alias);
} }
for (i=0; i < stmt->ntab; i++) { for (i = 0; i < stmt->ntab; i++)
mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias); mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);
}
/******************************************************/ /******************************************************/
...@@ -560,24 +639,30 @@ RETCODE result; ...@@ -560,24 +639,30 @@ RETCODE result;
/* Call SQLColumns for each table and store the result */ /* Call SQLColumns for each table and store the result */
for (i = 0; i < stmt->ntab; i++) { for (i = 0; i < stmt->ntab; i++)
{
/* See if already got it */ /* See if already got it */
char found = FALSE; char found = FALSE;
for (k = 0; k < conn->ntables; k++) {
if ( ! stricmp(conn->col_info[k]->name, ti[i]->name)) { for (k = 0; k < conn->ntables; k++)
{
if (!stricmp(conn->col_info[k]->name, ti[i]->name))
{
mylog("FOUND col_info table='%s'\n", ti[i]->name); mylog("FOUND col_info table='%s'\n", ti[i]->name);
found = TRUE; found = TRUE;
break; break;
} }
} }
if ( ! found) { if (!found)
{
mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name); mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);
result = SQLAllocStmt( stmt->hdbc, &hcol_stmt); result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
stmt->errormsg = "SQLAllocStmt failed in parse_statement for columns."; stmt->errormsg = "SQLAllocStmt failed in parse_statement for columns.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
...@@ -591,14 +676,17 @@ RETCODE result; ...@@ -591,14 +676,17 @@ RETCODE result;
ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0); ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0);
mylog(" Past SQLColumns\n"); mylog(" Past SQLColumns\n");
if (result == SQL_SUCCESS) { if (result == SQL_SUCCESS)
{
mylog(" Success\n"); mylog(" Success\n");
if ( ! (conn->ntables % COL_INCR)) { if (!(conn->ntables % COL_INCR))
{
mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables); 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 *)); conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *));
if ( ! conn->col_info) { if (!conn->col_info)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
...@@ -606,17 +694,22 @@ RETCODE result; ...@@ -606,17 +694,22 @@ RETCODE result;
mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables); mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables);
conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO)); conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO));
if ( ! conn->col_info[conn->ntables]) { if (!conn->col_info[conn->ntables])
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
/* Store the table name and the SQLColumns result structure */ /*
* Store the table name and the SQLColumns result
* structure
*/
strcpy(conn->col_info[conn->ntables]->name, ti[i]->name); strcpy(conn->col_info[conn->ntables]->name, ti[i]->name);
conn->col_info[conn->ntables]->result = col_stmt->result; conn->col_info[conn->ntables]->result = col_stmt->result;
/* The connection will now free the result structures, so make /*
sure that the statement doesn't free it * The connection will now free the result structures, so
* make sure that the statement doesn't free it
*/ */
col_stmt->result = NULL; col_stmt->result = NULL;
...@@ -625,7 +718,8 @@ RETCODE result; ...@@ -625,7 +718,8 @@ RETCODE result;
SQLFreeStmt(hcol_stmt, SQL_DROP); SQLFreeStmt(hcol_stmt, SQL_DROP);
mylog("Created col_info table='%s', ntables=%d\n", ti[i]->name, conn->ntables); mylog("Created col_info table='%s', ntables=%d\n", ti[i]->name, conn->ntables);
} }
else { else
{
SQLFreeStmt(hcol_stmt, SQL_DROP); SQLFreeStmt(hcol_stmt, SQL_DROP);
break; break;
} }
...@@ -645,34 +739,41 @@ RETCODE result; ...@@ -645,34 +739,41 @@ RETCODE result;
for (i = 0; i < stmt->nfld;) { for (i = 0; i < stmt->nfld;)
{
/* Dont worry about functions or quotes */ /* Dont worry about functions or quotes */
if (fi[i]->func || fi[i]->quote || fi[i]->numeric) { if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
{
i++; i++;
continue; continue;
} }
/* Stars get expanded to all fields in the table */ /* Stars get expanded to all fields in the table */
else if (fi[i]->name[0] == '*') { else if (fi[i]->name[0] == '*')
{
char do_all_tables; char do_all_tables;
int total_cols, old_size, need, cols; int total_cols,
old_size,
need,
cols;
mylog("expanding field %d\n", i); mylog("expanding field %d\n", i);
total_cols = 0; total_cols = 0;
if (fi[i]->ti) /* The star represents only the qualified table */ if (fi[i]->ti) /* The star represents only the qualified
* table */
total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result); total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result);
else { /* The star represents all tables */ else
{ /* The star represents all tables */
/* Calculate the total number of columns after expansion */ /* Calculate the total number of columns after expansion */
for (k = 0; k < stmt->ntab; k++) { for (k = 0; k < stmt->ntab; k++)
total_cols += QR_get_num_tuples(ti[k]->col_info->result); total_cols += QR_get_num_tuples(ti[k]->col_info->result);
} }
}
total_cols--; /* makes up for the star */ total_cols--; /* makes up for the star */
/* Allocate some more field pointers if necessary */ /* Allocate some more field pointers if necessary */
...@@ -680,21 +781,29 @@ RETCODE result; ...@@ -680,21 +781,29 @@ RETCODE result;
old_size = (stmt->nfld / FLD_INCR * FLD_INCR + FLD_INCR); old_size = (stmt->nfld / FLD_INCR * FLD_INCR + FLD_INCR);
need = total_cols - (old_size - stmt->nfld); need = total_cols - (old_size - stmt->nfld);
mylog("k=%d, total_cols=%d, old_size=%d, need=%d\n", k,total_cols,old_size,need); mylog("k=%d, total_cols=%d, old_size=%d, need=%d\n", k, total_cols, old_size, need);
if (need > 0) { if (need > 0)
{
int new_size = need / FLD_INCR * FLD_INCR + FLD_INCR; int new_size = need / FLD_INCR * FLD_INCR + FLD_INCR;
mylog("need more cols: new_size = %d\n", new_size); mylog("need more cols: new_size = %d\n", new_size);
fi = (FIELD_INFO **) realloc(fi, (old_size + new_size) * sizeof(FIELD_INFO *)); fi = (FIELD_INFO **) realloc(fi, (old_size + new_size) * sizeof(FIELD_INFO *));
if ( ! fi) { if (!fi)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
} }
/*------------------------------------------------------------- */ /*------------------------------------------------------------- */
/* copy any other fields (if there are any) up past the expansion */
for (j = stmt->nfld - 1; j > i; j--) { /*
* copy any other fields (if there are any) up past the
* expansion
*/
for (j = stmt->nfld - 1; j > i; j--)
{
mylog("copying field %d to %d\n", j, total_cols + j); mylog("copying field %d to %d\n", j, total_cols + j);
fi[total_cols + j] = fi[j]; fi[total_cols + j] = fi[j];
} }
...@@ -712,19 +821,23 @@ RETCODE result; ...@@ -712,19 +821,23 @@ RETCODE result;
do_all_tables = (fi[i]->ti ? FALSE : TRUE); do_all_tables = (fi[i]->ti ? FALSE : TRUE);
for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++) { for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)
{
TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti; TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
cols = QR_get_num_tuples(the_ti->col_info->result); cols = QR_get_num_tuples(the_ti->col_info->result);
for (n = 0; n < cols; n++) { for (n = 0; n < cols; n++)
{
mylog("creating field info: n=%d\n", n); mylog("creating field info: n=%d\n", n);
/* skip malloc (already did it for the Star) */ /* skip malloc (already did it for the Star) */
if (k > 0 || n > 0) { if (k > 0 || n > 0)
{
mylog("allocating field info at %d\n", n + i); mylog("allocating field info at %d\n", n + i);
fi[n + i] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO)); fi[n + i] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO));
if (fi[n + i] == NULL) { if (fi[n + i] == NULL)
{
stmt->parse_status = STMT_PARSE_FATAL; stmt->parse_status = STMT_PARSE_FATAL;
return FALSE; return FALSE;
} }
...@@ -747,22 +860,28 @@ RETCODE result; ...@@ -747,22 +860,28 @@ RETCODE result;
/*------------------------------------------------------------- */ /*------------------------------------------------------------- */
} }
/* We either know which table the field was in because it was qualified /*
with a table name or alias -OR- there was only 1 table. * We either know which table the field was in because it was
* qualified with a table name or alias -OR- there was only 1
* table.
*/ */
else if (fi[i]->ti) { else if (fi[i]->ti)
{
if ( ! searchColInfo(fi[i]->ti->col_info, fi[i])) if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
parse = FALSE; parse = FALSE;
i++; i++;
} }
/* Don't know the table -- search all tables in "from" list */ /* Don't know the table -- search all tables in "from" list */
else { else
{
parse = FALSE; parse = FALSE;
for (k = 0; k < stmt->ntab; k++) { for (k = 0; k < stmt->ntab; k++)
if ( searchColInfo(ti[k]->col_info, fi[i])) { {
if (searchColInfo(ti[k]->col_info, fi[i]))
{
fi[i]->ti = ti[k]; /* now know the table */ fi[i]->ti = ti[k]; /* now know the table */
parse = TRUE; parse = TRUE;
break; break;
...@@ -773,7 +892,7 @@ RETCODE result; ...@@ -773,7 +892,7 @@ RETCODE result;
} }
if ( ! parse) if (!parse)
stmt->parse_status = STMT_PARSE_INCOMPLETE; stmt->parse_status = STMT_PARSE_INCOMPLETE;
else else
stmt->parse_status = STMT_PARSE_COMPLETE; stmt->parse_status = STMT_PARSE_COMPLETE;
...@@ -782,4 +901,3 @@ RETCODE result; ...@@ -782,4 +901,3 @@ RETCODE result;
mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status); mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
return parse; return parse;
} }
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); 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 */ /* these are the types we support. all of the pgtype_ functions should */
...@@ -79,7 +79,7 @@ Int4 pgtypes_defined[] = { ...@@ -79,7 +79,7 @@ Int4 pgtypes_defined[] = {
/* These are NOW the SQL Types reported in SQLGetTypeInfo. */ /* These are NOW the SQL Types reported in SQLGetTypeInfo. */
Int2 sqlTypes [] = { Int2 sqlTypes[] = {
SQL_BIGINT, SQL_BIGINT,
/* SQL_BINARY, -- Commented out because VarBinary is more correct. */ /* SQL_BINARY, -- Commented out because VarBinary is more correct. */
SQL_BIT, SQL_BIT,
...@@ -102,11 +102,13 @@ Int2 sqlTypes [] = { ...@@ -102,11 +102,13 @@ Int2 sqlTypes [] = {
0 0
}; };
Int4 sqltype_to_pgtype(SWORD fSqlType) Int4
sqltype_to_pgtype(SWORD fSqlType)
{ {
Int4 pgType; Int4 pgType;
switch(fSqlType) { switch (fSqlType)
{
case SQL_BINARY: case SQL_BINARY:
pgType = PG_TYPE_BYTEA; pgType = PG_TYPE_BYTEA;
...@@ -192,142 +194,211 @@ Int4 pgType; ...@@ -192,142 +194,211 @@ Int4 pgType;
know. This allows for supporting know. This allows for supporting
types that are unknown. All other pg routines in here return a suitable default. types that are unknown. All other pg routines in here return a suitable default.
*/ */
Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) Int2
pgtype_to_sqltype(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_CHAR: case PG_TYPE_CHAR:
case PG_TYPE_CHAR2: case PG_TYPE_CHAR2:
case PG_TYPE_CHAR4: case PG_TYPE_CHAR4:
case PG_TYPE_CHAR8: case PG_TYPE_CHAR8:
case PG_TYPE_NAME: return SQL_CHAR; case PG_TYPE_NAME:return SQL_CHAR;
case PG_TYPE_BPCHAR: return SQL_CHAR; case PG_TYPE_BPCHAR:
return SQL_CHAR;
case PG_TYPE_VARCHAR: return SQL_VARCHAR; case PG_TYPE_VARCHAR:
return SQL_VARCHAR;
case PG_TYPE_TEXT: return globals.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; case PG_TYPE_TEXT:
return globals.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
case PG_TYPE_BYTEA: return SQL_VARBINARY; case PG_TYPE_BYTEA:
case PG_TYPE_LO: return SQL_LONGVARBINARY; return SQL_VARBINARY;
case PG_TYPE_LO:
return SQL_LONGVARBINARY;
case PG_TYPE_INT2: return SQL_SMALLINT; case PG_TYPE_INT2:
return SQL_SMALLINT;
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_XID: case PG_TYPE_XID:
case PG_TYPE_INT4: return SQL_INTEGER; case PG_TYPE_INT4:
return SQL_INTEGER;
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */ /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
case PG_TYPE_INT8: return SQL_CHAR; case PG_TYPE_INT8:
return SQL_CHAR;
case PG_TYPE_NUMERIC: return SQL_NUMERIC; case PG_TYPE_NUMERIC:
return SQL_NUMERIC;
case PG_TYPE_FLOAT4: return SQL_REAL; case PG_TYPE_FLOAT4:
case PG_TYPE_FLOAT8: return SQL_FLOAT; return SQL_REAL;
case PG_TYPE_DATE: return SQL_DATE; case PG_TYPE_FLOAT8:
case PG_TYPE_TIME: return SQL_TIME; return SQL_FLOAT;
case PG_TYPE_DATE:
return SQL_DATE;
case PG_TYPE_TIME:
return SQL_TIME;
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return SQL_TIMESTAMP; case PG_TYPE_TIMESTAMP:
case PG_TYPE_MONEY: return SQL_FLOAT; return SQL_TIMESTAMP;
case PG_TYPE_BOOL: return globals.bools_as_char ? SQL_CHAR : SQL_BIT; case PG_TYPE_MONEY:
return SQL_FLOAT;
case PG_TYPE_BOOL:
return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
default: default:
/* first, check to see if 'type' is in list. If not, look up with query. /*
Add oid, name to list. If it's already in list, just return. * first, check to see if 'type' is in list. If not, look up
* with query. Add oid, name to list. If it's already in
* list, just return.
*/ */
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */ if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
return SQL_LONGVARBINARY; return SQL_LONGVARBINARY;
return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
} }
} }
Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type) Int2
pgtype_to_ctype(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
case PG_TYPE_INT8: return SQL_C_CHAR; {
case PG_TYPE_NUMERIC: return SQL_C_CHAR; case PG_TYPE_INT8:return SQL_C_CHAR;
case PG_TYPE_INT2: return SQL_C_SSHORT; case PG_TYPE_NUMERIC:
return SQL_C_CHAR;
case PG_TYPE_INT2:
return SQL_C_SSHORT;
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_XID: case PG_TYPE_XID:
case PG_TYPE_INT4: return SQL_C_SLONG; case PG_TYPE_INT4:
case PG_TYPE_FLOAT4: return SQL_C_FLOAT; return SQL_C_SLONG;
case PG_TYPE_FLOAT8: return SQL_C_DOUBLE; case PG_TYPE_FLOAT4:
case PG_TYPE_DATE: return SQL_C_DATE; return SQL_C_FLOAT;
case PG_TYPE_TIME: return SQL_C_TIME; case PG_TYPE_FLOAT8:
return SQL_C_DOUBLE;
case PG_TYPE_DATE:
return SQL_C_DATE;
case PG_TYPE_TIME:
return SQL_C_TIME;
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return SQL_C_TIMESTAMP; case PG_TYPE_TIMESTAMP:
case PG_TYPE_MONEY: return SQL_C_FLOAT; return SQL_C_TIMESTAMP;
case PG_TYPE_BOOL: return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT; case PG_TYPE_MONEY:
return SQL_C_FLOAT;
case PG_TYPE_BOOL:
return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
case PG_TYPE_BYTEA: return SQL_C_BINARY; case PG_TYPE_BYTEA:
case PG_TYPE_LO: return SQL_C_BINARY; return SQL_C_BINARY;
case PG_TYPE_LO:
return SQL_C_BINARY;
default: default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */ if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
return SQL_C_BINARY; return SQL_C_BINARY;
return SQL_C_CHAR; return SQL_C_CHAR;
} }
} }
char *pgtype_to_name(StatementClass *stmt, Int4 type) char *
pgtype_to_name(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
case PG_TYPE_CHAR: return "char"; {
case PG_TYPE_CHAR2: return "char2"; case PG_TYPE_CHAR:return "char";
case PG_TYPE_CHAR4: return "char4"; case PG_TYPE_CHAR2:
case PG_TYPE_CHAR8: return "char8"; return "char2";
case PG_TYPE_INT8: return "int8"; case PG_TYPE_CHAR4:
case PG_TYPE_NUMERIC: return "numeric"; return "char4";
case PG_TYPE_VARCHAR: return "varchar"; case PG_TYPE_CHAR8:
case PG_TYPE_BPCHAR: return "char"; return "char8";
case PG_TYPE_TEXT: return "text"; case PG_TYPE_INT8:
case PG_TYPE_NAME: return "name"; return "int8";
case PG_TYPE_INT2: return "int2"; case PG_TYPE_NUMERIC:
case PG_TYPE_OID: return "oid"; return "numeric";
case PG_TYPE_INT4: return "int4"; case PG_TYPE_VARCHAR:
case PG_TYPE_FLOAT4: return "float4"; return "varchar";
case PG_TYPE_FLOAT8: return "float8"; case PG_TYPE_BPCHAR:
case PG_TYPE_DATE: return "date"; return "char";
case PG_TYPE_TIME: return "time"; case PG_TYPE_TEXT:
case PG_TYPE_ABSTIME: return "abstime"; return "text";
case PG_TYPE_DATETIME: return "datetime"; case PG_TYPE_NAME:
case PG_TYPE_TIMESTAMP: return "timestamp"; return "name";
case PG_TYPE_MONEY: return "money"; case PG_TYPE_INT2:
case PG_TYPE_BOOL: return "bool"; return "int2";
case PG_TYPE_BYTEA: return "bytea"; case PG_TYPE_OID:
return "oid";
case PG_TYPE_LO: return PG_TYPE_LO_NAME; case PG_TYPE_INT4:
return "int4";
case PG_TYPE_FLOAT4:
return "float4";
case PG_TYPE_FLOAT8:
return "float8";
case PG_TYPE_DATE:
return "date";
case PG_TYPE_TIME:
return "time";
case PG_TYPE_ABSTIME:
return "abstime";
case PG_TYPE_DATETIME:
return "datetime";
case PG_TYPE_TIMESTAMP:
return "timestamp";
case PG_TYPE_MONEY:
return "money";
case PG_TYPE_BOOL:
return "bool";
case PG_TYPE_BYTEA:
return "bytea";
case PG_TYPE_LO:
return PG_TYPE_LO_NAME;
default: default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */ if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
return PG_TYPE_LO_NAME; return PG_TYPE_LO_NAME;
/* "unknown" can actually be used in alter table because it is a real PG type! */ /*
* "unknown" can actually be used in alter table because it is
* a real PG type!
*/
return "unknown"; return "unknown";
} }
} }
static Int2 static Int2
getNumericScale(StatementClass *stmt, Int4 type, int col) getNumericScale(StatementClass * stmt, Int4 type, int col)
{ {
Int4 atttypmod; Int4 atttypmod;
QResultClass *result; QResultClass *result;
ColumnInfoClass *flds; ColumnInfoClass *flds;
mylog("getNumericScale: type=%d, col=%d, unknown = %d\n", type,col); mylog("getNumericScale: type=%d, col=%d, unknown = %d\n", type, col);
if (col < 0) if (col < 0)
return PG_NUMERIC_MAX_SCALE; return PG_NUMERIC_MAX_SCALE;
result = SC_get_Result(stmt); result = SC_get_Result(stmt);
/* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */ /*
if (stmt->manual_result) { * Manual Result Sets -- use assigned column width (i.e., from
* set_tuplefield_string)
*/
if (stmt->manual_result)
{
flds = result->fields; flds = result->fields;
if (flds) if (flds)
return flds->adtsize[col]; return flds->adtsize[col];
...@@ -336,30 +407,34 @@ mylog("getNumericScale: type=%d, col=%d, unknown = %d\n", type,col); ...@@ -336,30 +407,34 @@ mylog("getNumericScale: type=%d, col=%d, unknown = %d\n", type,col);
} }
atttypmod = QR_get_atttypmod(result, col); atttypmod = QR_get_atttypmod(result, col);
if ( atttypmod > -1 ) if (atttypmod > -1)
return (atttypmod & 0xffff); return (atttypmod & 0xffff);
else else
return ( QR_get_display_size(result, col) ? return (QR_get_display_size(result, col) ?
QR_get_display_size(result, col) : QR_get_display_size(result, col) :
PG_NUMERIC_MAX_SCALE); PG_NUMERIC_MAX_SCALE);
} }
static Int4 static Int4
getNumericPrecision(StatementClass *stmt, Int4 type, int col) getNumericPrecision(StatementClass * stmt, Int4 type, int col)
{ {
Int4 atttypmod; Int4 atttypmod;
QResultClass *result; QResultClass *result;
ColumnInfoClass *flds; ColumnInfoClass *flds;
mylog("getNumericPrecision: type=%d, col=%d, unknown = %d\n", type,col); mylog("getNumericPrecision: type=%d, col=%d, unknown = %d\n", type, col);
if (col < 0) if (col < 0)
return PG_NUMERIC_MAX_PRECISION; return PG_NUMERIC_MAX_PRECISION;
result = SC_get_Result(stmt); result = SC_get_Result(stmt);
/* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */ /*
if (stmt->manual_result) { * Manual Result Sets -- use assigned column width (i.e., from
* set_tuplefield_string)
*/
if (stmt->manual_result)
{
flds = result->fields; flds = result->fields;
if (flds) if (flds)
return flds->adtsize[col]; return flds->adtsize[col];
...@@ -368,25 +443,27 @@ mylog("getNumericPrecision: type=%d, col=%d, unknown = %d\n", type,col); ...@@ -368,25 +443,27 @@ mylog("getNumericPrecision: type=%d, col=%d, unknown = %d\n", type,col);
} }
atttypmod = QR_get_atttypmod(result, col); atttypmod = QR_get_atttypmod(result, col);
if ( atttypmod > -1 ) if (atttypmod > -1)
return (atttypmod >> 16) & 0xffff; return (atttypmod >> 16) & 0xffff;
else else
return ( QR_get_display_size(result, col) >= 0 ? return (QR_get_display_size(result, col) >= 0 ?
QR_get_display_size(result, col) : QR_get_display_size(result, col) :
PG_NUMERIC_MAX_PRECISION ); PG_NUMERIC_MAX_PRECISION);
} }
Int4 Int4
getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) getCharPrecision(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as)
{ {
int p = -1, maxsize; int p = -1,
QResultClass *result; maxsize;
ColumnInfoClass *flds; QResultClass *result;
ColumnInfoClass *flds;
mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unknown_size_as); mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as);
/* Assign Maximum size based on parameters */ /* Assign Maximum size based on parameters */
switch(type) { switch (type)
{
case PG_TYPE_TEXT: case PG_TYPE_TEXT:
if (globals.text_as_longvarchar) if (globals.text_as_longvarchar)
maxsize = globals.max_longvarchar_size; maxsize = globals.max_longvarchar_size;
...@@ -407,16 +484,21 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno ...@@ -407,16 +484,21 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno
break; break;
} }
/* Static Precision (i.e., the Maximum Precision of the datatype) /*
This has nothing to do with a result set. * Static Precision (i.e., the Maximum Precision of the datatype) This
* has nothing to do with a result set.
*/ */
if (col < 0) if (col < 0)
return maxsize; return maxsize;
result = SC_get_Result(stmt); result = SC_get_Result(stmt);
/* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */ /*
if (stmt->manual_result) { * Manual Result Sets -- use assigned column width (i.e., from
* set_tuplefield_string)
*/
if (stmt->manual_result)
{
flds = result->fields; flds = result->fields;
if (flds) if (flds)
return flds->adtsize[col]; return flds->adtsize[col];
...@@ -428,7 +510,8 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno ...@@ -428,7 +510,8 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno
if (QR_get_atttypmod(result, col) > -1) if (QR_get_atttypmod(result, col) > -1)
return QR_get_atttypmod(result, col); return QR_get_atttypmod(result, col);
if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST) { if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
{
p = QR_get_display_size(result, col); p = QR_get_display_size(result, col);
mylog("getCharPrecision: LONGEST: p = %d\n", p); mylog("getCharPrecision: LONGEST: p = %d\n", p);
} }
...@@ -445,47 +528,65 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno ...@@ -445,47 +528,65 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno
If col >= 0, then will attempt to get the info from the result set. If col >= 0, then will attempt to get the info from the result set.
This is used for functions SQLDescribeCol and SQLColAttributes. This is used for functions SQLDescribeCol and SQLColAttributes.
*/ */
Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) Int4
pgtype_precision(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as)
{ {
switch(type) { switch (type)
{
case PG_TYPE_CHAR: return 1; case PG_TYPE_CHAR:return 1;
case PG_TYPE_CHAR2: return 2; case PG_TYPE_CHAR2:
case PG_TYPE_CHAR4: return 4; return 2;
case PG_TYPE_CHAR8: return 8; case PG_TYPE_CHAR4:
return 4;
case PG_TYPE_CHAR8:
return 8;
case PG_TYPE_NAME: return NAME_FIELD_SIZE; case PG_TYPE_NAME:
return NAME_FIELD_SIZE;
case PG_TYPE_INT2: return 5; case PG_TYPE_INT2:
return 5;
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_XID: case PG_TYPE_XID:
case PG_TYPE_INT4: return 10; case PG_TYPE_INT4:
return 10;
case PG_TYPE_INT8: return 19; /* signed */ case PG_TYPE_INT8:
return 19; /* signed */
case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col); case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col);
case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY: return 7; case PG_TYPE_MONEY:
return 7;
case PG_TYPE_FLOAT8: return 15; case PG_TYPE_FLOAT8:
return 15;
case PG_TYPE_DATE: return 10; case PG_TYPE_DATE:
case PG_TYPE_TIME: return 8; return 10;
case PG_TYPE_TIME:
return 8;
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return 19; case PG_TYPE_TIMESTAMP:
return 19;
case PG_TYPE_BOOL: return 1; case PG_TYPE_BOOL:
return 1;
case PG_TYPE_LO: return SQL_NO_TOTAL; case PG_TYPE_LO:
return SQL_NO_TOTAL;
default: default:
if (type == stmt->hdbc->lobj_type) /* hack until permanent type is available */ if (type == stmt->hdbc->lobj_type) /* hack until permanent
* type is available */
return SQL_NO_TOTAL; return SQL_NO_TOTAL;
/* Handle Character types and unknown types */ /* Handle Character types and unknown types */
...@@ -493,26 +594,35 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno ...@@ -493,26 +594,35 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno
} }
} }
Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) Int4
pgtype_display_size(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as)
{ {
switch(type) { switch (type)
case PG_TYPE_INT2: return 6; {
case PG_TYPE_INT2:return 6;
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_XID: return 10; case PG_TYPE_XID:
return 10;
case PG_TYPE_INT4: return 11; case PG_TYPE_INT4:
return 11;
case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */ case PG_TYPE_INT8:
return 20; /* signed: 19 digits + sign */
case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col) + 2; case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col) + 2;
case PG_TYPE_MONEY: return 15; /* ($9,999,999.99) */ case PG_TYPE_MONEY:
return 15; /* ($9,999,999.99) */
case PG_TYPE_FLOAT4: return 13; case PG_TYPE_FLOAT4:
return 13;
case PG_TYPE_FLOAT8: return 22; case PG_TYPE_FLOAT8:
return 22;
/* Character types use regular precision */ /* Character types use regular precision */
default: default:
...@@ -523,32 +633,41 @@ Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_un ...@@ -523,32 +633,41 @@ Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_un
/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will /* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
override this length with the atttypmod length from pg_attribute override this length with the atttypmod length from pg_attribute
*/ */
Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) Int4
pgtype_length(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as)
{ {
switch(type) { switch (type)
{
case PG_TYPE_INT2: return 2; case PG_TYPE_INT2:return 2;
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_XID: case PG_TYPE_XID:
case PG_TYPE_INT4: return 4; case PG_TYPE_INT4:
return 4;
case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */ case PG_TYPE_INT8:
return 20; /* signed: 19 digits + sign */
case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col) + 2; case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col) + 2;
case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY: return 4; case PG_TYPE_MONEY:
return 4;
case PG_TYPE_FLOAT8: return 8; case PG_TYPE_FLOAT8:
return 8;
case PG_TYPE_DATE: case PG_TYPE_DATE:
case PG_TYPE_TIME: return 6; case PG_TYPE_TIME:
return 6;
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return 16; case PG_TYPE_TIMESTAMP:
return 16;
/* Character types (and NUMERIC) use the default precision */ /* Character types (and NUMERIC) use the default precision */
...@@ -557,9 +676,11 @@ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_ ...@@ -557,9 +676,11 @@ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_
} }
} }
Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col) Int2
pgtype_scale(StatementClass * stmt, Int4 type, int col)
{ {
switch(type) { switch (type)
{
case PG_TYPE_INT2: case PG_TYPE_INT2:
case PG_TYPE_OID: case PG_TYPE_OID:
...@@ -571,21 +692,28 @@ Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col) ...@@ -571,21 +692,28 @@ Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col)
case PG_TYPE_MONEY: case PG_TYPE_MONEY:
case PG_TYPE_BOOL: 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_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return 0; case PG_TYPE_TIMESTAMP:return 0;
case PG_TYPE_NUMERIC: return getNumericScale(stmt,type,col); case PG_TYPE_NUMERIC:
return getNumericScale(stmt, type, col);
default: return -1; default:
return -1;
} }
} }
Int2 pgtype_radix(StatementClass *stmt, Int4 type) Int2
pgtype_radix(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_INT2: case PG_TYPE_INT2:
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_INT4: case PG_TYPE_INT4:
...@@ -593,20 +721,24 @@ Int2 pgtype_radix(StatementClass *stmt, Int4 type) ...@@ -593,20 +721,24 @@ Int2 pgtype_radix(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY: case PG_TYPE_MONEY:
case PG_TYPE_FLOAT8: return 10; case PG_TYPE_FLOAT8:return 10;
default: return -1; default:
return -1;
} }
} }
Int2 pgtype_nullable(StatementClass *stmt, Int4 type) Int2
pgtype_nullable(StatementClass * stmt, Int4 type)
{ {
return SQL_NULLABLE; /* everything should be nullable */ return SQL_NULLABLE; /* everything should be nullable */
} }
Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type) Int2
pgtype_auto_increment(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_INT2: case PG_TYPE_INT2:
case PG_TYPE_OID: case PG_TYPE_OID:
...@@ -623,15 +755,18 @@ Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type) ...@@ -623,15 +755,18 @@ Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type)
case PG_TYPE_TIME: case PG_TYPE_TIME:
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return FALSE; case PG_TYPE_TIMESTAMP:return FALSE;
default: return -1; default:
return -1;
} }
} }
Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type) Int2
pgtype_case_sensitive(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_CHAR: case PG_TYPE_CHAR:
case PG_TYPE_CHAR2: case PG_TYPE_CHAR2:
...@@ -641,23 +776,29 @@ Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type) ...@@ -641,23 +776,29 @@ Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type)
case PG_TYPE_VARCHAR: case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR: case PG_TYPE_BPCHAR:
case PG_TYPE_TEXT: case PG_TYPE_TEXT:
case PG_TYPE_NAME: return TRUE; case PG_TYPE_NAME:return TRUE;
default: return FALSE; default:
return FALSE;
} }
} }
Int2 pgtype_money(StatementClass *stmt, Int4 type) Int2
pgtype_money(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
case PG_TYPE_MONEY: return TRUE; {
default: return FALSE; case PG_TYPE_MONEY:return TRUE;
default:
return FALSE;
} }
} }
Int2 pgtype_searchable(StatementClass *stmt, Int4 type) Int2
pgtype_searchable(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_CHAR: case PG_TYPE_CHAR:
case PG_TYPE_CHAR2: case PG_TYPE_CHAR2:
case PG_TYPE_CHAR4: case PG_TYPE_CHAR4:
...@@ -666,17 +807,20 @@ Int2 pgtype_searchable(StatementClass *stmt, Int4 type) ...@@ -666,17 +807,20 @@ Int2 pgtype_searchable(StatementClass *stmt, Int4 type)
case PG_TYPE_VARCHAR: case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR: case PG_TYPE_BPCHAR:
case PG_TYPE_TEXT: case PG_TYPE_TEXT:
case PG_TYPE_NAME: return SQL_SEARCHABLE; case PG_TYPE_NAME:return SQL_SEARCHABLE;
default: return SQL_ALL_EXCEPT_LIKE; default:
return SQL_ALL_EXCEPT_LIKE;
} }
} }
Int2 pgtype_unsigned(StatementClass *stmt, Int4 type) Int2
pgtype_unsigned(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_OID: case PG_TYPE_OID:
case PG_TYPE_XID: return TRUE; case PG_TYPE_XID:return TRUE;
case PG_TYPE_INT2: case PG_TYPE_INT2:
case PG_TYPE_INT4: case PG_TYPE_INT4:
...@@ -684,15 +828,19 @@ Int2 pgtype_unsigned(StatementClass *stmt, Int4 type) ...@@ -684,15 +828,19 @@ Int2 pgtype_unsigned(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT4:
case PG_TYPE_FLOAT8: case PG_TYPE_FLOAT8:
case PG_TYPE_MONEY: return FALSE; case PG_TYPE_MONEY:
return FALSE;
default: return -1; default:
return -1;
} }
} }
char *pgtype_literal_prefix(StatementClass *stmt, Int4 type) char *
pgtype_literal_prefix(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_INT2: case PG_TYPE_INT2:
case PG_TYPE_OID: case PG_TYPE_OID:
...@@ -702,15 +850,18 @@ char *pgtype_literal_prefix(StatementClass *stmt, Int4 type) ...@@ -702,15 +850,18 @@ char *pgtype_literal_prefix(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT4:
case PG_TYPE_FLOAT8: case PG_TYPE_FLOAT8:
case PG_TYPE_MONEY: return NULL; case PG_TYPE_MONEY:return NULL;
default: return "'"; default:
return "'";
} }
} }
char *pgtype_literal_suffix(StatementClass *stmt, Int4 type) char *
pgtype_literal_suffix(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_INT2: case PG_TYPE_INT2:
case PG_TYPE_OID: case PG_TYPE_OID:
...@@ -720,27 +871,33 @@ char *pgtype_literal_suffix(StatementClass *stmt, Int4 type) ...@@ -720,27 +871,33 @@ char *pgtype_literal_suffix(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT4:
case PG_TYPE_FLOAT8: case PG_TYPE_FLOAT8:
case PG_TYPE_MONEY: return NULL; case PG_TYPE_MONEY:return NULL;
default: return "'"; default:
return "'";
} }
} }
char *pgtype_create_params(StatementClass *stmt, Int4 type) char *
pgtype_create_params(StatementClass * stmt, Int4 type)
{ {
switch(type) { switch (type)
{
case PG_TYPE_CHAR: case PG_TYPE_CHAR:
case PG_TYPE_VARCHAR: return "max. length"; case PG_TYPE_VARCHAR:return "max. length";
default: return NULL; default:
return NULL;
} }
} }
Int2 sqltype_to_default_ctype(Int2 sqltype) Int2
sqltype_to_default_ctype(Int2 sqltype)
{ {
/* from the table on page 623 of ODBC 2.0 Programmer's Reference */ /* from the table on page 623 of ODBC 2.0 Programmer's Reference */
/* (Appendix D) */ /* (Appendix D) */
switch(sqltype) { switch (sqltype)
{
case SQL_CHAR: case SQL_CHAR:
case SQL_VARCHAR: case SQL_VARCHAR:
case SQL_LONGVARCHAR: case SQL_LONGVARCHAR:
...@@ -786,4 +943,3 @@ Int2 sqltype_to_default_ctype(Int2 sqltype) ...@@ -786,4 +943,3 @@ Int2 sqltype_to_default_ctype(Int2 sqltype)
return SQL_C_CHAR; return SQL_C_CHAR;
} }
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#if 0 #if 0
#define PG_TYPE_LO ???? /* waiting for permanent type */ #define PG_TYPE_LO ????/* waiting for permanent type */
#endif #endif
#define PG_TYPE_BOOL 16 #define PG_TYPE_BOOL 16
...@@ -71,28 +71,27 @@ extern Int2 sqlTypes[]; ...@@ -71,28 +71,27 @@ extern Int2 sqlTypes[];
Int4 sqltype_to_pgtype(Int2 fSqlType); Int4 sqltype_to_pgtype(Int2 fSqlType);
Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type); Int2 pgtype_to_sqltype(StatementClass * stmt, Int4 type);
Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type); Int2 pgtype_to_ctype(StatementClass * stmt, Int4 type);
char *pgtype_to_name(StatementClass *stmt, Int4 type); char *pgtype_to_name(StatementClass * stmt, Int4 type);
/* These functions can use static numbers or result sets(col parameter) */ /* These functions can use static numbers or result sets(col parameter) */
Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); Int4 pgtype_precision(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as);
Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); Int4 pgtype_display_size(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as);
Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); Int4 pgtype_length(StatementClass * stmt, Int4 type, int col, int handle_unknown_size_as);
Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col); Int2 pgtype_scale(StatementClass * stmt, Int4 type, int col);
Int2 pgtype_radix(StatementClass *stmt, Int4 type); Int2 pgtype_radix(StatementClass * stmt, Int4 type);
Int2 pgtype_nullable(StatementClass *stmt, Int4 type); Int2 pgtype_nullable(StatementClass * stmt, Int4 type);
Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type); Int2 pgtype_auto_increment(StatementClass * stmt, Int4 type);
Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type); Int2 pgtype_case_sensitive(StatementClass * stmt, Int4 type);
Int2 pgtype_money(StatementClass *stmt, Int4 type); Int2 pgtype_money(StatementClass * stmt, Int4 type);
Int2 pgtype_searchable(StatementClass *stmt, Int4 type); Int2 pgtype_searchable(StatementClass * stmt, Int4 type);
Int2 pgtype_unsigned(StatementClass *stmt, Int4 type); Int2 pgtype_unsigned(StatementClass * stmt, Int4 type);
char *pgtype_literal_prefix(StatementClass *stmt, Int4 type); char *pgtype_literal_prefix(StatementClass * stmt, Int4 type);
char *pgtype_literal_suffix(StatementClass *stmt, Int4 type); char *pgtype_literal_suffix(StatementClass * stmt, Int4 type);
char *pgtype_create_params(StatementClass *stmt, Int4 type); char *pgtype_create_params(StatementClass * stmt, Int4 type);
Int2 sqltype_to_default_ctype(Int2 sqltype); Int2 sqltype_to_default_ctype(Int2 sqltype);
#endif #endif
...@@ -38,24 +38,27 @@ RETCODE SQL_API SQLDummyOrdinal(void); ...@@ -38,24 +38,27 @@ RETCODE SQL_API SQLDummyOrdinal(void);
HINSTANCE NEAR s_hModule; /* Saved module handle. */ HINSTANCE NEAR s_hModule; /* Saved module handle. */
/* This is where the Driver Manager attaches to this Driver */ /* This is where the Driver Manager attaches to this Driver */
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) BOOL WINAPI
DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{ {
WORD wVersionRequested; WORD wVersionRequested;
WSADATA wsaData; WSADATA wsaData;
switch (ul_reason_for_call) { switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
s_hModule = hInst; /* Save for dialog boxes */ s_hModule = hInst; /* Save for dialog boxes */
/* Load the WinSock Library */ /* Load the WinSock Library */
wVersionRequested = MAKEWORD(1, 1); wVersionRequested = MAKEWORD(1, 1);
if ( WSAStartup(wVersionRequested, &wsaData)) if (WSAStartup(wVersionRequested, &wsaData))
return FALSE; return FALSE;
/* Verify that this is the minimum version of WinSock */ /* Verify that this is the minimum version of WinSock */
if ( LOBYTE( wsaData.wVersion ) != 1 || if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) { HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup(); WSACleanup();
return FALSE; return FALSE;
...@@ -134,8 +137,8 @@ _fini(void) ...@@ -134,8 +137,8 @@ _fini(void)
Driver Manager do this. Also, the ordinal values of the Driver Manager do this. Also, the ordinal values of the
functions must match the value of fFunction in SQLGetFunctions() functions must match the value of fFunction in SQLGetFunctions()
*/ */
RETCODE SQL_API SQLDummyOrdinal(void) RETCODE SQL_API
SQLDummyOrdinal(void)
{ {
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
* $Id: psqlodbc.h,v 1.31 2001/02/10 06:57:53 momjian Exp $ * $Id: psqlodbc.h,v 1.32 2001/02/10 07:01:19 momjian Exp $
*/ */
#ifndef __PSQLODBC_H__ #ifndef __PSQLODBC_H__
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define UInt2 unsigned short #define UInt2 unsigned short
typedef float SFLOAT; typedef float SFLOAT;
typedef double SDOUBLE; typedef double SDOUBLE;
#else #else
#define Int4 int #define Int4 int
#define UInt4 unsigned int #define UInt4 unsigned int
...@@ -54,14 +55,18 @@ typedef UInt4 Oid; ...@@ -54,14 +55,18 @@ typedef UInt4 Oid;
#define BLCKSZ 4096 #define BLCKSZ 4096
#endif #endif
#define MAX_MESSAGE_LEN 65536 /* This puts a limit on query size but I don't */ #define MAX_MESSAGE_LEN 65536 /* This puts a limit on
* query size but I don't */
/* see an easy way round this - DJP 24-1-2001 */ /* see an easy way round this - DJP 24-1-2001 */
#define MAX_CONNECT_STRING 4096 #define MAX_CONNECT_STRING 4096
#define ERROR_MSG_LENGTH 4096 #define ERROR_MSG_LENGTH 4096
#define FETCH_MAX 100 /* default number of rows to cache for declare/fetch */ #define FETCH_MAX 100 /* default number of rows to cache
* for declare/fetch */
#define TUPLE_MALLOC_INC 100 #define TUPLE_MALLOC_INC 100
#define SOCK_BUFFER_SIZE 4096 /* default socket buffer size */ #define SOCK_BUFFER_SIZE 4096 /* default socket buffer
#define MAX_CONNECTIONS 128 /* conns per environment (arbitrary) */ * size */
#define MAX_CONNECTIONS 128 /* conns per environment
* (arbitrary) */
#define MAX_FIELDS 512 #define MAX_FIELDS 512
#define BYTELEN 8 #define BYTELEN 8
#define VARHDRSZ sizeof(Int4) #define VARHDRSZ sizeof(Int4)
...@@ -72,7 +77,8 @@ typedef UInt4 Oid; ...@@ -72,7 +77,8 @@ typedef UInt4 Oid;
/* Registry length limits */ /* Registry length limits */
#define LARGE_REGISTRY_LEN 4096 /* used for special cases */ #define LARGE_REGISTRY_LEN 4096 /* used for special cases */
#define MEDIUM_REGISTRY_LEN 256 /* normal size for user,database,etc. */ #define MEDIUM_REGISTRY_LEN 256 /* normal size for
* user,database,etc. */
#define SMALL_REGISTRY_LEN 10 /* for 1/0 settings */ #define SMALL_REGISTRY_LEN 10 /* for 1/0 settings */
...@@ -83,8 +89,10 @@ typedef UInt4 Oid; ...@@ -83,8 +89,10 @@ typedef UInt4 Oid;
/* Info limits */ /* Info limits */
#define MAX_INFO_STRING 128 #define MAX_INFO_STRING 128
#define MAX_KEYPARTS 20 #define MAX_KEYPARTS 20
#define MAX_KEYLEN 512 /* max key of the form "date+outlet+invoice" */ #define MAX_KEYLEN 512 /* max key of the form
#define MAX_ROW_SIZE 0 /* Unlimited rowsize with the Tuple Toaster */ * "date+outlet+invoice" */
#define MAX_ROW_SIZE 0 /* Unlimited rowsize with the Tuple
* Toaster */
#define MAX_STATEMENT_LEN 0 /* Unlimited statement size with 7.0 */ #define MAX_STATEMENT_LEN 0 /* Unlimited statement size with 7.0 */
/* Previously, numerous query strings were defined of length MAX_STATEMENT_LEN */ /* Previously, numerous query strings were defined of length MAX_STATEMENT_LEN */
...@@ -120,7 +128,8 @@ typedef struct GlobalValues_ ...@@ -120,7 +128,8 @@ typedef struct GlobalValues_
char disable_optimizer; char disable_optimizer;
char ksqo; char ksqo;
char unique_index; char unique_index;
char onlyread; /* readonly is reserved on Digital C++ compiler */ char onlyread; /* readonly is reserved on Digital C++
* compiler */
char use_declarefetch; char use_declarefetch;
char text_as_longvarchar; char text_as_longvarchar;
char unknowns_as_longvarchar; char unknowns_as_longvarchar;
...@@ -130,15 +139,18 @@ typedef struct GlobalValues_ ...@@ -130,15 +139,18 @@ typedef struct GlobalValues_
char cancel_as_freestmt; char cancel_as_freestmt;
char extra_systable_prefixes[MEDIUM_REGISTRY_LEN]; char extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
char conn_settings[LARGE_REGISTRY_LEN]; char conn_settings[LARGE_REGISTRY_LEN];
/* Protocol is not used anymore, but kept in case
* it is useful in the future. bjm 2001-02-10 /*
* Protocol is not used anymore, but kept in case it is useful in the
* future. bjm 2001-02-10
*/ */
char protocol[SMALL_REGISTRY_LEN]; char protocol[SMALL_REGISTRY_LEN];
FILE* mylogFP; FILE *mylogFP;
FILE* qlogFP; FILE *qlogFP;
} GLOBAL_VALUES; } GLOBAL_VALUES;
typedef struct StatementOptions_ { typedef struct StatementOptions_
{
int maxRows; int maxRows;
int maxLength; int maxLength;
int rowset_size; int rowset_size;
...@@ -146,26 +158,32 @@ typedef struct StatementOptions_ { ...@@ -146,26 +158,32 @@ typedef struct StatementOptions_ {
int cursor_type; int cursor_type;
int scroll_concurrency; int scroll_concurrency;
int retrieve_data; int retrieve_data;
int bind_size; /* size of each structure if using Row Binding */ int bind_size; /* size of each structure if using Row
* Binding */
int use_bookmarks; int use_bookmarks;
} StatementOptions; } StatementOptions;
/* Used to pass extra query info to send_query */ /* Used to pass extra query info to send_query */
typedef struct QueryInfo_ { typedef struct QueryInfo_
{
int row_size; int row_size;
QResultClass *result_in; QResultClass *result_in;
char *cursor; char *cursor;
} QueryInfo; } QueryInfo;
#define PG_TYPE_LO -999 /* hack until permanent type available */ #define PG_TYPE_LO -999 /* hack until permanent type
* available */
#define PG_TYPE_LO_NAME "lo" #define PG_TYPE_LO_NAME "lo"
#define OID_ATTNUM -2 /* the attnum in pg_index of the oid */ #define OID_ATTNUM -2 /* the attnum in pg_index of the
* oid */
/* sizes */ /* sizes */
#define TEXT_FIELD_SIZE 8190 /* size of text fields (not including null term) */ #define TEXT_FIELD_SIZE 8190 /* size of text fields (not
* including null term) */
#define NAME_FIELD_SIZE 32 /* size of name fields */ #define NAME_FIELD_SIZE 32 /* size of name fields */
#define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not including null term) */ #define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not
* including null term) */
#define PG_NUMERIC_MAX_PRECISION 1000 #define PG_NUMERIC_MAX_PRECISION 1000
#define PG_NUMERIC_MAX_SCALE 1000 #define PG_NUMERIC_MAX_SCALE 1000
......
...@@ -34,12 +34,12 @@ extern GLOBAL_VALUES globals; ...@@ -34,12 +34,12 @@ extern GLOBAL_VALUES globals;
/* Used for building a Manual Result only */ /* Used for building a Manual Result only */
/* All info functions call this function to create the manual result set. */ /* All info functions call this function to create the manual result set. */
void void
QR_set_num_fields(QResultClass *self, int new_num_fields) QR_set_num_fields(QResultClass * self, int new_num_fields)
{ {
mylog("in QR_set_num_fields\n"); mylog("in QR_set_num_fields\n");
CI_set_num_fields(self->fields, new_num_fields); CI_set_num_fields(self->fields, new_num_fields);
if(self->manual_tuples) if (self->manual_tuples)
TL_Destructor(self->manual_tuples); TL_Destructor(self->manual_tuples);
self->manual_tuples = TL_Constructor(new_num_fields); self->manual_tuples = TL_Constructor(new_num_fields);
...@@ -48,25 +48,25 @@ QR_set_num_fields(QResultClass *self, int new_num_fields) ...@@ -48,25 +48,25 @@ QR_set_num_fields(QResultClass *self, int new_num_fields)
} }
void void
QR_set_position(QResultClass *self, int pos) QR_set_position(QResultClass * self, int pos)
{ {
self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields); self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields);
} }
void void
QR_set_cache_size(QResultClass *self, int cache_size) QR_set_cache_size(QResultClass * self, int cache_size)
{ {
self->cache_size = cache_size; self->cache_size = cache_size;
} }
void void
QR_set_rowset_size(QResultClass *self, int rowset_size) QR_set_rowset_size(QResultClass * self, int rowset_size)
{ {
self->rowset_size = rowset_size; self->rowset_size = rowset_size;
} }
void void
QR_inc_base(QResultClass *self, int base_inc) QR_inc_base(QResultClass * self, int base_inc)
{ {
self->base += base_inc; self->base += base_inc;
} }
...@@ -78,16 +78,18 @@ QR_inc_base(QResultClass *self, int base_inc) ...@@ -78,16 +78,18 @@ QR_inc_base(QResultClass *self, int base_inc)
QResultClass * QResultClass *
QR_Constructor(void) QR_Constructor(void)
{ {
QResultClass *rv; QResultClass *rv;
mylog("in QR_Constructor\n"); mylog("in QR_Constructor\n");
rv = (QResultClass *) malloc(sizeof(QResultClass)); rv = (QResultClass *) malloc(sizeof(QResultClass));
if (rv != NULL) { if (rv != NULL)
{
rv->status = PGRES_EMPTY_QUERY; rv->status = PGRES_EMPTY_QUERY;
/* construct the column info */ /* construct the column info */
if ( ! (rv->fields = CI_Constructor())) { if (!(rv->fields = CI_Constructor()))
{
free(rv); free(rv);
return NULL; return NULL;
} }
...@@ -116,7 +118,7 @@ QResultClass *rv; ...@@ -116,7 +118,7 @@ QResultClass *rv;
} }
void void
QR_Destructor(QResultClass *self) QR_Destructor(QResultClass * self)
{ {
mylog("QResult: in DESTRUCTOR\n"); mylog("QResult: in DESTRUCTOR\n");
...@@ -154,7 +156,7 @@ QR_Destructor(QResultClass *self) ...@@ -154,7 +156,7 @@ QR_Destructor(QResultClass *self)
} }
void void
QR_set_command(QResultClass *self, char *msg) QR_set_command(QResultClass * self, char *msg)
{ {
if (self->command) if (self->command)
free(self->command); free(self->command);
...@@ -163,7 +165,7 @@ QR_set_command(QResultClass *self, char *msg) ...@@ -163,7 +165,7 @@ QR_set_command(QResultClass *self, char *msg)
} }
void void
QR_set_notice(QResultClass *self, char *msg) QR_set_notice(QResultClass * self, char *msg)
{ {
if (self->notice) if (self->notice)
free(self->notice); free(self->notice);
...@@ -172,26 +174,31 @@ QR_set_notice(QResultClass *self, char *msg) ...@@ -172,26 +174,31 @@ QR_set_notice(QResultClass *self, char *msg)
} }
void void
QR_free_memory(QResultClass *self) QR_free_memory(QResultClass * self)
{ {
register int lf, row; register int lf,
register TupleField *tuple = self->backend_tuples; row;
int fcount = self->fcount; register TupleField *tuple = self->backend_tuples;
int num_fields = self->num_fields; int fcount = self->fcount;
int num_fields = self->num_fields;
mylog("QResult: free memory in, fcount=%d\n", fcount); mylog("QResult: free memory in, fcount=%d\n", fcount);
if ( self->backend_tuples) { if (self->backend_tuples)
{
for (row = 0; row < fcount; row++) { for (row = 0; row < fcount; row++)
{
mylog("row = %d, num_fields = %d\n", row, num_fields); mylog("row = %d, num_fields = %d\n", row, num_fields);
for (lf=0; lf < num_fields; lf++) { for (lf = 0; lf < num_fields; lf++)
if (tuple[lf].value != NULL) { {
if (tuple[lf].value != NULL)
{
mylog("free [lf=%d] %u\n", lf, tuple[lf].value); mylog("free [lf=%d] %u\n", lf, tuple[lf].value);
free(tuple[lf].value); free(tuple[lf].value);
} }
} }
tuple += num_fields; /* next row */ tuple += num_fields;/* next row */
} }
free(self->backend_tuples); free(self->backend_tuples);
...@@ -205,25 +212,28 @@ int num_fields = self->num_fields; ...@@ -205,25 +212,28 @@ int num_fields = self->num_fields;
/* This function is called by send_query() */ /* This function is called by send_query() */
char char
QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor) QR_fetch_tuples(QResultClass * self, ConnectionClass * conn, char *cursor)
{ {
int tuple_size; int tuple_size;
/* If called from send_query the first time (conn != NULL), */ /* If called from send_query the first time (conn != NULL), */
/* then set the inTuples state, */ /* then set the inTuples state, */
/* and read the tuples. If conn is NULL, */ /* and read the tuples. If conn is NULL, */
/* it implies that we are being called from next_tuple(), */ /* it implies that we are being called from next_tuple(), */
/* like to get more rows so don't call next_tuple again! */ /* like to get more rows so don't call next_tuple again! */
if (conn != NULL) { if (conn != NULL)
{
self->conn = conn; self->conn = conn;
mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor==NULL)?"":cursor, self->cursor); mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor == NULL) ? "" : cursor, self->cursor);
if (self->cursor) if (self->cursor)
free(self->cursor); free(self->cursor);
if ( globals.use_declarefetch) { if (globals.use_declarefetch)
if (! cursor || cursor[0] == '\0') { {
if (!cursor || cursor[0] == '\0')
{
self->status = PGRES_INTERNAL_ERROR; self->status = PGRES_INTERNAL_ERROR;
QR_set_message(self, "Internal Error -- no cursor for fetch"); QR_set_message(self, "Internal Error -- no cursor for fetch");
return FALSE; return FALSE;
...@@ -233,11 +243,13 @@ int tuple_size; ...@@ -233,11 +243,13 @@ int tuple_size;
/* Read the field attributes. */ /* Read the field attributes. */
/* $$$$ Should do some error control HERE! $$$$ */ /* $$$$ Should do some error control HERE! $$$$ */
if ( CI_read_fields(self->fields, self->conn)) { if (CI_read_fields(self->fields, self->conn))
{
self->status = PGRES_FIELDS_OK; self->status = PGRES_FIELDS_OK;
self->num_fields = CI_get_num_fields(self->fields); self->num_fields = CI_get_num_fields(self->fields);
} }
else { else
{
self->status = PGRES_BAD_RESPONSE; self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Error reading field information"); QR_set_message(self, "Error reading field information");
return FALSE; return FALSE;
...@@ -253,7 +265,8 @@ int tuple_size; ...@@ -253,7 +265,8 @@ int tuple_size;
/* allocate memory for the tuple cache */ /* allocate memory for the tuple cache */
mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size); mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size); self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
if ( ! self->backend_tuples) { if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Could not get memory for tuple cache."); QR_set_message(self, "Could not get memory for tuple cache.");
return FALSE; return FALSE;
...@@ -263,18 +276,20 @@ int tuple_size; ...@@ -263,18 +276,20 @@ int tuple_size;
/* Force a read to occur in next_tuple */ /* Force a read to occur in next_tuple */
self->fcount = tuple_size+1; self->fcount = tuple_size + 1;
self->fetch_count = tuple_size+1; self->fetch_count = tuple_size + 1;
self->base = 0; self->base = 0;
return QR_next_tuple(self); return QR_next_tuple(self);
} }
else { else
{
/* Always have to read the field attributes. */ /* Always have to read the field attributes. */
/* But we dont have to reallocate memory for them! */ /* But we dont have to reallocate memory for them! */
if ( ! CI_read_fields(NULL, self->conn)) { if (!CI_read_fields(NULL, self->conn))
{
self->status = PGRES_BAD_RESPONSE; self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Error reading field information"); QR_set_message(self, "Error reading field information");
return FALSE; return FALSE;
...@@ -286,11 +301,12 @@ int tuple_size; ...@@ -286,11 +301,12 @@ int tuple_size;
/* Close the cursor and end the transaction (if no cursors left) */ /* Close the cursor and end the transaction (if no cursors left) */
/* We only close cursor/end the transaction if a cursor was used. */ /* We only close cursor/end the transaction if a cursor was used. */
int int
QR_close(QResultClass *self) QR_close(QResultClass * self)
{ {
QResultClass *res; QResultClass *res;
if (globals.use_declarefetch && self->conn && self->cursor) { if (globals.use_declarefetch && self->conn && self->cursor)
{
char buf[64]; char buf[64];
sprintf(buf, "close %s", self->cursor); sprintf(buf, "close %s", self->cursor);
...@@ -304,21 +320,24 @@ QResultClass *res; ...@@ -304,21 +320,24 @@ QResultClass *res;
free(self->cursor); free(self->cursor);
self->cursor = NULL; self->cursor = NULL;
if (res == NULL) { if (res == NULL)
{
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error closing cursor."); QR_set_message(self, "Error closing cursor.");
return FALSE; return FALSE;
} }
/* End the transaction if there are no cursors left on this conn */ /* End the transaction if there are no cursors left on this conn */
if (CC_cursor_count(self->conn) == 0) { if (CC_cursor_count(self->conn) == 0)
{
mylog("QResult: END transaction on conn=%u\n", self->conn); mylog("QResult: END transaction on conn=%u\n", self->conn);
res = CC_send_query(self->conn, "END", NULL); res = CC_send_query(self->conn, "END", NULL);
CC_set_no_trans(self->conn); CC_set_no_trans(self->conn);
if (res == NULL) { if (res == NULL)
{
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error ending transaction."); QR_set_message(self, "Error ending transaction.");
return FALSE; return FALSE;
...@@ -332,54 +351,65 @@ QResultClass *res; ...@@ -332,54 +351,65 @@ QResultClass *res;
/* This function is called by fetch_tuples() AND SQLFetch() */ /* This function is called by fetch_tuples() AND SQLFetch() */
int int
QR_next_tuple(QResultClass *self) QR_next_tuple(QResultClass * self)
{ {
int id; int id;
QResultClass *res; QResultClass *res;
SocketClass *sock; SocketClass *sock;
/* Speed up access */ /* Speed up access */
int fetch_count = self->fetch_count; int fetch_count = self->fetch_count;
int fcount = self->fcount; int fcount = self->fcount;
int fetch_size, offset= 0; int fetch_size,
int end_tuple = self->rowset_size + self->base; offset = 0;
char corrected = FALSE; int end_tuple = self->rowset_size + self->base;
TupleField *the_tuples = self->backend_tuples; char corrected = FALSE;
static char msgbuffer[MAX_MESSAGE_LEN+1]; TupleField *the_tuples = self->backend_tuples;
char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont need static */ static char msgbuffer[MAX_MESSAGE_LEN + 1];
char fetch[128]; char cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
QueryInfo qi; * this string so dont
* need static */
if (fetch_count < fcount) { /* return a row from cache */ char fetch[128];
QueryInfo qi;
if (fetch_count < fcount)
{ /* return a row from cache */
mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount); 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->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */
self->fetch_count++; self->fetch_count++;
return TRUE; return TRUE;
} }
else if (self->fcount < self->cache_size) { /* last row from cache */ else if (self->fcount < self->cache_size)
{ /* last row from cache */
/* We are done because we didn't even get CACHE_SIZE tuples */ /* 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); mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count);
self->tupleField = NULL; self->tupleField = NULL;
self->status = PGRES_END_TUPLES; self->status = PGRES_END_TUPLES;
return -1; /* end of tuples */ return -1; /* end of tuples */
} }
else { else
/* See if we need to fetch another group of rows. {
We may be being called from send_query(), and
if so, don't send another fetch, just fall through /*
and read the tuples. * See if we need to fetch another group of rows. We may be being
* called from send_query(), and if so, don't send another fetch,
* just fall through and read the tuples.
*/ */
self->tupleField = NULL; self->tupleField = NULL;
if ( ! self->inTuples) { if (!self->inTuples)
{
if ( ! globals.use_declarefetch) { if (!globals.use_declarefetch)
{
mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count); mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
self->tupleField = NULL; self->tupleField = NULL;
self->status = PGRES_END_TUPLES; self->status = PGRES_END_TUPLES;
return -1; /* end of tuples */ return -1; /* end of tuples */
} }
if (self->base == fcount) { /* not a correction */ if (self->base == fcount)
{ /* not a correction */
/* Determine the optimum cache size. */ /* Determine the optimum cache size. */
if (globals.fetch_max % self->rowset_size == 0) if (globals.fetch_max % self->rowset_size == 0)
...@@ -392,7 +422,8 @@ QueryInfo qi; ...@@ -392,7 +422,8 @@ QueryInfo qi;
self->cache_size = fetch_size; self->cache_size = fetch_size;
self->fetch_count = 1; self->fetch_count = 1;
} }
else { /* need to correct */ else
{ /* need to correct */
corrected = TRUE; corrected = TRUE;
...@@ -407,7 +438,8 @@ QueryInfo qi; ...@@ -407,7 +438,8 @@ QueryInfo qi;
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size); self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
if ( ! self->backend_tuples) { if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples."); QR_set_message(self, "Out of memory while reading tuples.");
return FALSE; return FALSE;
...@@ -421,24 +453,29 @@ QueryInfo qi; ...@@ -421,24 +453,29 @@ QueryInfo qi;
qi.result_in = self; qi.result_in = self;
qi.cursor = NULL; qi.cursor = NULL;
res = CC_send_query(self->conn, fetch, &qi); res = CC_send_query(self->conn, fetch, &qi);
if (res == NULL) { if (res == NULL)
{
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error fetching next group."); QR_set_message(self, "Error fetching next group.");
return FALSE; return FALSE;
} }
self->inTuples = TRUE; self->inTuples = TRUE;
} }
else { else
{
mylog("next_tuple: inTuples = true, falling through: fcount = %d, fetch_count = %d\n", self->fcount, self->fetch_count); mylog("next_tuple: inTuples = true, falling through: fcount = %d, fetch_count = %d\n", self->fcount, self->fetch_count);
/* This is a pre-fetch (fetching rows right after query
but before any real SQLFetch() calls. This is done /*
so the field attributes are available. * This is a pre-fetch (fetching rows right after query but
* before any real SQLFetch() calls. This is done so the
* field attributes are available.
*/ */
self->fetch_count = 0; self->fetch_count = 0;
} }
} }
if ( ! corrected) { if (!corrected)
{
self->base = 0; self->base = 0;
self->fcount = 0; self->fcount = 0;
} }
...@@ -447,11 +484,13 @@ QueryInfo qi; ...@@ -447,11 +484,13 @@ QueryInfo qi;
sock = CC_get_socket(self->conn); sock = CC_get_socket(self->conn);
self->tupleField = NULL; self->tupleField = NULL;
for ( ; ;) { for (;;)
{
id = SOCK_get_char(sock); id = SOCK_get_char(sock);
switch (id) { switch (id)
{
case 'T': /* Tuples within tuples cannot be handled */ case 'T': /* Tuples within tuples cannot be handled */
self->status = PGRES_BAD_RESPONSE; self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Tuples within tuples cannot be handled"); QR_set_message(self, "Tuples within tuples cannot be handled");
...@@ -459,19 +498,23 @@ QueryInfo qi; ...@@ -459,19 +498,23 @@ QueryInfo qi;
case 'B': /* Tuples in binary format */ case 'B': /* Tuples in binary format */
case 'D': /* Tuples in ASCII format */ case 'D': /* Tuples in ASCII format */
if ( ! globals.use_declarefetch && self->fcount > 0 && ! (self->fcount % TUPLE_MALLOC_INC)) { if (!globals.use_declarefetch && self->fcount > 0 && !(self->fcount % TUPLE_MALLOC_INC))
{
size_t old_size = self->fcount * self->num_fields * sizeof(TupleField); size_t old_size = self->fcount * self->num_fields * sizeof(TupleField);
mylog("REALLOC: old_size = %d\n", old_size); mylog("REALLOC: old_size = %d\n", old_size);
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, old_size + (self->num_fields * sizeof(TupleField) * TUPLE_MALLOC_INC)); self->backend_tuples = (TupleField *) realloc(self->backend_tuples, old_size + (self->num_fields * sizeof(TupleField) * TUPLE_MALLOC_INC));
if ( ! self->backend_tuples) { if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples."); QR_set_message(self, "Out of memory while reading tuples.");
return FALSE; return FALSE;
} }
} }
if ( ! QR_read_tuple(self, (char) (id == 0))) { if (!QR_read_tuple(self, (char) (id == 0)))
{
self->status = PGRES_BAD_RESPONSE; self->status = PGRES_BAD_RESPONSE;
QR_set_message(self, "Error reading the tuple"); QR_set_message(self, "Error reading the tuple");
return FALSE; return FALSE;
...@@ -488,7 +531,8 @@ QueryInfo qi; ...@@ -488,7 +531,8 @@ QueryInfo qi;
mylog("end of tuple list -- setting inUse to false: this = %u\n", self); mylog("end of tuple list -- setting inUse to false: this = %u\n", self);
self->inTuples = FALSE; self->inTuples = FALSE;
if (self->fcount > 0) { if (self->fcount > 0)
{
qlog(" [ fetched %d rows ]\n", self->fcount); qlog(" [ fetched %d rows ]\n", self->fcount);
mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount); mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount);
...@@ -497,7 +541,9 @@ QueryInfo qi; ...@@ -497,7 +541,9 @@ QueryInfo qi;
self->tupleField = self->backend_tuples + (offset * self->num_fields); self->tupleField = self->backend_tuples + (offset * self->num_fields);
return TRUE; return TRUE;
} }
else { /* We are surely done here (we read 0 tuples) */ else
{ /* We are surely done here (we read 0
* tuples) */
qlog(" [ fetched 0 rows ]\n"); qlog(" [ fetched 0 rows ]\n");
mylog("_next_tuple: 'C': DONE (fcount == 0)\n"); mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
return -1; /* end of tuples */ return -1; /* end of tuples */
...@@ -508,7 +554,7 @@ QueryInfo qi; ...@@ -508,7 +554,7 @@ QueryInfo qi;
QR_set_message(self, msgbuffer); QR_set_message(self, msgbuffer);
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
if ( ! strncmp(msgbuffer, "FATAL", 5)) if (!strncmp(msgbuffer, "FATAL", 5))
CC_set_no_trans(self->conn); CC_set_no_trans(self->conn);
qlog("ERROR from backend in next_tuple: '%s'\n", msgbuffer); qlog("ERROR from backend in next_tuple: '%s'\n", msgbuffer);
...@@ -522,7 +568,8 @@ QueryInfo qi; ...@@ -522,7 +568,8 @@ QueryInfo qi;
qlog("NOTICE from backend in next_tuple: '%s'\n", msgbuffer); qlog("NOTICE from backend in next_tuple: '%s'\n", msgbuffer);
continue; continue;
default: /* this should only happen if the backend dumped core */ default: /* this should only happen if the backend
* dumped core */
mylog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id); mylog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id);
qlog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id); qlog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)\n", id, id);
QR_set_message(self, "Unexpected result from backend. It probably crashed"); QR_set_message(self, "Unexpected result from backend. It probably crashed");
...@@ -535,19 +582,20 @@ QueryInfo qi; ...@@ -535,19 +582,20 @@ QueryInfo qi;
} }
char char
QR_read_tuple(QResultClass *self, char binary) QR_read_tuple(QResultClass * self, char binary)
{ {
Int2 field_lf; Int2 field_lf;
TupleField *this_tuplefield; TupleField *this_tuplefield;
char bmp, bitmap[MAX_FIELDS]; /* Max. len of the bitmap */ char bmp,
Int2 bitmaplen; /* len of the bitmap in bytes */ bitmap[MAX_FIELDS]; /* Max. len of the bitmap */
Int2 bitmap_pos; Int2 bitmaplen; /* len of the bitmap in bytes */
Int2 bitcnt; Int2 bitmap_pos;
Int4 len; Int2 bitcnt;
char *buffer; Int4 len;
int num_fields = self->num_fields; /* speed up access */ char *buffer;
SocketClass *sock = CC_get_socket(self->conn); int num_fields = self->num_fields; /* speed up access */
ColumnInfoClass *flds; SocketClass *sock = CC_get_socket(self->conn);
ColumnInfoClass *flds;
/* set the current row to read the fields into */ /* set the current row to read the fields into */
...@@ -558,8 +606,8 @@ ColumnInfoClass *flds; ...@@ -558,8 +606,8 @@ ColumnInfoClass *flds;
bitmaplen++; bitmaplen++;
/* /*
At first the server sends a bitmap that indicates which * At first the server sends a bitmap that indicates which database
database fields are null * fields are null
*/ */
SOCK_get_n_char(sock, bitmap, bitmaplen); SOCK_get_n_char(sock, bitmap, bitmaplen);
...@@ -567,22 +615,27 @@ ColumnInfoClass *flds; ...@@ -567,22 +615,27 @@ ColumnInfoClass *flds;
bitcnt = 0; bitcnt = 0;
bmp = bitmap[bitmap_pos]; bmp = bitmap[bitmap_pos];
for(field_lf = 0; field_lf < num_fields; field_lf++) { for (field_lf = 0; field_lf < num_fields; field_lf++)
{
/* Check if the current field is NULL */ /* Check if the current field is NULL */
if(!(bmp & 0200)) { if (!(bmp & 0200))
{
/* YES, it is NULL ! */ /* YES, it is NULL ! */
this_tuplefield[field_lf].len = 0; this_tuplefield[field_lf].len = 0;
this_tuplefield[field_lf].value = 0; this_tuplefield[field_lf].value = 0;
} else { }
else
{
/* /*
NO, the field is not null. so get at first the * NO, the field is not null. so get at first the length of
length of the field (four bytes) * the field (four bytes)
*/ */
len = SOCK_get_int(sock, VARHDRSZ); len = SOCK_get_int(sock, VARHDRSZ);
if (!binary) if (!binary)
len -= VARHDRSZ; len -= VARHDRSZ;
buffer = (char *)malloc(len+1); buffer = (char *) malloc(len + 1);
SOCK_get_n_char(sock, buffer, len); SOCK_get_n_char(sock, buffer, len);
buffer[len] = '\0'; buffer[len] = '\0';
...@@ -591,27 +644,31 @@ ColumnInfoClass *flds; ...@@ -591,27 +644,31 @@ ColumnInfoClass *flds;
this_tuplefield[field_lf].len = len; this_tuplefield[field_lf].len = len;
this_tuplefield[field_lf].value = buffer; this_tuplefield[field_lf].value = buffer;
/* This can be used to set the longest length of the column for any /*
row in the tuple cache. It would not be accurate for varchar and * This can be used to set the longest length of the column
text fields to use this since a tuple cache is only 100 rows. * for any row in the tuple cache. It would not be accurate
Bpchar can be handled since the strlen of all rows is fixed, * for varchar and text fields to use this since a tuple cache
assuming there are not 100 nulls in a row! * is only 100 rows. Bpchar can be handled since the strlen of
* all rows is fixed, assuming there are not 100 nulls in a
* row!
*/ */
flds = self->fields; flds = self->fields;
if (flds->display_size[field_lf] < len) if (flds->display_size[field_lf] < len)
flds->display_size[field_lf] = len; flds->display_size[field_lf] = len;
} }
/* /*
Now adjust for the next bit to be scanned in the * Now adjust for the next bit to be scanned in the next loop.
next loop.
*/ */
bitcnt++; bitcnt++;
if (BYTELEN == bitcnt) { if (BYTELEN == bitcnt)
{
bitmap_pos++; bitmap_pos++;
bmp = bitmap[bitmap_pos]; bmp = bitmap[bitmap_pos];
bitcnt = 0; bitcnt = 0;
} else }
else
bmp <<= 1; bmp <<= 1;
} }
self->currTuple++; self->currTuple++;
......
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
#include "psqlodbc.h" #include "psqlodbc.h"
#include "tuple.h" #include "tuple.h"
enum QueryResultCode_ { enum QueryResultCode_
{
PGRES_EMPTY_QUERY = 0, PGRES_EMPTY_QUERY = 0,
PGRES_COMMAND_OK, /* a query command that doesn't return */ PGRES_COMMAND_OK, /* a query command that doesn't return */
/* anything was executed properly by the backend */ /* anything was executed properly by the backend */
...@@ -26,20 +27,24 @@ enum QueryResultCode_ { ...@@ -26,20 +27,24 @@ enum QueryResultCode_ {
/* contains the resulttuples */ /* contains the resulttuples */
PGRES_COPY_OUT, PGRES_COPY_OUT,
PGRES_COPY_IN, PGRES_COPY_IN,
PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the backend */ PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from
* the backend */
PGRES_NONFATAL_ERROR, PGRES_NONFATAL_ERROR,
PGRES_FATAL_ERROR, PGRES_FATAL_ERROR,
PGRES_FIELDS_OK, /* field information from a query was successful */ PGRES_FIELDS_OK, /* field information from a query was
* successful */
PGRES_END_TUPLES, PGRES_END_TUPLES,
PGRES_INTERNAL_ERROR PGRES_INTERNAL_ERROR
}; };
typedef enum QueryResultCode_ QueryResultCode; typedef enum QueryResultCode_ QueryResultCode;
struct QResultClass_ { struct QResultClass_
{
ColumnInfoClass *fields; /* the Column information */ ColumnInfoClass *fields; /* the Column information */
TupleListClass *manual_tuples; /* manual result tuple list */ TupleListClass *manual_tuples; /* manual result tuple list */
ConnectionClass *conn; /* the connection this result is using (backend) */ ConnectionClass *conn; /* the connection this result is using
* (backend) */
/* Stuff for declare/fetch tuples */ /* Stuff for declare/fetch tuples */
int fetch_count; /* logical rows read so far */ int fetch_count; /* logical rows read so far */
...@@ -54,14 +59,16 @@ struct QResultClass_ { ...@@ -54,14 +59,16 @@ struct QResultClass_ {
QueryResultCode status; QueryResultCode status;
char *message; char *message;
char *cursor; /* The name of the cursor for select statements */ char *cursor; /* The name of the cursor for select
* statements */
char *command; char *command;
char *notice; char *notice;
TupleField *backend_tuples; /* data from the backend (the tuple cache) */ TupleField *backend_tuples; /* data from the backend (the tuple cache) */
TupleField *tupleField; /* current backend tuple being retrieved */ TupleField *tupleField; /* current backend tuple being retrieved */
char inTuples; /* is a fetch of rows from the backend in progress? */ char inTuples; /* is a fetch of rows from the backend in
* progress? */
}; };
#define QR_get_fields(self) (self->fields) #define QR_get_fields(self) (self->fields)
...@@ -99,20 +106,20 @@ struct QResultClass_ { ...@@ -99,20 +106,20 @@ struct QResultClass_ {
/* Core Functions */ /* Core Functions */
QResultClass *QR_Constructor(void); QResultClass *QR_Constructor(void);
void QR_Destructor(QResultClass *self); void QR_Destructor(QResultClass * self);
char QR_read_tuple(QResultClass *self, char binary); char QR_read_tuple(QResultClass * self, char binary);
int QR_next_tuple(QResultClass *self); int QR_next_tuple(QResultClass * self);
int QR_close(QResultClass *self); int QR_close(QResultClass * self);
char QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor); char QR_fetch_tuples(QResultClass * self, ConnectionClass * conn, char *cursor);
void QR_free_memory(QResultClass *self); void QR_free_memory(QResultClass * self);
void QR_set_command(QResultClass *self, char *msg); void QR_set_command(QResultClass * self, char *msg);
void QR_set_notice(QResultClass *self, char *msg); void QR_set_notice(QResultClass * self, char *msg);
void QR_set_num_fields(QResultClass *self, int new_num_fields); /* manual result only */ void QR_set_num_fields(QResultClass * self, int new_num_fields); /* manual result only */
void QR_inc_base(QResultClass *self, int base_inc); void QR_inc_base(QResultClass * self, int base_inc);
void QR_set_cache_size(QResultClass *self, int cache_size); void QR_set_cache_size(QResultClass * self, int cache_size);
void QR_set_rowset_size(QResultClass *self, int rowset_size); void QR_set_rowset_size(QResultClass * self, int rowset_size);
void QR_set_position(QResultClass *self, int pos); void QR_set_position(QResultClass * self, int pos);
#endif #endif
...@@ -43,47 +43,59 @@ extern GLOBAL_VALUES globals; ...@@ -43,47 +43,59 @@ extern GLOBAL_VALUES globals;
RETCODE SQL_API SQLRowCount( RETCODE SQL_API
SQLRowCount(
HSTMT hstmt, HSTMT hstmt,
SDWORD FAR *pcrow) SDWORD FAR * pcrow)
{ {
static char *func="SQLRowCount"; static char *func = "SQLRowCount";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
char *msg, *ptr; char *msg,
*ptr;
if ( ! stmt) {
if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if (stmt->manual_result) { if (stmt->manual_result)
{
if (pcrow) if (pcrow)
*pcrow = -1; *pcrow = -1;
return SQL_SUCCESS; return SQL_SUCCESS;
} }
if(stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->statement_type == STMT_TYPE_SELECT)
if (stmt->status == STMT_FINISHED) { {
if (stmt->status == STMT_FINISHED)
{
res = SC_get_Result(stmt); res = SC_get_Result(stmt);
if(res && pcrow) { if (res && pcrow)
{
*pcrow = globals.use_declarefetch ? -1 : QR_get_num_tuples(res); *pcrow = globals.use_declarefetch ? -1 : QR_get_num_tuples(res);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
} }
} else { }
else
{
res = SC_get_Result(stmt); res = SC_get_Result(stmt);
if (res && pcrow) { if (res && pcrow)
{
msg = QR_get_command(res); msg = QR_get_command(res);
mylog("*** msg = '%s'\n", msg); mylog("*** msg = '%s'\n", msg);
trim(msg); /* get rid of trailing spaces */ trim(msg); /* get rid of trailing spaces */
ptr = strrchr(msg, ' '); ptr = strrchr(msg, ' ');
if (ptr) { if (ptr)
*pcrow = atoi(ptr+1); {
*pcrow = atoi(ptr + 1);
mylog("**** SQLRowCount(): THE ROWS: *pcrow = %d\n", *pcrow); mylog("**** SQLRowCount(): THE ROWS: *pcrow = %d\n", *pcrow);
} }
else { else
{
*pcrow = -1; *pcrow = -1;
mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow); mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow);
...@@ -102,16 +114,18 @@ char *msg, *ptr; ...@@ -102,16 +114,18 @@ char *msg, *ptr;
/* attached to "hstmt". */ /* attached to "hstmt". */
RETCODE SQL_API SQLNumResultCols( RETCODE SQL_API
SQLNumResultCols(
HSTMT hstmt, HSTMT hstmt,
SWORD FAR *pccol) SWORD FAR * pccol)
{ {
static char *func="SQLNumResultCols"; static char *func = "SQLNumResultCols";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *result; QResultClass *result;
char parse_ok; char parse_ok;
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -119,27 +133,32 @@ char parse_ok; ...@@ -119,27 +133,32 @@ char parse_ok;
SC_clear_error(stmt); SC_clear_error(stmt);
parse_ok = FALSE; parse_ok = FALSE;
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE) { if (stmt->parse_status == STMT_PARSE_NONE)
{
mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt); mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt);
parse_statement(stmt); parse_statement(stmt);
} }
if (stmt->parse_status != STMT_PARSE_FATAL) { if (stmt->parse_status != STMT_PARSE_FATAL)
{
parse_ok = TRUE; parse_ok = TRUE;
*pccol = stmt->nfld; *pccol = stmt->nfld;
mylog("PARSE: SQLNumResultCols: *pccol = %d\n", *pccol); mylog("PARSE: SQLNumResultCols: *pccol = %d\n", *pccol);
} }
} }
if ( ! parse_ok) { if (!parse_ok)
{
SC_pre_execute(stmt); SC_pre_execute(stmt);
result = SC_get_Result(stmt); result = SC_get_Result(stmt);
mylog("SQLNumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1); mylog("SQLNumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);
if (( ! result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) { if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
{
/* no query has been executed on this statement */ /* no query has been executed on this statement */
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No query has been executed with that handle"; stmt->errormsg = "No query has been executed with that handle";
...@@ -160,34 +179,37 @@ char parse_ok; ...@@ -160,34 +179,37 @@ char parse_ok;
/* Return information about the database column the user wants */ /* Return information about the database column the user wants */
/* information about. */ /* information about. */
RETCODE SQL_API SQLDescribeCol( RETCODE SQL_API
SQLDescribeCol(
HSTMT hstmt, HSTMT hstmt,
UWORD icol, UWORD icol,
UCHAR FAR *szColName, UCHAR FAR * szColName,
SWORD cbColNameMax, SWORD cbColNameMax,
SWORD FAR *pcbColName, SWORD FAR * pcbColName,
SWORD FAR *pfSqlType, SWORD FAR * pfSqlType,
UDWORD FAR *pcbColDef, UDWORD FAR * pcbColDef,
SWORD FAR *pibScale, SWORD FAR * pibScale,
SWORD FAR *pfNullable) SWORD FAR * pfNullable)
{ {
static char *func="SQLDescribeCol"; static char *func = "SQLDescribeCol";
/* gets all the information about a specific column */ /* gets all the information about a specific column */
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
char *col_name = NULL; char *col_name = NULL;
Int4 fieldtype = 0; Int4 fieldtype = 0;
int precision = 0; int precision = 0;
ConnInfo *ci; ConnInfo *ci;
char parse_ok; char parse_ok;
char buf[255]; char buf[255];
int len = 0; int len = 0;
RETCODE result; RETCODE result;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -196,17 +218,20 @@ RETCODE result; ...@@ -196,17 +218,20 @@ RETCODE result;
SC_clear_error(stmt); 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 */ icol--; /* use zero based column numbers */
parse_ok = FALSE; parse_ok = FALSE;
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE) { if (stmt->parse_status == STMT_PARSE_NONE)
{
mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt); mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt);
parse_statement(stmt); parse_statement(stmt);
} }
...@@ -214,9 +239,11 @@ RETCODE result; ...@@ -214,9 +239,11 @@ RETCODE result;
mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi); 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 (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
{
if (icol >= stmt->nfld) { if (icol >= stmt->nfld)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in DescribeCol."; stmt->errormsg = "Invalid column number in DescribeCol.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -235,16 +262,20 @@ RETCODE result; ...@@ -235,16 +262,20 @@ RETCODE result;
} }
/* 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) { if (!parse_ok)
{
SC_pre_execute(stmt); SC_pre_execute(stmt);
res = SC_get_Result(stmt); res = SC_get_Result(stmt);
mylog("**** SQLDescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE); mylog("**** SQLDescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
if ( (NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) { if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
{
/* no query has been executed on this statement */ /* no query has been executed on this statement */
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No query has been assigned to this statement."; stmt->errormsg = "No query has been assigned to this statement.";
...@@ -252,7 +283,8 @@ RETCODE result; ...@@ -252,7 +283,8 @@ RETCODE result;
return SQL_ERROR; return SQL_ERROR;
} }
if (icol >= QR_NumResultCols(res)) { if (icol >= QR_NumResultCols(res))
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in DescribeCol."; stmt->errormsg = "Invalid column number in DescribeCol.";
sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(res)); sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(res));
...@@ -263,7 +295,8 @@ RETCODE result; ...@@ -263,7 +295,8 @@ RETCODE result;
col_name = QR_get_fieldname(res, icol); col_name = QR_get_fieldname(res, icol);
fieldtype = QR_get_field_type(res, icol); fieldtype = QR_get_field_type(res, icol);
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); /* atoi(ci->unknown_sizes) */ precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); /* atoi(ci->unknown_sizes
* ) */
} }
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name); mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
...@@ -281,10 +314,12 @@ RETCODE result; ...@@ -281,10 +314,12 @@ RETCODE result;
if (pcbColName) if (pcbColName)
*pcbColName = len; *pcbColName = len;
if (szColName) { if (szColName)
{
strncpy_null(szColName, col_name, cbColNameMax); strncpy_null(szColName, col_name, cbColNameMax);
if (len >= cbColNameMax) { if (len >= cbColNameMax)
{
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
stmt->errornumber = STMT_TRUNCATED; stmt->errornumber = STMT_TRUNCATED;
stmt->errormsg = "The buffer was too small for the result."; stmt->errormsg = "The buffer was too small for the result.";
...@@ -295,7 +330,8 @@ RETCODE result; ...@@ -295,7 +330,8 @@ RETCODE result;
/************************/ /************************/
/* SQL TYPE */ /* SQL TYPE */
/************************/ /************************/
if (pfSqlType) { if (pfSqlType)
{
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype); *pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType); mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
...@@ -304,9 +340,10 @@ RETCODE result; ...@@ -304,9 +340,10 @@ RETCODE result;
/************************/ /************************/
/* PRECISION */ /* PRECISION */
/************************/ /************************/
if (pcbColDef) { if (pcbColDef)
{
if ( precision < 0) if (precision < 0)
precision = 0; /* "I dont know" */ precision = 0; /* "I dont know" */
*pcbColDef = precision; *pcbColDef = precision;
...@@ -317,10 +354,13 @@ RETCODE result; ...@@ -317,10 +354,13 @@ RETCODE result;
/************************/ /************************/
/* SCALE */ /* SCALE */
/************************/ /************************/
if (pibScale) { if (pibScale)
{
Int2 scale; Int2 scale;
scale = pgtype_scale(stmt, fieldtype, icol); scale = pgtype_scale(stmt, fieldtype, icol);
if(scale == -1) { scale = 0; } if (scale == -1)
scale = 0;
*pibScale = scale; *pibScale = scale;
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale); mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
...@@ -329,7 +369,8 @@ RETCODE result; ...@@ -329,7 +369,8 @@ RETCODE result;
/************************/ /************************/
/* NULLABILITY */ /* NULLABILITY */
/************************/ /************************/
if (pfNullable) { if (pfNullable)
{
*pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype); *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable); mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable);
...@@ -340,69 +381,81 @@ RETCODE result; ...@@ -340,69 +381,81 @@ RETCODE result;
/* Returns result column descriptor information for a result set. */ /* Returns result column descriptor information for a result set. */
RETCODE SQL_API SQLColAttributes( RETCODE SQL_API
SQLColAttributes(
HSTMT hstmt, HSTMT hstmt,
UWORD icol, UWORD icol,
UWORD fDescType, UWORD fDescType,
PTR rgbDesc, PTR rgbDesc,
SWORD cbDescMax, SWORD cbDescMax,
SWORD FAR *pcbDesc, SWORD FAR * pcbDesc,
SDWORD FAR *pfDesc) SDWORD FAR * pfDesc)
{ {
static char *func = "SQLColAttributes"; static char *func = "SQLColAttributes";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
Int4 field_type = 0; Int4 field_type = 0;
ConnInfo *ci; ConnInfo *ci;
int unknown_sizes; int unknown_sizes;
int cols = 0; int cols = 0;
char parse_ok; char parse_ok;
RETCODE result; RETCODE result;
char *p = NULL; char *p = NULL;
int len = 0, value = 0; int len = 0,
value = 0;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
ci = &(stmt->hdbc->connInfo); ci = &(stmt->hdbc->connInfo);
/* Dont check for bookmark column. This is the responsibility /*
of the driver manager. For certain types of arguments, the column * Dont check for bookmark column. This is the responsibility of the
number is ignored anyway, so it may be 0. * driver manager. For certain types of arguments, the column number
* is ignored anyway, so it may be 0.
*/ */
icol--; icol--;
unknown_sizes = globals.unknown_sizes; /* atoi(ci->unknown_sizes); */ unknown_sizes = globals.unknown_sizes; /* atoi(ci->unknown_sizes);
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) /* not appropriate for SQLColAttributes() */ * */
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) /* not appropriate for
* SQLColAttributes() */
unknown_sizes = UNKNOWNS_AS_MAX; unknown_sizes = UNKNOWNS_AS_MAX;
parse_ok = FALSE; parse_ok = FALSE;
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE) { if (stmt->parse_status == STMT_PARSE_NONE)
{
mylog("SQLColAttributes: calling parse_statement\n"); mylog("SQLColAttributes: calling parse_statement\n");
parse_statement(stmt); parse_statement(stmt);
} }
cols = stmt->nfld; cols = stmt->nfld;
/* Column Count is a special case. The Column number is ignored /*
in this case. * Column Count is a special case. The Column number is ignored
* in this case.
*/ */
if (fDescType == SQL_COLUMN_COUNT) { if (fDescType == SQL_COLUMN_COUNT)
{
if (pfDesc) if (pfDesc)
*pfDesc = cols; *pfDesc = cols;
return SQL_SUCCESS; return SQL_SUCCESS;
} }
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) { if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
{
if (icol >= cols) { if (icol >= cols)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in DescribeCol."; stmt->errormsg = "Invalid column number in DescribeCol.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -415,12 +468,14 @@ int len = 0, value = 0; ...@@ -415,12 +468,14 @@ int len = 0, value = 0;
} }
} }
if ( ! parse_ok) { if (!parse_ok)
{
SC_pre_execute(stmt); SC_pre_execute(stmt);
mylog("**** SQLColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1); mylog("**** SQLColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1);
if ( (NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) { if ((NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
{
stmt->errormsg = "Can't get column attributes: no result found."; stmt->errormsg = "Can't get column attributes: no result found.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -429,17 +484,20 @@ int len = 0, value = 0; ...@@ -429,17 +484,20 @@ int len = 0, value = 0;
cols = QR_NumResultCols(stmt->result); cols = QR_NumResultCols(stmt->result);
/* Column Count is a special case. The Column number is ignored /*
in this case. * Column Count is a special case. The Column number is ignored
* in this case.
*/ */
if (fDescType == SQL_COLUMN_COUNT) { if (fDescType == SQL_COLUMN_COUNT)
{
if (pfDesc) if (pfDesc)
*pfDesc = cols; *pfDesc = cols;
return SQL_SUCCESS; return SQL_SUCCESS;
} }
if (icol >= cols) { if (icol >= cols)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in DescribeCol."; stmt->errormsg = "Invalid column number in DescribeCol.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -451,7 +509,8 @@ int len = 0, value = 0; ...@@ -451,7 +509,8 @@ int len = 0, value = 0;
mylog("colAttr: col %d field_type = %d\n", icol, field_type); mylog("colAttr: col %d field_type = %d\n", icol, field_type);
switch(fDescType) { switch (fDescType)
{
case SQL_COLUMN_AUTO_INCREMENT: case SQL_COLUMN_AUTO_INCREMENT:
value = pgtype_auto_increment(stmt, field_type); value = pgtype_auto_increment(stmt, field_type);
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */ if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
...@@ -463,9 +522,10 @@ int len = 0, value = 0; ...@@ -463,9 +522,10 @@ int len = 0, value = 0;
value = pgtype_case_sensitive(stmt, field_type); value = pgtype_case_sensitive(stmt, field_type);
break; break;
/* This special case is handled above. /*
* This special case is handled above.
case SQL_COLUMN_COUNT: *
* case SQL_COLUMN_COUNT:
*/ */
case SQL_COLUMN_DISPLAY_SIZE: case SQL_COLUMN_DISPLAY_SIZE:
...@@ -476,13 +536,15 @@ int len = 0, value = 0; ...@@ -476,13 +536,15 @@ int len = 0, value = 0;
break; break;
case SQL_COLUMN_LABEL: case SQL_COLUMN_LABEL:
if (parse_ok && stmt->fi[icol]->alias[0] != '\0') { if (parse_ok && stmt->fi[icol]->alias[0] != '\0')
{
p = stmt->fi[icol]->alias; p = stmt->fi[icol]->alias;
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p); mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
break; break;
} /* otherwise same as column name -- FALL THROUGH!!! */ } /* otherwise same as column name -- FALL
* THROUGH!!! */
case SQL_COLUMN_NAME: case SQL_COLUMN_NAME:
...@@ -544,17 +606,18 @@ int len = 0, value = 0; ...@@ -544,17 +606,18 @@ int len = 0, value = 0;
case SQL_COLUMN_UNSIGNED: case SQL_COLUMN_UNSIGNED:
value = pgtype_unsigned(stmt, field_type); value = pgtype_unsigned(stmt, field_type);
if(value == -1) /* non-numeric becomes TRUE (ODBC Doc) */ if (value == -1) /* non-numeric becomes TRUE (ODBC Doc) */
value = TRUE; value = TRUE;
break; break;
case SQL_COLUMN_UPDATABLE: case SQL_COLUMN_UPDATABLE:
/* Neither Access or Borland care about this.
if (field_type == PG_TYPE_OID) /*
*pfDesc = SQL_ATTR_READONLY; * Neither Access or Borland care about this.
else *
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
* else
*/ */
value = SQL_ATTR_WRITE; value = SQL_ATTR_WRITE;
...@@ -565,13 +628,16 @@ int len = 0, value = 0; ...@@ -565,13 +628,16 @@ int len = 0, value = 0;
result = SQL_SUCCESS; result = SQL_SUCCESS;
if (p) { /* char/binary data */ if (p)
{ /* char/binary data */
len = strlen(p); len = strlen(p);
if (rgbDesc) { if (rgbDesc)
strncpy_null((char *)rgbDesc, p, (size_t)cbDescMax); {
strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax);
if (len >= cbDescMax) { if (len >= cbDescMax)
{
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
stmt->errornumber = STMT_TRUNCATED; stmt->errornumber = STMT_TRUNCATED;
stmt->errormsg = "The buffer was too small for the result."; stmt->errormsg = "The buffer was too small for the result.";
...@@ -581,7 +647,8 @@ int len = 0, value = 0; ...@@ -581,7 +647,8 @@ int len = 0, value = 0;
if (pcbDesc) if (pcbDesc)
*pcbDesc = len; *pcbDesc = len;
} }
else { /* numeric data */ else
{ /* numeric data */
if (pfDesc) if (pfDesc)
*pfDesc = value; *pfDesc = value;
...@@ -594,48 +661,55 @@ int len = 0, value = 0; ...@@ -594,48 +661,55 @@ int len = 0, value = 0;
/* 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( RETCODE SQL_API
SQLGetData(
HSTMT hstmt, HSTMT hstmt,
UWORD icol, UWORD icol,
SWORD fCType, SWORD fCType,
PTR rgbValue, PTR rgbValue,
SDWORD cbValueMax, SDWORD cbValueMax,
SDWORD FAR *pcbValue) SDWORD FAR * pcbValue)
{ {
static char *func="SQLGetData"; static char *func = "SQLGetData";
QResultClass *res; QResultClass *res;
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
int num_cols, num_rows; int num_cols,
Int4 field_type; num_rows;
void *value = NULL; Int4 field_type;
int result; void *value = NULL;
char get_bookmark = FALSE; int result;
char get_bookmark = FALSE;
mylog("SQLGetData: enter, stmt=%u\n", stmt);
mylog("SQLGetData: enter, stmt=%u\n", stmt);
if( ! stmt) {
if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
res = stmt->result; res = stmt->result;
if (STMT_EXECUTING == stmt->status) { if (STMT_EXECUTING == stmt->status)
{
stmt->errormsg = "Can't get data while statement is still executing."; stmt->errormsg = "Can't get data while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->status != STMT_FINISHED) { if (stmt->status != STMT_FINISHED)
{
stmt->errornumber = STMT_STATUS_ERROR; stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "GetData can only be called after the successful execution on a SQL statement"; stmt->errormsg = "GetData can only be called after the successful execution on a SQL statement";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (icol == 0) { if (icol == 0)
{
if (stmt->options.use_bookmarks == SQL_UB_OFF) { if (stmt->options.use_bookmarks == SQL_UB_OFF)
{
stmt->errornumber = STMT_COLNUM_ERROR; stmt->errornumber = STMT_COLNUM_ERROR;
stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled"; stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -643,7 +717,8 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt); ...@@ -643,7 +717,8 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
} }
/* Make sure it is the bookmark data type */ /* Make sure it is the bookmark data type */
if (fCType != SQL_C_BOOKMARK) { if (fCType != SQL_C_BOOKMARK)
{
stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK"; stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE; stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -654,14 +729,16 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt); ...@@ -654,14 +729,16 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
} }
else { else
{
/* use zero-based column numbers */ /* use zero-based column numbers */
icol--; icol--;
/* make sure the column number is valid */ /* make sure the column number is valid */
num_cols = QR_NumResultCols(res); num_cols = QR_NumResultCols(res);
if (icol >= num_cols) { if (icol >= num_cols)
{
stmt->errormsg = "Invalid column number."; stmt->errormsg = "Invalid column number.";
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -669,11 +746,13 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt); ...@@ -669,11 +746,13 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
} }
} }
if ( stmt->manual_result || ! globals.use_declarefetch) { if (stmt->manual_result || !globals.use_declarefetch)
{
/* make sure we're positioned on a valid row */ /* make sure we're positioned on a valid row */
num_rows = QR_get_num_tuples(res); num_rows = QR_get_num_tuples(res);
if((stmt->currTuple < 0) || if ((stmt->currTuple < 0) ||
(stmt->currTuple >= num_rows)) { (stmt->currTuple >= num_rows))
{
stmt->errormsg = "Not positioned on a valid row for GetData."; stmt->errormsg = "Not positioned on a valid row for GetData.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -681,31 +760,33 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt); ...@@ -681,31 +760,33 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
} }
mylog(" num_rows = %d\n", num_rows); mylog(" num_rows = %d\n", num_rows);
if ( ! get_bookmark) { if (!get_bookmark)
if ( stmt->manual_result) { {
if (stmt->manual_result)
value = QR_get_value_manual(res, stmt->currTuple, icol); value = QR_get_value_manual(res, stmt->currTuple, icol);
} else
else {
value = QR_get_value_backend_row(res, stmt->currTuple, icol); value = QR_get_value_backend_row(res, stmt->currTuple, icol);
}
mylog(" value = '%s'\n", value); mylog(" value = '%s'\n", value);
} }
} }
else { /* it's a SOCKET result (backend data) */ else
if (stmt->currTuple == -1 || ! res || ! res->tupleField) { { /* it's a SOCKET result (backend data) */
if (stmt->currTuple == -1 || !res || !res->tupleField)
{
stmt->errormsg = "Not positioned on a valid row for GetData."; stmt->errormsg = "Not positioned on a valid row for GetData.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR; stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if ( ! get_bookmark) if (!get_bookmark)
value = QR_get_value_backend(res, icol); value = QR_get_value_backend(res, icol);
mylog(" socket: value = '%s'\n", value); mylog(" socket: value = '%s'\n", value);
} }
if ( get_bookmark) { if (get_bookmark)
{
*((UDWORD *) rgbValue) = SC_get_bookmark(stmt); *((UDWORD *) rgbValue) = SC_get_bookmark(stmt);
if (pcbValue) if (pcbValue)
...@@ -725,7 +806,8 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt); ...@@ -725,7 +806,8 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
stmt->current_col = -1; stmt->current_col = -1;
switch(result) { switch (result)
{
case COPY_OK: case COPY_OK:
return SQL_SUCCESS; return SQL_SUCCESS;
...@@ -767,23 +849,26 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt); ...@@ -767,23 +849,26 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
/* Returns data for bound columns in the current row ("hstmt->iCursor"), */ /* Returns data for bound columns in the current row ("hstmt->iCursor"), */
/* advances the cursor. */ /* advances the cursor. */
RETCODE SQL_API SQLFetch( RETCODE SQL_API
SQLFetch(
HSTMT hstmt) HSTMT hstmt)
{ {
static char *func = "SQLFetch"; static char *func = "SQLFetch";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result); mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
SC_clear_error(stmt); SC_clear_error(stmt);
if ( ! (res = stmt->result)) { if (!(res = stmt->result))
{
stmt->errormsg = "Null statement result in SQLFetch."; stmt->errormsg = "Null statement result in SQLFetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -791,14 +876,16 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result); ...@@ -791,14 +876,16 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
} }
/* Not allowed to bind a bookmark column when using SQLFetch. */ /* Not allowed to bind a bookmark column when using SQLFetch. */
if ( stmt->bookmark.buffer) { if (stmt->bookmark.buffer)
{
stmt->errornumber = STMT_COLNUM_ERROR; stmt->errornumber = STMT_COLNUM_ERROR;
stmt->errormsg = "Not allowed to bind a bookmark column when using SQLFetch"; stmt->errormsg = "Not allowed to bind a bookmark column when using SQLFetch";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->status == STMT_EXECUTING) { if (stmt->status == STMT_EXECUTING)
{
stmt->errormsg = "Can't fetch while statement is still executing."; stmt->errormsg = "Can't fetch while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -806,14 +893,16 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result); ...@@ -806,14 +893,16 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
} }
if (stmt->status != STMT_FINISHED) { if (stmt->status != STMT_FINISHED)
{
stmt->errornumber = STMT_STATUS_ERROR; stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "Fetch can only be called after the successful execution on a SQL statement"; stmt->errormsg = "Fetch can only be called after the successful execution on a SQL statement";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->bindings == NULL) { if (stmt->bindings == NULL)
{
/* just to avoid a crash if the user insists on calling this */ /* just to avoid a crash if the user insists on calling this */
/* function even if SQL_ExecDirect has reported an Error */ /* function even if SQL_ExecDirect has reported an Error */
stmt->errormsg = "Bindings were not allocated properly."; stmt->errormsg = "Bindings were not allocated properly.";
...@@ -830,29 +919,36 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result); ...@@ -830,29 +919,36 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
/* This fetchs a block of data (rowset). */ /* This fetchs a block of data (rowset). */
RETCODE SQL_API SQLExtendedFetch( RETCODE SQL_API
SQLExtendedFetch(
HSTMT hstmt, HSTMT hstmt,
UWORD fFetchType, UWORD fFetchType,
SDWORD irow, SDWORD irow,
UDWORD FAR *pcrow, UDWORD FAR * pcrow,
UWORD FAR *rgfRowStatus) UWORD FAR * rgfRowStatus)
{ {
static char *func = "SQLExtendedFetch"; static char *func = "SQLExtendedFetch";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
int num_tuples, i, save_rowset_size; int num_tuples,
RETCODE result; i,
char truncated, error; save_rowset_size;
RETCODE result;
mylog("SQLExtendedFetch: stmt=%u\n", stmt); char truncated,
error;
if ( ! stmt) {
mylog("SQLExtendedFetch: stmt=%u\n", stmt);
if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if ( globals.use_declarefetch && ! stmt->manual_result) { if (globals.use_declarefetch && !stmt->manual_result)
if ( fFetchType != SQL_FETCH_NEXT) { {
if (fFetchType != SQL_FETCH_NEXT)
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Unsupported fetch type for SQLExtendedFetch with UseDeclareFetch option."; stmt->errormsg = "Unsupported fetch type for SQLExtendedFetch with UseDeclareFetch option.";
return SQL_ERROR; return SQL_ERROR;
...@@ -861,36 +957,44 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -861,36 +957,44 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
SC_clear_error(stmt); SC_clear_error(stmt);
if ( ! (res = stmt->result)) { if (!(res = stmt->result))
{
stmt->errormsg = "Null statement result in SQLExtendedFetch."; stmt->errormsg = "Null statement result in SQLExtendedFetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
/* If a bookmark colunmn is bound but bookmark usage is off, then error */ /*
if (stmt->bookmark.buffer && stmt->options.use_bookmarks == SQL_UB_OFF) { * If a bookmark colunmn is bound but bookmark usage is off, then
* error
*/
if (stmt->bookmark.buffer && stmt->options.use_bookmarks == SQL_UB_OFF)
{
stmt->errornumber = STMT_COLNUM_ERROR; stmt->errornumber = STMT_COLNUM_ERROR;
stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled"; stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->status == STMT_EXECUTING) { if (stmt->status == STMT_EXECUTING)
{
stmt->errormsg = "Can't fetch while statement is still executing."; stmt->errormsg = "Can't fetch while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->status != STMT_FINISHED) { if (stmt->status != STMT_FINISHED)
{
stmt->errornumber = STMT_STATUS_ERROR; stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "ExtendedFetch can only be called after the successful execution on a SQL statement"; stmt->errormsg = "ExtendedFetch can only be called after the successful execution on a SQL statement";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (stmt->bindings == NULL) { if (stmt->bindings == NULL)
{
/* just to avoid a crash if the user insists on calling this */ /* just to avoid a crash if the user insists on calling this */
/* function even if SQL_ExecDirect has reported an Error */ /* function even if SQL_ExecDirect has reported an Error */
stmt->errormsg = "Bindings were not allocated properly."; stmt->errormsg = "Bindings were not allocated properly.";
...@@ -913,17 +1017,21 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -913,17 +1017,21 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
save_rowset_size = stmt->save_rowset_size; save_rowset_size = stmt->save_rowset_size;
stmt->save_rowset_size = -1; stmt->save_rowset_size = -1;
switch (fFetchType) { switch (fFetchType)
{
case SQL_FETCH_NEXT: case SQL_FETCH_NEXT:
/* From the odbc spec... If positioned before the start of the RESULT SET, /*
then this should be equivalent to SQL_FETCH_FIRST. * From the odbc spec... If positioned before the start of the
* RESULT SET, then this should be equivalent to
* SQL_FETCH_FIRST.
*/ */
if (stmt->rowset_start < 0) if (stmt->rowset_start < 0)
stmt->rowset_start = 0; stmt->rowset_start = 0;
else { else
{
stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size); stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size);
} }
...@@ -935,15 +1043,19 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -935,15 +1043,19 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); 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. * 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) { if (stmt->rowset_start >= num_tuples)
{
stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size); stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
} }
else { else
{
stmt->rowset_start -= stmt->options.rowset_size; stmt->rowset_start -= stmt->options.rowset_size;
...@@ -960,35 +1072,36 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -960,35 +1072,36 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
case SQL_FETCH_LAST: case SQL_FETCH_LAST:
mylog("SQL_FETCH_LAST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple); mylog("SQL_FETCH_LAST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size) ; stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
break; break;
case SQL_FETCH_ABSOLUTE: case SQL_FETCH_ABSOLUTE:
mylog("SQL_FETCH_ABSOLUTE: num_tuples=%d, currtuple=%d, irow=%d\n", num_tuples, stmt->currTuple, irow); mylog("SQL_FETCH_ABSOLUTE: num_tuples=%d, currtuple=%d, irow=%d\n", num_tuples, stmt->currTuple, irow);
/* Position before result set, but dont fetch anything */ /* Position before result set, but dont fetch anything */
if (irow == 0) { if (irow == 0)
{
stmt->rowset_start = -1; stmt->rowset_start = -1;
stmt->currTuple = -1; stmt->currTuple = -1;
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
/* Position before the desired row */ /* Position before the desired row */
else if (irow > 0) { else if (irow > 0)
stmt->rowset_start = irow - 1; stmt->rowset_start = irow - 1;
}
/* Position with respect to the end of the result set */ /* Position with respect to the end of the result set */
else { else
stmt->rowset_start = num_tuples + irow; stmt->rowset_start = num_tuples + irow;
}
break; break;
case SQL_FETCH_RELATIVE: case SQL_FETCH_RELATIVE:
/* Refresh the current rowset -- not currently implemented, but lie anyway */ /*
if (irow == 0) { * Refresh the current rowset -- not currently implemented,
* but lie anyway
*/
if (irow == 0)
break; break;
}
stmt->rowset_start += irow; stmt->rowset_start += irow;
...@@ -1010,27 +1123,37 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -1010,27 +1123,37 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
/***********************************/ /***********************************/
/* CHECK FOR PROPER CURSOR STATE */ /* CHECK FOR PROPER CURSOR STATE */
/***********************************/ /***********************************/
/* Handle Declare Fetch style specially because the end is not really the end... */
if ( globals.use_declarefetch && ! stmt->manual_result) { /*
if (QR_end_tuples(res)) { * Handle Declare Fetch style specially because the end is not really
* the end...
*/
if (globals.use_declarefetch && !stmt->manual_result)
{
if (QR_end_tuples(res))
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
} else
else { {
/* If *new* rowset is after the result_set, return no data found */ /* If *new* rowset is after the result_set, return no data found */
if (stmt->rowset_start >= num_tuples) { if (stmt->rowset_start >= num_tuples)
{
stmt->rowset_start = num_tuples; stmt->rowset_start = num_tuples;
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
} }
/* If *new* rowset is prior to result_set, return no data found */ /* If *new* rowset is prior to result_set, return no data found */
if (stmt->rowset_start < 0) { if (stmt->rowset_start < 0)
if (stmt->rowset_start + stmt->options.rowset_size <= 0) { {
if (stmt->rowset_start + stmt->options.rowset_size <= 0)
{
stmt->rowset_start = -1; stmt->rowset_start = -1;
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
else { /* overlap with beginning of result set, so get first rowset */ else
{ /* overlap with beginning of result set,
* so get first rowset */
stmt->rowset_start = 0; stmt->rowset_start = 0;
} }
} }
...@@ -1047,7 +1170,8 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -1047,7 +1170,8 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
mylog("SQLExtendedFetch: new currTuple = %d\n", stmt->currTuple); mylog("SQLExtendedFetch: new currTuple = %d\n", stmt->currTuple);
truncated = error = FALSE; truncated = error = FALSE;
for (i = 0; i < stmt->options.rowset_size; i++) { for (i = 0; i < stmt->options.rowset_size; i++)
{
stmt->bind_row = i; /* set the binding location */ stmt->bind_row = i; /* set the binding location */
result = SC_fetch(stmt); result = SC_fetch(stmt);
...@@ -1061,16 +1185,17 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -1061,16 +1185,17 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
error = TRUE; error = TRUE;
/* Determine Row Status */ /* Determine Row Status */
if (rgfRowStatus) { if (rgfRowStatus)
{
if (result == SQL_ERROR) if (result == SQL_ERROR)
*(rgfRowStatus + i) = SQL_ROW_ERROR; *(rgfRowStatus + i) = SQL_ROW_ERROR;
else else
*(rgfRowStatus + i)= SQL_ROW_SUCCESS; *(rgfRowStatus + i) = SQL_ROW_SUCCESS;
} }
} }
/* Save the fetch count for SQLSetPos */ /* Save the fetch count for SQLSetPos */
stmt->last_fetch_count= i; stmt->last_fetch_count = i;
/* Reset next binding row */ /* Reset next binding row */
stmt->bind_row = 0; stmt->bind_row = 0;
...@@ -1079,16 +1204,16 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -1079,16 +1204,16 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
stmt->currTuple = stmt->rowset_start; stmt->currTuple = stmt->rowset_start;
/* For declare/fetch, need to reset cursor to beginning of rowset */ /* For declare/fetch, need to reset cursor to beginning of rowset */
if (globals.use_declarefetch && ! stmt->manual_result) { if (globals.use_declarefetch && !stmt->manual_result)
QR_set_position(res, 0); QR_set_position(res, 0);
}
/* Set the number of rows retrieved */ /* Set the number of rows retrieved */
if (pcrow) if (pcrow)
*pcrow = i; *pcrow = i;
if (i == 0) if (i == 0)
return SQL_NO_DATA_FOUND; /* Only DeclareFetch should wind up here */ return SQL_NO_DATA_FOUND; /* Only DeclareFetch should wind
* up here */
else if (error) else if (error)
return SQL_ERROR; return SQL_ERROR;
else if (truncated) else if (truncated)
...@@ -1103,7 +1228,8 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt); ...@@ -1103,7 +1228,8 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
/* the "hstmt". */ /* the "hstmt". */
/* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */ /* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */
RETCODE SQL_API SQLMoreResults( RETCODE SQL_API
SQLMoreResults(
HSTMT hstmt) HSTMT hstmt)
{ {
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
...@@ -1111,31 +1237,36 @@ RETCODE SQL_API SQLMoreResults( ...@@ -1111,31 +1237,36 @@ RETCODE SQL_API SQLMoreResults(
/* This positions the cursor within a rowset, that was positioned using 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. */ /* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch. */
RETCODE SQL_API SQLSetPos( RETCODE SQL_API
SQLSetPos(
HSTMT hstmt, HSTMT hstmt,
UWORD irow, UWORD irow,
UWORD fOption, UWORD fOption,
UWORD fLock) UWORD fLock)
{ {
static char *func = "SQLSetPos"; static char *func = "SQLSetPos";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
int num_cols, i; int num_cols,
BindInfoClass *bindings = stmt->bindings; i;
BindInfoClass *bindings = stmt->bindings;
if ( ! stmt) {
if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if (fOption != SQL_POSITION && fOption != SQL_REFRESH) { if (fOption != SQL_POSITION && fOption != SQL_REFRESH)
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Only SQL_POSITION/REFRESH is supported for SQLSetPos"; stmt->errormsg = "Only SQL_POSITION/REFRESH is supported for SQLSetPos";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if ( ! (res = stmt->result)) { if (!(res = stmt->result))
{
stmt->errormsg = "Null statement result in SQLSetPos."; stmt->errormsg = "Null statement result in SQLSetPos.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1143,14 +1274,16 @@ BindInfoClass *bindings = stmt->bindings; ...@@ -1143,14 +1274,16 @@ BindInfoClass *bindings = stmt->bindings;
} }
num_cols = QR_NumResultCols(res); num_cols = QR_NumResultCols(res);
if (irow == 0) { if (irow == 0)
{
stmt->errornumber = STMT_ROW_OUT_OF_RANGE; stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
stmt->errormsg = "Driver does not support Bulk operations."; stmt->errormsg = "Driver does not support Bulk operations.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (irow > stmt->last_fetch_count) { if (irow > stmt->last_fetch_count)
{
stmt->errornumber = STMT_ROW_OUT_OF_RANGE; stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
stmt->errormsg = "Row value out of range"; stmt->errormsg = "Row value out of range";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1173,13 +1306,14 @@ BindInfoClass *bindings = stmt->bindings; ...@@ -1173,13 +1306,14 @@ BindInfoClass *bindings = stmt->bindings;
/* Sets options that control the behavior of cursors. */ /* Sets options that control the behavior of cursors. */
RETCODE SQL_API SQLSetScrollOptions( RETCODE SQL_API
SQLSetScrollOptions(
HSTMT hstmt, HSTMT hstmt,
UWORD fConcurrency, UWORD fConcurrency,
SDWORD crowKeyset, SDWORD crowKeyset,
UWORD crowRowset) UWORD crowRowset)
{ {
static char *func = "SQLSetScrollOptions"; static char *func = "SQLSetScrollOptions";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR; return SQL_ERROR;
...@@ -1188,56 +1322,62 @@ static char *func = "SQLSetScrollOptions"; ...@@ -1188,56 +1322,62 @@ static char *func = "SQLSetScrollOptions";
/* Set the cursor name on a statement handle */ /* Set the cursor name on a statement handle */
RETCODE SQL_API SQLSetCursorName( RETCODE SQL_API
SQLSetCursorName(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR *szCursor, UCHAR FAR * szCursor,
SWORD cbCursor) SWORD cbCursor)
{ {
static char *func="SQLSetCursorName"; static char *func = "SQLSetCursorName";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
int len; int len;
mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n", hstmt, szCursor, cbCursor); mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n", hstmt, szCursor, cbCursor);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor; len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor;
if (len <= 0 || len > sizeof(stmt->cursor_name) - 1) { if (len <= 0 || len > sizeof(stmt->cursor_name) - 1)
{
stmt->errornumber = STMT_INVALID_CURSOR_NAME; stmt->errornumber = STMT_INVALID_CURSOR_NAME;
stmt->errormsg = "Invalid Cursor Name"; stmt->errormsg = "Invalid Cursor Name";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
strncpy_null(stmt->cursor_name, szCursor, len+1); strncpy_null(stmt->cursor_name, szCursor, len + 1);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
/* Return the cursor name for a statement handle */ /* Return the cursor name for a statement handle */
RETCODE SQL_API SQLGetCursorName( RETCODE SQL_API
SQLGetCursorName(
HSTMT hstmt, HSTMT hstmt,
UCHAR FAR *szCursor, UCHAR FAR * szCursor,
SWORD cbCursorMax, SWORD cbCursorMax,
SWORD FAR *pcbCursor) SWORD FAR * pcbCursor)
{ {
static char *func="SQLGetCursorName"; static char *func = "SQLGetCursorName";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
int len = 0; int len = 0;
RETCODE result; RETCODE result;
mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor); mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if ( stmt->cursor_name[0] == '\0') { if (stmt->cursor_name[0] == '\0')
{
stmt->errornumber = STMT_NO_CURSOR_NAME; stmt->errornumber = STMT_NO_CURSOR_NAME;
stmt->errormsg = "No Cursor name available"; stmt->errormsg = "No Cursor name available";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -1247,10 +1387,12 @@ mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", ...@@ -1247,10 +1387,12 @@ mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n",
result = SQL_SUCCESS; result = SQL_SUCCESS;
len = strlen(stmt->cursor_name); len = strlen(stmt->cursor_name);
if (szCursor) { if (szCursor)
{
strncpy_null(szCursor, stmt->cursor_name, cbCursorMax); strncpy_null(szCursor, stmt->cursor_name, cbCursorMax);
if (len >= cbCursorMax) { if (len >= cbCursorMax)
{
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
stmt->errornumber = STMT_TRUNCATED; stmt->errornumber = STMT_TRUNCATED;
stmt->errormsg = "The buffer was too small for the result."; stmt->errormsg = "The buffer was too small for the result.";
...@@ -1262,5 +1404,3 @@ mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", ...@@ -1262,5 +1404,3 @@ mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n",
return result; return result;
} }
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define INTFUNC __stdcall #define INTFUNC __stdcall
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */ extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
/* Constants --------------------------------------------------------------- */ /* Constants --------------------------------------------------------------- */
...@@ -42,7 +42,8 @@ extern GLOBAL_VALUES globals; ...@@ -42,7 +42,8 @@ extern GLOBAL_VALUES globals;
/* Globals ----------------------------------------------------------------- */ /* Globals ----------------------------------------------------------------- */
/* NOTE: All these are used by the dialog procedures */ /* NOTE: All these are used by the dialog procedures */
typedef struct tagSETUPDLG { typedef struct tagSETUPDLG
{
HWND hwndParent; /* Parent window handle */ HWND hwndParent; /* Parent window handle */
LPCSTR lpszDrvr; /* Driver description */ LPCSTR lpszDrvr; /* Driver description */
ConnInfo ci; ConnInfo ci;
...@@ -50,14 +51,14 @@ typedef struct tagSETUPDLG { ...@@ -50,14 +51,14 @@ typedef struct tagSETUPDLG {
BOOL fNewDSN; /* New data source flag */ BOOL fNewDSN; /* New data source flag */
BOOL fDefault; /* Default data source flag */ BOOL fDefault; /* Default data source flag */
} SETUPDLG, FAR *LPSETUPDLG; } SETUPDLG, FAR * LPSETUPDLG;
/* Prototypes -------------------------------------------------------------- */ /* Prototypes -------------------------------------------------------------- */
void INTFUNC CenterDialog(HWND hdlg); void INTFUNC CenterDialog(HWND hdlg);
int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam); int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
void INTFUNC ParseAttributes (LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg); void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg); BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
...@@ -72,21 +73,22 @@ BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg); ...@@ -72,21 +73,22 @@ BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
Output : TRUE success, FALSE otherwise Output : TRUE success, FALSE otherwise
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
BOOL CALLBACK ConfigDSN (HWND hwnd, BOOL CALLBACK
ConfigDSN(HWND hwnd,
WORD fRequest, WORD fRequest,
LPCSTR lpszDriver, LPCSTR lpszDriver,
LPCSTR lpszAttributes) LPCSTR lpszAttributes)
{ {
BOOL fSuccess; /* Success/fail flag */ BOOL fSuccess; /* Success/fail flag */
GLOBALHANDLE hglbAttr; GLOBALHANDLE hglbAttr;
LPSETUPDLG lpsetupdlg; LPSETUPDLG lpsetupdlg;
/* Allocate attribute array */ /* Allocate attribute array */
hglbAttr = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(SETUPDLG)); hglbAttr = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(SETUPDLG));
if (!hglbAttr) if (!hglbAttr)
return FALSE; return FALSE;
lpsetupdlg = (LPSETUPDLG)GlobalLock(hglbAttr); lpsetupdlg = (LPSETUPDLG) GlobalLock(hglbAttr);
/* Parse attribute string */ /* Parse attribute string */
if (lpszAttributes) if (lpszAttributes)
...@@ -99,7 +101,8 @@ LPSETUPDLG lpsetupdlg; ...@@ -99,7 +101,8 @@ LPSETUPDLG lpsetupdlg;
lpsetupdlg->szDSN[0] = '\0'; lpsetupdlg->szDSN[0] = '\0';
/* Remove data source */ /* Remove data source */
if (ODBC_REMOVE_DSN == fRequest) { if (ODBC_REMOVE_DSN == fRequest)
{
/* Fail if no data source name was supplied */ /* Fail if no data source name was supplied */
if (!lpsetupdlg->ci.dsn[0]) if (!lpsetupdlg->ci.dsn[0])
fSuccess = FALSE; fSuccess = FALSE;
...@@ -110,21 +113,26 @@ LPSETUPDLG lpsetupdlg; ...@@ -110,21 +113,26 @@ LPSETUPDLG lpsetupdlg;
} }
/* Add or Configure data source */ /* Add or Configure data source */
else { else
{
/* Save passed variables for global access (e.g., dialog access) */ /* Save passed variables for global access (e.g., dialog access) */
lpsetupdlg->hwndParent = hwnd; lpsetupdlg->hwndParent = hwnd;
lpsetupdlg->lpszDrvr = lpszDriver; lpsetupdlg->lpszDrvr = lpszDriver;
lpsetupdlg->fNewDSN = (ODBC_ADD_DSN == fRequest); lpsetupdlg->fNewDSN = (ODBC_ADD_DSN == fRequest);
lpsetupdlg->fDefault = !lstrcmpi(lpsetupdlg->ci.dsn, INI_DSN); lpsetupdlg->fDefault = !lstrcmpi(lpsetupdlg->ci.dsn, INI_DSN);
/* Display the appropriate dialog (if parent window handle supplied) */ /*
if (hwnd) { * Display the appropriate dialog (if parent window handle
* supplied)
*/
if (hwnd)
{
/* Display dialog(s) */ /* Display dialog(s) */
fSuccess = (IDOK == DialogBoxParam(s_hModule, fSuccess = (IDOK == DialogBoxParam(s_hModule,
MAKEINTRESOURCE(DLG_CONFIG), MAKEINTRESOURCE(DLG_CONFIG),
hwnd, hwnd,
ConfigDlgProc, ConfigDlgProc,
(LONG)(LPSTR)lpsetupdlg)); (LONG) (LPSTR) lpsetupdlg));
} }
else if (lpsetupdlg->ci.dsn[0]) else if (lpsetupdlg->ci.dsn[0])
...@@ -145,11 +153,15 @@ LPSETUPDLG lpsetupdlg; ...@@ -145,11 +153,15 @@ LPSETUPDLG lpsetupdlg;
Input : hdlg -- Dialog window handle Input : hdlg -- Dialog window handle
Output : None Output : None
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
void INTFUNC CenterDialog(HWND hdlg) void INTFUNC
CenterDialog(HWND hdlg)
{ {
HWND hwndFrame; HWND hwndFrame;
RECT rcDlg, rcScr, rcFrame; RECT rcDlg,
int cx, cy; rcScr,
rcFrame;
int cx,
cy;
hwndFrame = GetParent(hdlg); hwndFrame = GetParent(hdlg);
...@@ -158,8 +170,8 @@ void INTFUNC CenterDialog(HWND hdlg) ...@@ -158,8 +170,8 @@ void INTFUNC CenterDialog(HWND hdlg)
cy = rcDlg.bottom - rcDlg.top; cy = rcDlg.bottom - rcDlg.top;
GetClientRect(hwndFrame, &rcFrame); GetClientRect(hwndFrame, &rcFrame);
ClientToScreen(hwndFrame, (LPPOINT)(&rcFrame.left)); ClientToScreen(hwndFrame, (LPPOINT) (&rcFrame.left));
ClientToScreen(hwndFrame, (LPPOINT)(&rcFrame.right)); ClientToScreen(hwndFrame, (LPPOINT) (&rcFrame.right));
rcDlg.top = rcFrame.top + (((rcFrame.bottom - rcFrame.top) - cy) >> 1); rcDlg.top = rcFrame.top + (((rcFrame.bottom - rcFrame.top) - cy) >> 1);
rcDlg.left = rcFrame.left + (((rcFrame.right - rcFrame.left) - cx) >> 1); rcDlg.left = rcFrame.left + (((rcFrame.right - rcFrame.left) - cx) >> 1);
rcDlg.bottom = rcDlg.top + cy; rcDlg.bottom = rcDlg.top + cy;
...@@ -177,8 +189,10 @@ void INTFUNC CenterDialog(HWND hdlg) ...@@ -177,8 +189,10 @@ void INTFUNC CenterDialog(HWND hdlg)
rcDlg.left = rcDlg.right - cx; rcDlg.left = rcDlg.right - cx;
} }
if (rcDlg.left < 0) rcDlg.left = 0; if (rcDlg.left < 0)
if (rcDlg.top < 0) rcDlg.top = 0; rcDlg.left = 0;
if (rcDlg.top < 0)
rcDlg.top = 0;
MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE); MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE);
return; return;
...@@ -194,13 +208,15 @@ void INTFUNC CenterDialog(HWND hdlg) ...@@ -194,13 +208,15 @@ void INTFUNC CenterDialog(HWND hdlg)
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
int CALLBACK ConfigDlgProc(HWND hdlg, int CALLBACK
ConfigDlgProc(HWND hdlg,
WORD wMsg, WORD wMsg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
switch (wMsg) { switch (wMsg)
{
/* Initialize the dialog */ /* Initialize the dialog */
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
...@@ -213,7 +229,10 @@ int CALLBACK ConfigDlgProc(HWND hdlg, ...@@ -213,7 +229,10 @@ int CALLBACK ConfigDlgProc(HWND hdlg,
SetWindowLong(hdlg, DWL_USER, lParam); SetWindowLong(hdlg, DWL_USER, lParam);
CenterDialog(hdlg); /* Center dialog */ CenterDialog(hdlg); /* Center dialog */
/* NOTE: Values supplied in the attribute string will always */ /*
* NOTE: Values supplied in the attribute string will
* always
*/
/* override settings in ODBC.INI */ /* override settings in ODBC.INI */
/* Get the rest of the common attributes */ /* Get the rest of the common attributes */
...@@ -227,16 +246,17 @@ int CALLBACK ConfigDlgProc(HWND hdlg, ...@@ -227,16 +246,17 @@ int CALLBACK ConfigDlgProc(HWND hdlg,
SetDlgStuff(hdlg, ci); SetDlgStuff(hdlg, ci);
if (lpsetupdlg->fDefault) { if (lpsetupdlg->fDefault)
{
EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
} }
else else
SendDlgItemMessage(hdlg, IDC_DSNAME, SendDlgItemMessage(hdlg, IDC_DSNAME,
EM_LIMITTEXT, (WPARAM)(MAXDSNAME-1), 0L); EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
SendDlgItemMessage(hdlg, IDC_DESC, SendDlgItemMessage(hdlg, IDC_DESC,
EM_LIMITTEXT, (WPARAM)(MAXDESC-1), 0L); EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
return TRUE; /* Focus was not set */ return TRUE; /* Focus was not set */
} }
...@@ -244,8 +264,13 @@ int CALLBACK ConfigDlgProc(HWND hdlg, ...@@ -244,8 +264,13 @@ int CALLBACK ConfigDlgProc(HWND hdlg,
/* Process buttons */ /* Process buttons */
case WM_COMMAND: case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) { switch (GET_WM_COMMAND_ID(wParam, lParam))
/* Ensure the OK button is enabled only when a data source name */ {
/*
* Ensure the OK button is enabled only when a data
* source name
*/
/* is entered */ /* is entered */
case IDC_DSNAME: case IDC_DSNAME:
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
...@@ -266,7 +291,7 @@ int CALLBACK ConfigDlgProc(HWND hdlg, ...@@ -266,7 +291,7 @@ int CALLBACK ConfigDlgProc(HWND hdlg,
{ {
LPSETUPDLG lpsetupdlg; LPSETUPDLG lpsetupdlg;
lpsetupdlg = (LPSETUPDLG)GetWindowLong(hdlg, DWL_USER); lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
/* Retrieve dialog values */ /* Retrieve dialog values */
if (!lpsetupdlg->fDefault) if (!lpsetupdlg->fDefault)
GetDlgItemText(hdlg, IDC_DSNAME, GetDlgItemText(hdlg, IDC_DSNAME,
...@@ -297,10 +322,10 @@ int CALLBACK ConfigDlgProc(HWND hdlg, ...@@ -297,10 +322,10 @@ int CALLBACK ConfigDlgProc(HWND hdlg,
{ {
LPSETUPDLG lpsetupdlg; LPSETUPDLG lpsetupdlg;
lpsetupdlg = (LPSETUPDLG)GetWindowLong(hdlg, DWL_USER); lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS), DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
hdlg, ds_optionsProc, (LPARAM) &lpsetupdlg->ci); hdlg, ds_optionsProc, (LPARAM) & lpsetupdlg->ci);
return TRUE; return TRUE;
} }
...@@ -319,18 +344,20 @@ int CALLBACK ConfigDlgProc(HWND hdlg, ...@@ -319,18 +344,20 @@ int CALLBACK ConfigDlgProc(HWND hdlg,
Input : lpszAttributes - Pointer to attribute string Input : lpszAttributes - Pointer to attribute string
Output : None (global aAttr normally updated) Output : None (global aAttr normally updated)
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg) void INTFUNC
ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
{ {
LPCSTR lpsz; LPCSTR lpsz;
LPCSTR lpszStart; LPCSTR lpszStart;
char aszKey[MAXKEYLEN]; char aszKey[MAXKEYLEN];
int cbKey; int cbKey;
char value[MAXPGPATH]; char value[MAXPGPATH];
memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo)); memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
for (lpsz=lpszAttributes; *lpsz; lpsz++) 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; lpszStart = lpsz;
for (;; lpsz++) for (;; lpsz++)
{ {
...@@ -354,7 +381,7 @@ char value[MAXPGPATH]; ...@@ -354,7 +381,7 @@ char value[MAXPGPATH];
/* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */ /* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
_fmemcpy(value, lpszStart, MIN(lpsz-lpszStart+1, MAXPGPATH)); _fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH));
mylog("aszKey='%s', value='%s'\n", aszKey, value); mylog("aszKey='%s', value='%s'\n", aszKey, value);
...@@ -371,9 +398,10 @@ char value[MAXPGPATH]; ...@@ -371,9 +398,10 @@ char value[MAXPGPATH];
Output : TRUE if successful, FALSE otherwise Output : TRUE if successful, FALSE otherwise
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
BOOL INTFUNC SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg) BOOL INTFUNC
SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
{ {
LPCSTR lpszDSN; /* Pointer to data source name */ LPCSTR lpszDSN; /* Pointer to data source name */
lpszDSN = lpsetupdlg->ci.dsn; lpszDSN = lpsetupdlg->ci.dsn;
...@@ -404,8 +432,6 @@ LPCSTR lpszDSN; /* Pointer to da ...@@ -404,8 +432,6 @@ LPCSTR lpszDSN; /* Pointer to da
/* If the data source name has changed, remove the old name */ /* If the data source name has changed, remove the old name */
if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn)) if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
{
SQLRemoveDSNFromIni(lpsetupdlg->szDSN); SQLRemoveDSNFromIni(lpsetupdlg->szDSN);
}
return TRUE; return TRUE;
} }
...@@ -36,7 +36,7 @@ extern GLOBAL_VALUES globals; ...@@ -36,7 +36,7 @@ extern GLOBAL_VALUES globals;
void void
SOCK_clear_error(SocketClass *self) SOCK_clear_error(SocketClass * self)
{ {
self->errornumber = 0; self->errornumber = 0;
self->errormsg = NULL; self->errormsg = NULL;
...@@ -45,22 +45,23 @@ SOCK_clear_error(SocketClass *self) ...@@ -45,22 +45,23 @@ SOCK_clear_error(SocketClass *self)
SocketClass * SocketClass *
SOCK_Constructor() SOCK_Constructor()
{ {
SocketClass *rv; SocketClass *rv;
rv = (SocketClass *) malloc(sizeof(SocketClass)); rv = (SocketClass *) malloc(sizeof(SocketClass));
if (rv != NULL) { if (rv != NULL)
rv->socket = (SOCKETFD) -1; {
rv->socket = (SOCKETFD) - 1;
rv->buffer_filled_in = 0; rv->buffer_filled_in = 0;
rv->buffer_filled_out = 0; rv->buffer_filled_out = 0;
rv->buffer_read_in = 0; rv->buffer_read_in = 0;
rv->buffer_in = (unsigned char *) malloc(globals.socket_buffersize); rv->buffer_in = (unsigned char *) malloc(globals.socket_buffersize);
if ( ! rv->buffer_in) if (!rv->buffer_in)
return NULL; return NULL;
rv->buffer_out = (unsigned char *) malloc(globals.socket_buffersize); rv->buffer_out = (unsigned char *) malloc(globals.socket_buffersize);
if ( ! rv->buffer_out) if (!rv->buffer_out)
return NULL; return NULL;
rv->errormsg = NULL; rv->errormsg = NULL;
...@@ -73,10 +74,11 @@ SocketClass *rv; ...@@ -73,10 +74,11 @@ SocketClass *rv;
} }
void void
SOCK_Destructor(SocketClass *self) SOCK_Destructor(SocketClass * self)
{ {
if (self->socket != -1) { if (self->socket != -1)
if ( ! shutdown(self->socket, 2)) /* no sends or receives */ {
if (!shutdown(self->socket, 2)) /* no sends or receives */
{ {
SOCK_put_char(self, 'X'); SOCK_put_char(self, 'X');
SOCK_flush_output(self); SOCK_flush_output(self);
...@@ -96,27 +98,30 @@ SOCK_Destructor(SocketClass *self) ...@@ -96,27 +98,30 @@ SOCK_Destructor(SocketClass *self)
char char
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname) SOCK_connect_to(SocketClass * self, unsigned short port, char *hostname)
{ {
struct hostent *host; struct hostent *host;
struct sockaddr_in sadr; struct sockaddr_in sadr;
unsigned long iaddr; unsigned long iaddr;
if (self->socket != -1) { if (self->socket != -1)
{
self->errornumber = SOCKET_ALREADY_CONNECTED; self->errornumber = SOCKET_ALREADY_CONNECTED;
self->errormsg = "Socket is already connected"; self->errormsg = "Socket is already connected";
return 0; return 0;
} }
memset((char *)&sadr, 0, sizeof(sadr)); memset((char *) &sadr, 0, sizeof(sadr));
/* If it is a valid IP address, use it. /*
Otherwise use hostname lookup. * If it is a valid IP address, use it. Otherwise use hostname lookup.
*/ */
iaddr = inet_addr(hostname); iaddr = inet_addr(hostname);
if (iaddr == INADDR_NONE) { if (iaddr == INADDR_NONE)
{
host = gethostbyname(hostname); host = gethostbyname(hostname);
if (host == NULL) { if (host == NULL)
{
self->errornumber = SOCKET_HOST_NOT_FOUND; self->errornumber = SOCKET_HOST_NOT_FOUND;
self->errormsg = "Could not resolve hostname."; self->errormsg = "Could not resolve hostname.";
return 0; return 0;
...@@ -124,25 +129,27 @@ unsigned long iaddr; ...@@ -124,25 +129,27 @@ unsigned long iaddr;
memcpy(&(sadr.sin_addr), host->h_addr, host->h_length); memcpy(&(sadr.sin_addr), host->h_addr, host->h_length);
} }
else else
memcpy(&(sadr.sin_addr), (struct in_addr *) &iaddr, sizeof(iaddr)); memcpy(&(sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
sadr.sin_family = AF_INET; sadr.sin_family = AF_INET;
sadr.sin_port = htons(port); sadr.sin_port = htons(port);
self->socket = socket(AF_INET, SOCK_STREAM, 0); self->socket = socket(AF_INET, SOCK_STREAM, 0);
if (self->socket == -1) { if (self->socket == -1)
{
self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET; self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
self->errormsg = "Could not create Socket."; self->errormsg = "Could not create Socket.";
return 0; return 0;
} }
if ( connect(self->socket, (struct sockaddr *)&(sadr), if (connect(self->socket, (struct sockaddr *) & (sadr),
sizeof(sadr)) < 0) { sizeof(sadr)) < 0)
{
self->errornumber = SOCKET_COULD_NOT_CONNECT; self->errornumber = SOCKET_COULD_NOT_CONNECT;
self->errormsg = "Could not connect to remote socket."; self->errormsg = "Could not connect to remote socket.";
closesocket(self->socket); closesocket(self->socket);
self->socket = (SOCKETFD) -1; self->socket = (SOCKETFD) - 1;
return 0; return 0;
} }
return 1; return 1;
...@@ -150,34 +157,36 @@ unsigned long iaddr; ...@@ -150,34 +157,36 @@ unsigned long iaddr;
void void
SOCK_get_n_char(SocketClass *self, char *buffer, int len) SOCK_get_n_char(SocketClass * self, char *buffer, int len)
{ {
int lf; int lf;
if ( ! buffer) { if (!buffer)
{
self->errornumber = SOCKET_NULLPOINTER_PARAMETER; self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
self->errormsg = "get_n_char was called with NULL-Pointer"; self->errormsg = "get_n_char was called with NULL-Pointer";
return; return;
} }
for(lf=0; lf < len; lf++) for (lf = 0; lf < len; lf++)
buffer[lf] = SOCK_get_next_byte(self); buffer[lf] = SOCK_get_next_byte(self);
} }
void void
SOCK_put_n_char(SocketClass *self, char *buffer, int len) SOCK_put_n_char(SocketClass * self, char *buffer, int len)
{ {
int lf; int lf;
if ( ! buffer) { if (!buffer)
{
self->errornumber = SOCKET_NULLPOINTER_PARAMETER; self->errornumber = SOCKET_NULLPOINTER_PARAMETER;
self->errormsg = "put_n_char was called with NULL-Pointer"; self->errormsg = "put_n_char was called with NULL-Pointer";
return; return;
} }
for(lf=0; lf < len; lf++) for (lf = 0; lf < len; lf++)
SOCK_put_next_byte(self, (unsigned char)buffer[lf]); SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
} }
...@@ -185,50 +194,51 @@ int lf; ...@@ -185,50 +194,51 @@ int lf;
will read at most bufsize-1 characters + null. will read at most bufsize-1 characters + null.
*/ */
void void
SOCK_get_string(SocketClass *self, char *buffer, int bufsize) SOCK_get_string(SocketClass * self, char *buffer, int bufsize)
{ {
register int lf = 0; register int lf = 0;
for (lf = 0; lf < bufsize; lf++) for (lf = 0; lf < bufsize; lf++)
if ( ! (buffer[lf] = SOCK_get_next_byte(self))) if (!(buffer[lf] = SOCK_get_next_byte(self)))
return; return;
buffer[bufsize-1] = '\0'; buffer[bufsize - 1] = '\0';
} }
void void
SOCK_put_string(SocketClass *self, char *string) SOCK_put_string(SocketClass * self, char *string)
{ {
register int lf; register int lf;
int len; int len;
len = strlen(string)+1; len = strlen(string) + 1;
for(lf = 0; lf < len; lf++) for (lf = 0; lf < len; lf++)
SOCK_put_next_byte(self, (unsigned char)string[lf]); SOCK_put_next_byte(self, (unsigned char) string[lf]);
} }
int int
SOCK_get_int(SocketClass *self, short len) SOCK_get_int(SocketClass * self, short len)
{ {
char buf[4]; char buf[4];
switch (len) { switch (len)
{
case 2: case 2:
SOCK_get_n_char(self, buf, len); SOCK_get_n_char(self, buf, len);
if (self->reverse) if (self->reverse)
return *((unsigned short *) buf); return *((unsigned short *) buf);
else else
return ntohs( *((unsigned short *) buf) ); return ntohs(*((unsigned short *) buf));
case 4: case 4:
SOCK_get_n_char(self, buf, len); SOCK_get_n_char(self, buf, len);
if (self->reverse) if (self->reverse)
return *((unsigned int *) buf); return *((unsigned int *) buf);
else else
return ntohl( *((unsigned int *) buf) ); return ntohl(*((unsigned int *) buf));
default: default:
self->errornumber = SOCKET_GET_INT_WRONG_LENGTH; self->errornumber = SOCKET_GET_INT_WRONG_LENGTH;
...@@ -239,18 +249,19 @@ char buf[4]; ...@@ -239,18 +249,19 @@ char buf[4];
void void
SOCK_put_int(SocketClass *self, int value, short len) SOCK_put_int(SocketClass * self, int value, short len)
{ {
unsigned int rv; unsigned int rv;
switch (len) { switch (len)
{
case 2: case 2:
rv = self->reverse ? value : htons( (unsigned short) value); rv = self->reverse ? value : htons((unsigned short) value);
SOCK_put_n_char(self, (char *) &rv, 2); SOCK_put_n_char(self, (char *) &rv, 2);
return; return;
case 4: case 4:
rv = self->reverse ? value : htonl( (unsigned int) value); rv = self->reverse ? value : htonl((unsigned int) value);
SOCK_put_n_char(self, (char *) &rv, 4); SOCK_put_n_char(self, (char *) &rv, 4);
return; return;
...@@ -263,12 +274,13 @@ unsigned int rv; ...@@ -263,12 +274,13 @@ unsigned int rv;
void void
SOCK_flush_output(SocketClass *self) SOCK_flush_output(SocketClass * self)
{ {
int written; int written;
written = send(self->socket, (char *)self->buffer_out, self->buffer_filled_out, 0); written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
if (written != self->buffer_filled_out) { if (written != self->buffer_filled_out)
{
self->errornumber = SOCKET_WRITE_ERROR; self->errornumber = SOCKET_WRITE_ERROR;
self->errormsg = "Could not flush socket buffer."; self->errormsg = "Could not flush socket buffer.";
} }
...@@ -276,24 +288,27 @@ int written; ...@@ -276,24 +288,27 @@ int written;
} }
unsigned char unsigned char
SOCK_get_next_byte(SocketClass *self) SOCK_get_next_byte(SocketClass * self)
{ {
if (self->buffer_read_in >= self->buffer_filled_in) { if (self->buffer_read_in >= self->buffer_filled_in)
{
/* there are no more bytes left in the buffer -> */ /* there are no more bytes left in the buffer -> */
/* reload the buffer */ /* reload the buffer */
self->buffer_read_in = 0; self->buffer_read_in = 0;
self->buffer_filled_in = recv(self->socket, (char *)self->buffer_in, globals.socket_buffersize, 0); self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize); mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize);
if (self->buffer_filled_in == -1) { if (self->buffer_filled_in == -1)
{
self->errornumber = SOCKET_READ_ERROR; self->errornumber = SOCKET_READ_ERROR;
self->errormsg = "Error while reading from the socket."; self->errormsg = "Error while reading from the socket.";
self->buffer_filled_in = 0; self->buffer_filled_in = 0;
} }
if (self->buffer_filled_in == 0) { if (self->buffer_filled_in == 0)
{
self->errornumber = SOCKET_CLOSED; self->errornumber = SOCKET_CLOSED;
self->errormsg = "Socket has been closed."; self->errormsg = "Socket has been closed.";
self->buffer_filled_in = 0; self->buffer_filled_in = 0;
...@@ -304,16 +319,18 @@ SOCK_get_next_byte(SocketClass *self) ...@@ -304,16 +319,18 @@ SOCK_get_next_byte(SocketClass *self)
} }
void void
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte) SOCK_put_next_byte(SocketClass * self, unsigned char next_byte)
{ {
int bytes_sent; int bytes_sent;
self->buffer_out[self->buffer_filled_out++] = next_byte; self->buffer_out[self->buffer_filled_out++] = next_byte;
if (self->buffer_filled_out == globals.socket_buffersize) { if (self->buffer_filled_out == globals.socket_buffersize)
{
/* buffer is full, so write it out */ /* buffer is full, so write it out */
bytes_sent = send(self->socket, (char *)self->buffer_out, globals.socket_buffersize, 0); bytes_sent = send(self->socket, (char *) self->buffer_out, globals.socket_buffersize, 0);
if (bytes_sent != globals.socket_buffersize) { if (bytes_sent != globals.socket_buffersize)
{
self->errornumber = SOCKET_WRITE_ERROR; self->errornumber = SOCKET_WRITE_ERROR;
self->errormsg = "Error while writing to the socket."; self->errormsg = "Error while writing to the socket.";
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#ifndef _IN_ADDR_T #ifndef _IN_ADDR_T
#define _IN_ADDR_T #define _IN_ADDR_T
typedef unsigned int in_addr_t; typedef unsigned int in_addr_t;
#endif #endif
#define INADDR_NONE ((in_addr_t)-1) #define INADDR_NONE ((in_addr_t)-1)
#endif #endif
...@@ -52,7 +53,8 @@ typedef unsigned int in_addr_t; ...@@ -52,7 +53,8 @@ typedef unsigned int in_addr_t;
#define SOCKET_CLOSED 10 #define SOCKET_CLOSED 10
struct SocketClass_ { struct SocketClass_
{
int buffer_filled_in; int buffer_filled_in;
int buffer_filled_out; int buffer_filled_out;
...@@ -65,7 +67,8 @@ struct SocketClass_ { ...@@ -65,7 +67,8 @@ struct SocketClass_ {
char *errormsg; char *errormsg;
int errornumber; int errornumber;
char reverse; /* used to handle Postgres 6.2 protocol (reverse byte order) */ char reverse; /* used to handle Postgres 6.2 protocol
* (reverse byte order) */
}; };
...@@ -80,17 +83,17 @@ struct SocketClass_ { ...@@ -80,17 +83,17 @@ struct SocketClass_ {
/* Socket prototypes */ /* Socket prototypes */
SocketClass *SOCK_Constructor(void); SocketClass *SOCK_Constructor(void);
void SOCK_Destructor(SocketClass *self); void SOCK_Destructor(SocketClass * self);
char SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname); char SOCK_connect_to(SocketClass * self, unsigned short port, char *hostname);
void SOCK_get_n_char(SocketClass *self, char *buffer, int len); void SOCK_get_n_char(SocketClass * self, char *buffer, int len);
void SOCK_put_n_char(SocketClass *self, char *buffer, int len); void SOCK_put_n_char(SocketClass * self, char *buffer, int len);
void SOCK_get_string(SocketClass *self, char *buffer, int bufsize); void SOCK_get_string(SocketClass * self, char *buffer, int bufsize);
void SOCK_put_string(SocketClass *self, char *string); void SOCK_put_string(SocketClass * self, char *string);
int SOCK_get_int(SocketClass *self, short len); int SOCK_get_int(SocketClass * self, short len);
void SOCK_put_int(SocketClass *self, int value, short len); void SOCK_put_int(SocketClass * self, int value, short len);
void SOCK_flush_output(SocketClass *self); void SOCK_flush_output(SocketClass * self);
unsigned char SOCK_get_next_byte(SocketClass *self); unsigned char SOCK_get_next_byte(SocketClass * self);
void SOCK_put_next_byte(SocketClass *self, unsigned char next_byte); void SOCK_put_next_byte(SocketClass * self, unsigned char next_byte);
void SOCK_clear_error(SocketClass *self); void SOCK_clear_error(SocketClass * self);
#endif #endif
...@@ -45,33 +45,58 @@ extern GLOBAL_VALUES globals; ...@@ -45,33 +45,58 @@ extern GLOBAL_VALUES globals;
#define PRN_NULLCHECK #define PRN_NULLCHECK
/* Map sql commands to statement types */ /* Map sql commands to statement types */
static struct { static struct
{
int type; int type;
char *s; char *s;
} Statement_Type[] = { } Statement_Type[] =
{ STMT_TYPE_SELECT, "SELECT" },
{ STMT_TYPE_INSERT, "INSERT" }, {
{ STMT_TYPE_UPDATE, "UPDATE" }, {
{ STMT_TYPE_DELETE, "DELETE" }, STMT_TYPE_SELECT, "SELECT"
{ STMT_TYPE_CREATE, "CREATE" }, },
{ STMT_TYPE_ALTER, "ALTER" }, {
{ STMT_TYPE_DROP, "DROP" }, STMT_TYPE_INSERT, "INSERT"
{ STMT_TYPE_GRANT, "GRANT" }, },
{ STMT_TYPE_REVOKE, "REVOKE" }, {
{ 0, NULL } STMT_TYPE_UPDATE, "UPDATE"
},
{
STMT_TYPE_DELETE, "DELETE"
},
{
STMT_TYPE_CREATE, "CREATE"
},
{
STMT_TYPE_ALTER, "ALTER"
},
{
STMT_TYPE_DROP, "DROP"
},
{
STMT_TYPE_GRANT, "GRANT"
},
{
STMT_TYPE_REVOKE, "REVOKE"
},
{
0, NULL
}
}; };
RETCODE SQL_API SQLAllocStmt(HDBC hdbc, RETCODE SQL_API
HSTMT FAR *phstmt) SQLAllocStmt(HDBC hdbc,
HSTMT FAR * phstmt)
{ {
static char *func="SQLAllocStmt"; static char *func = "SQLAllocStmt";
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
StatementClass *stmt; StatementClass *stmt;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if( ! conn) { if (!conn)
{
CC_log_error(func, "", NULL); CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
...@@ -80,7 +105,8 @@ StatementClass *stmt; ...@@ -80,7 +105,8 @@ StatementClass *stmt;
mylog("**** SQLAllocStmt: hdbc = %u, stmt = %u\n", hdbc, stmt); mylog("**** SQLAllocStmt: hdbc = %u, stmt = %u\n", hdbc, stmt);
if ( ! stmt) { if (!stmt)
{
conn->errornumber = CONN_STMT_ALLOC_ERROR; conn->errornumber = CONN_STMT_ALLOC_ERROR;
conn->errormsg = "No more memory to allocate a further SQL-statement"; conn->errormsg = "No more memory to allocate a further SQL-statement";
*phstmt = SQL_NULL_HSTMT; *phstmt = SQL_NULL_HSTMT;
...@@ -88,7 +114,8 @@ StatementClass *stmt; ...@@ -88,7 +114,8 @@ StatementClass *stmt;
return SQL_ERROR; return SQL_ERROR;
} }
if ( ! CC_add_statement(conn, stmt)) { if (!CC_add_statement(conn, stmt))
{
conn->errormsg = "Maximum number of connections exceeded."; conn->errormsg = "Maximum number of connections exceeded.";
conn->errornumber = CONN_STMT_ALLOC_ERROR; conn->errornumber = CONN_STMT_ALLOC_ERROR;
CC_log_error(func, "", conn); CC_log_error(func, "", conn);
...@@ -99,7 +126,8 @@ StatementClass *stmt; ...@@ -99,7 +126,8 @@ StatementClass *stmt;
*phstmt = (HSTMT) stmt; *phstmt = (HSTMT) stmt;
/* Copy default statement options based from Connection options /*
* Copy default statement options based from Connection options
*/ */
stmt->options = conn->stmtOptions; stmt->options = conn->stmtOptions;
...@@ -111,33 +139,40 @@ StatementClass *stmt; ...@@ -111,33 +139,40 @@ StatementClass *stmt;
} }
RETCODE SQL_API SQLFreeStmt(HSTMT hstmt, RETCODE SQL_API
SQLFreeStmt(HSTMT hstmt,
UWORD fOption) UWORD fOption)
{ {
static char *func="SQLFreeStmt"; static char *func = "SQLFreeStmt";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...hstmt=%u, fOption=%d\n", func, hstmt, fOption); mylog("%s: entering...hstmt=%u, fOption=%d\n", func, hstmt, fOption);
if ( ! stmt) { if (!stmt)
{
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
if (fOption == SQL_DROP) { if (fOption == SQL_DROP)
{
ConnectionClass *conn = stmt->hdbc; ConnectionClass *conn = stmt->hdbc;
/* Remove the statement from the connection's statement list */ /* Remove the statement from the connection's statement list */
if ( conn) { if (conn)
if ( ! CC_remove_statement(conn, stmt)) { {
if (!CC_remove_statement(conn, stmt))
{
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Statement is currently executing a transaction."; stmt->errormsg = "Statement is currently executing a transaction.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; /* stmt may be executing a transaction */ return SQL_ERROR; /* stmt may be executing a
* transaction */
} }
/* Free any cursors and discard any result info */ /* Free any cursors and discard any result info */
if (stmt->result) { if (stmt->result)
{
QR_Destructor(stmt->result); QR_Destructor(stmt->result);
stmt->result = NULL; stmt->result = NULL;
} }
...@@ -146,22 +181,31 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -146,22 +181,31 @@ StatementClass *stmt = (StatementClass *) hstmt;
/* Destroy the statement and free any results, cursors, etc. */ /* Destroy the statement and free any results, cursors, etc. */
SC_Destructor(stmt); SC_Destructor(stmt);
} else if (fOption == SQL_UNBIND) { }
else if (fOption == SQL_UNBIND)
{
SC_unbind_cols(stmt); SC_unbind_cols(stmt);
} else if (fOption == SQL_CLOSE) { }
else if (fOption == SQL_CLOSE)
{
/* this should discard all the results, but leave the statement */ /* this should discard all the results, but leave the statement */
/* itself in place (it can be executed again) */ /* itself in place (it can be executed again) */
if (!SC_recycle_statement(stmt)) { if (!SC_recycle_statement(stmt))
{
/* errormsg passed in above */ /* errormsg passed in above */
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
} else if(fOption == SQL_RESET_PARAMS) { }
else if (fOption == SQL_RESET_PARAMS)
{
SC_free_params(stmt, STMT_FREE_PARAMS_ALL); SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
} else { }
else
{
stmt->errormsg = "Invalid option passed to SQLFreeStmt."; stmt->errormsg = "Invalid option passed to SQLFreeStmt.";
stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR; stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
...@@ -177,7 +221,7 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -177,7 +221,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
* StatementClass implementation * StatementClass implementation
*/ */
void void
InitializeStatementOptions(StatementOptions *opt) InitializeStatementOptions(StatementOptions * opt)
{ {
opt->maxRows = 0; /* driver returns all rows */ opt->maxRows = 0; /* driver returns all rows */
opt->maxLength = 0; /* driver returns all data for char/binary */ opt->maxLength = 0; /* driver returns all data for char/binary */
...@@ -193,10 +237,11 @@ InitializeStatementOptions(StatementOptions *opt) ...@@ -193,10 +237,11 @@ InitializeStatementOptions(StatementOptions *opt)
StatementClass * StatementClass *
SC_Constructor(void) SC_Constructor(void)
{ {
StatementClass *rv; StatementClass *rv;
rv = (StatementClass *) malloc(sizeof(StatementClass)); rv = (StatementClass *) malloc(sizeof(StatementClass));
if (rv) { if (rv)
{
rv->hdbc = NULL; /* no connection associated yet */ rv->hdbc = NULL; /* no connection associated yet */
rv->phstmt = NULL; rv->phstmt = NULL;
rv->result = NULL; rv->result = NULL;
...@@ -251,18 +296,20 @@ StatementClass *rv; ...@@ -251,18 +296,20 @@ StatementClass *rv;
} }
char char
SC_Destructor(StatementClass *self) SC_Destructor(StatementClass * self)
{ {
mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc); mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc);
if (STMT_EXECUTING == self->status) { if (STMT_EXECUTING == self->status)
{
self->errornumber = STMT_SEQUENCE_ERROR; self->errornumber = STMT_SEQUENCE_ERROR;
self->errormsg = "Statement is currently executing a transaction."; self->errormsg = "Statement is currently executing a transaction.";
return FALSE; return FALSE;
} }
if (self->result) { if (self->result)
if ( ! self->hdbc) {
if (!self->hdbc)
self->result->conn = NULL; /* prevent any dbase activity */ self->result->conn = NULL; /* prevent any dbase activity */
QR_Destructor(self->result); QR_Destructor(self->result);
...@@ -273,29 +320,38 @@ SC_Destructor(StatementClass *self) ...@@ -273,29 +320,38 @@ SC_Destructor(StatementClass *self)
SC_free_params(self, STMT_FREE_PARAMS_ALL); SC_free_params(self, STMT_FREE_PARAMS_ALL);
/* the memory pointed to by the bindings is not deallocated by the driver */ /*
/* by by the application that uses that driver, so we don't have to care */ * the memory pointed to by the bindings is not deallocated by the
* driver
*/
/*
* by by the application that uses that driver, so we don't have to
* care
*/
/* about that here. */ /* about that here. */
if (self->bindings) if (self->bindings)
free(self->bindings); free(self->bindings);
/* Free the parsed table information */ /* Free the parsed table information */
if (self->ti) { if (self->ti)
{
int i; int i;
for (i = 0; i < self->ntab; i++) {
for (i = 0; i < self->ntab; i++)
free(self->ti[i]); free(self->ti[i]);
}
free(self->ti); free(self->ti);
} }
/* Free the parsed field information */ /* Free the parsed field information */
if (self->fi) { if (self->fi)
{
int i; int i;
for (i = 0; i < self->nfld; i++) {
for (i = 0; i < self->nfld; i++)
free(self->fi[i]); free(self->fi[i]);
}
free(self->fi); free(self->fi);
} }
...@@ -311,24 +367,28 @@ SC_Destructor(StatementClass *self) ...@@ -311,24 +367,28 @@ SC_Destructor(StatementClass *self)
data-at-execution parameters that was allocated in SQLPutData. data-at-execution parameters that was allocated in SQLPutData.
*/ */
void void
SC_free_params(StatementClass *self, char option) SC_free_params(StatementClass * self, char option)
{ {
int i; int i;
mylog("SC_free_params: ENTER, self=%d\n", self); mylog("SC_free_params: ENTER, self=%d\n", self);
if( ! self->parameters) if (!self->parameters)
return; return;
for (i = 0; i < self->parameters_allocated; i++) { for (i = 0; i < self->parameters_allocated; i++)
if (self->parameters[i].data_at_exec == TRUE) { {
if (self->parameters[i].data_at_exec == TRUE)
{
if (self->parameters[i].EXEC_used) { if (self->parameters[i].EXEC_used)
{
free(self->parameters[i].EXEC_used); free(self->parameters[i].EXEC_used);
self->parameters[i].EXEC_used = NULL; self->parameters[i].EXEC_used = NULL;
} }
if (self->parameters[i].EXEC_buffer) { if (self->parameters[i].EXEC_buffer)
{
if (self->parameters[i].SQLType != SQL_LONGVARBINARY) if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
free(self->parameters[i].EXEC_buffer); free(self->parameters[i].EXEC_buffer);
self->parameters[i].EXEC_buffer = NULL; self->parameters[i].EXEC_buffer = NULL;
...@@ -339,7 +399,8 @@ int i; ...@@ -339,7 +399,8 @@ int i;
self->current_exec_param = -1; self->current_exec_param = -1;
self->put_data = FALSE; self->put_data = FALSE;
if (option == STMT_FREE_PARAMS_ALL) { if (option == STMT_FREE_PARAMS_ALL)
{
free(self->parameters); free(self->parameters);
self->parameters = NULL; self->parameters = NULL;
self->parameters_allocated = 0; self->parameters_allocated = 0;
...@@ -352,14 +413,14 @@ int i; ...@@ -352,14 +413,14 @@ int i;
int int
statement_type(char *statement) statement_type(char *statement)
{ {
int i; int i;
/* ignore leading whitespace in query string */ /* ignore leading whitespace in query string */
while (*statement && isspace((unsigned char) *statement)) while (*statement && isspace((unsigned char) *statement))
statement++; statement++;
for (i = 0; Statement_Type[i].s; i++) for (i = 0; Statement_Type[i].s; i++)
if ( ! strnicmp(statement, Statement_Type[i].s, strlen(Statement_Type[i].s))) if (!strnicmp(statement, Statement_Type[i].s, strlen(Statement_Type[i].s)))
return Statement_Type[i].type; return Statement_Type[i].type;
return STMT_TYPE_OTHER; return STMT_TYPE_OTHER;
...@@ -371,14 +432,15 @@ int i; ...@@ -371,14 +432,15 @@ int i;
from SQLFreeStmt(SQL_CLOSE) from SQLFreeStmt(SQL_CLOSE)
*/ */
char char
SC_recycle_statement(StatementClass *self) SC_recycle_statement(StatementClass * self)
{ {
ConnectionClass *conn; ConnectionClass *conn;
mylog("recycle statement: self= %u\n", self); mylog("recycle statement: self= %u\n", self);
/* This would not happen */ /* This would not happen */
if (self->status == STMT_EXECUTING) { if (self->status == STMT_EXECUTING)
{
self->errornumber = STMT_SEQUENCE_ERROR; self->errornumber = STMT_SEQUENCE_ERROR;
self->errormsg = "Statement is currently executing a transaction."; self->errormsg = "Statement is currently executing a transaction.";
return FALSE; return FALSE;
...@@ -388,7 +450,8 @@ mylog("recycle statement: self= %u\n", self); ...@@ -388,7 +450,8 @@ mylog("recycle statement: self= %u\n", self);
self->errornumber = 0; self->errornumber = 0;
self->errormsg_created = FALSE; self->errormsg_created = FALSE;
switch (self->status) { switch (self->status)
{
case STMT_ALLOCATED: case STMT_ALLOCATED:
/* this statement does not need to be recycled */ /* this statement does not need to be recycled */
return TRUE; return TRUE;
...@@ -397,11 +460,15 @@ mylog("recycle statement: self= %u\n", self); ...@@ -397,11 +460,15 @@ mylog("recycle statement: self= %u\n", self);
break; break;
case STMT_PREMATURE: case STMT_PREMATURE:
/* Premature execution of the statement might have caused the start of a transaction.
If so, we have to rollback that transaction. /*
* Premature execution of the statement might have caused the
* start of a transaction. If so, we have to rollback that
* transaction.
*/ */
conn = SC_get_conn(self); conn = SC_get_conn(self);
if ( ! CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) { if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
{
CC_send_query(conn, "ABORT", NULL); CC_send_query(conn, "ABORT", NULL);
CC_set_no_trans(conn); CC_set_no_trans(conn);
...@@ -418,11 +485,12 @@ mylog("recycle statement: self= %u\n", self); ...@@ -418,11 +485,12 @@ mylog("recycle statement: self= %u\n", self);
} }
/* Free the parsed table information */ /* Free the parsed table information */
if (self->ti) { if (self->ti)
{
int i; int i;
for (i = 0; i < self->ntab; i++) {
for (i = 0; i < self->ntab; i++)
free(self->ti[i]); free(self->ti[i]);
}
free(self->ti); free(self->ti);
self->ti = NULL; self->ti = NULL;
...@@ -430,11 +498,12 @@ mylog("recycle statement: self= %u\n", self); ...@@ -430,11 +498,12 @@ mylog("recycle statement: self= %u\n", self);
} }
/* Free the parsed field information */ /* Free the parsed field information */
if (self->fi) { if (self->fi)
{
int i; int i;
for (i = 0; i < self->nfld; i++) {
for (i = 0; i < self->nfld; i++)
free(self->fi[i]); free(self->fi[i]);
}
free(self->fi); free(self->fi);
self->fi = NULL; self->fi = NULL;
self->nfld = 0; self->nfld = 0;
...@@ -442,7 +511,8 @@ mylog("recycle statement: self= %u\n", self); ...@@ -442,7 +511,8 @@ mylog("recycle statement: self= %u\n", self);
self->parse_status = STMT_PARSE_NONE; self->parse_status = STMT_PARSE_NONE;
/* Free any cursors */ /* Free any cursors */
if (self->result) { if (self->result)
{
QR_Destructor(self->result); QR_Destructor(self->result);
self->result = NULL; self->result = NULL;
} }
...@@ -452,7 +522,7 @@ mylog("recycle statement: self= %u\n", self); ...@@ -452,7 +522,7 @@ mylog("recycle statement: self= %u\n", self);
/****************************************************************/ /****************************************************************/
self->status = STMT_READY; self->status = STMT_READY;
self->manual_result = FALSE; /* very important */ self->manual_result = FALSE;/* very important */
self->currTuple = -1; self->currTuple = -1;
self->rowset_start = -1; self->rowset_start = -1;
...@@ -476,17 +546,19 @@ mylog("recycle statement: self= %u\n", self); ...@@ -476,17 +546,19 @@ mylog("recycle statement: self= %u\n", self);
/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */ /* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */
void void
SC_pre_execute(StatementClass *self) SC_pre_execute(StatementClass * self)
{ {
mylog("SC_pre_execute: status = %d\n", self->status); mylog("SC_pre_execute: status = %d\n", self->status);
if (self->status == STMT_READY) { if (self->status == STMT_READY)
{
mylog(" preprocess: status = READY\n"); mylog(" preprocess: status = READY\n");
SQLExecute(self); SQLExecute(self);
if (self->status == STMT_FINISHED) { if (self->status == STMT_FINISHED)
{
mylog(" preprocess: after status = FINISHED, so set PREMATURE\n"); mylog(" preprocess: after status = FINISHED, so set PREMATURE\n");
self->status = STMT_PREMATURE; self->status = STMT_PREMATURE;
} }
...@@ -495,11 +567,12 @@ SC_pre_execute(StatementClass *self) ...@@ -495,11 +567,12 @@ SC_pre_execute(StatementClass *self)
/* This is only called from SQLFreeStmt(SQL_UNBIND) */ /* This is only called from SQLFreeStmt(SQL_UNBIND) */
char char
SC_unbind_cols(StatementClass *self) SC_unbind_cols(StatementClass * self)
{ {
Int2 lf; Int2 lf;
for(lf = 0; lf < self->bindings_allocated; lf++) { for (lf = 0; lf < self->bindings_allocated; lf++)
{
self->bindings[lf].data_left = -1; self->bindings[lf].data_left = -1;
self->bindings[lf].buflen = 0; self->bindings[lf].buflen = 0;
self->bindings[lf].buffer = NULL; self->bindings[lf].buffer = NULL;
...@@ -514,7 +587,7 @@ Int2 lf; ...@@ -514,7 +587,7 @@ Int2 lf;
} }
void void
SC_clear_error(StatementClass *self) SC_clear_error(StatementClass * self)
{ {
self->errornumber = 0; self->errornumber = 0;
self->errormsg = NULL; self->errormsg = NULL;
...@@ -525,12 +598,12 @@ SC_clear_error(StatementClass *self) ...@@ -525,12 +598,12 @@ SC_clear_error(StatementClass *self)
/* This function creates an error msg which is the concatenation */ /* This function creates an error msg which is the concatenation */
/* of the result, statement, connection, and socket messages. */ /* of the result, statement, connection, and socket messages. */
char * char *
SC_create_errormsg(StatementClass *self) SC_create_errormsg(StatementClass * self)
{ {
QResultClass *res = self->result; QResultClass *res = self->result;
ConnectionClass *conn = self->hdbc; ConnectionClass *conn = self->hdbc;
int pos; int pos;
static char msg[4096]; static char msg[4096];
msg[0] = '\0'; msg[0] = '\0';
...@@ -540,15 +613,18 @@ static char msg[4096]; ...@@ -540,15 +613,18 @@ static char msg[4096];
else if (self->errormsg) else if (self->errormsg)
strcpy(msg, self->errormsg); strcpy(msg, self->errormsg);
if (conn) { if (conn)
{
SocketClass *sock = conn->sock; SocketClass *sock = conn->sock;
if (conn->errormsg && conn->errormsg[0] != '\0') { if (conn->errormsg && conn->errormsg[0] != '\0')
{
pos = strlen(msg); pos = strlen(msg);
sprintf(&msg[pos], ";\n%s", conn->errormsg); sprintf(&msg[pos], ";\n%s", conn->errormsg);
} }
if (sock && sock->errormsg && sock->errormsg[0] != '\0') { if (sock && sock->errormsg && sock->errormsg[0] != '\0')
{
pos = strlen(msg); pos = strlen(msg);
sprintf(&msg[pos], ";\n%s", sock->errormsg); sprintf(&msg[pos], ";\n%s", sock->errormsg);
} }
...@@ -558,17 +634,19 @@ static char msg[4096]; ...@@ -558,17 +634,19 @@ static char msg[4096];
} }
char char
SC_get_error(StatementClass *self, int *number, char **message) SC_get_error(StatementClass * self, int *number, char **message)
{ {
char rv; 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) { if (!self->errormsg_created)
{
self->errormsg = SC_create_errormsg(self); self->errormsg = SC_create_errormsg(self);
self->errormsg_created = TRUE; self->errormsg_created = TRUE;
} }
if ( self->errornumber) { if (self->errornumber)
{
*number = self->errornumber; *number = self->errornumber;
*message = self->errormsg; *message = self->errormsg;
self->errormsg = NULL; self->errormsg = NULL;
...@@ -585,21 +663,24 @@ char rv; ...@@ -585,21 +663,24 @@ char rv;
someday, such as mapping a key to a 32 bit value someday, such as mapping a key to a 32 bit value
*/ */
unsigned long unsigned long
SC_get_bookmark(StatementClass *self) SC_get_bookmark(StatementClass * self)
{ {
return (self->currTuple + 1); return (self->currTuple + 1);
} }
RETCODE RETCODE
SC_fetch(StatementClass *self) SC_fetch(StatementClass * self)
{ {
static char *func = "SC_fetch"; static char *func = "SC_fetch";
QResultClass *res = self->result; QResultClass *res = self->result;
int retval, result; int retval,
Int2 num_cols, lf; result;
Oid type; Int2 num_cols,
char *value; lf;
ColumnInfoClass *ci; Oid type;
char *value;
ColumnInfoClass *ci;
/* TupleField *tupleField; */ /* TupleField *tupleField; */
self->last_fetch_count = 0; self->last_fetch_count = 0;
...@@ -607,13 +688,16 @@ ColumnInfoClass *ci; ...@@ -607,13 +688,16 @@ ColumnInfoClass *ci;
mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, globals.use_declarefetch); mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, globals.use_declarefetch);
if ( self->manual_result || ! globals.use_declarefetch) { if (self->manual_result || !globals.use_declarefetch)
{
if (self->currTuple >= QR_get_num_tuples(res) -1 || if (self->currTuple >= QR_get_num_tuples(res) - 1 ||
(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 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 * if at the end of the tuples, return "no data found" and set
* the cursor past the end of the result set
*/ */
self->currTuple = QR_get_num_tuples(res); self->currTuple = QR_get_num_tuples(res);
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
...@@ -622,18 +706,21 @@ ColumnInfoClass *ci; ...@@ -622,18 +706,21 @@ ColumnInfoClass *ci;
mylog("**** SQLFetch: manual_result\n"); mylog("**** SQLFetch: manual_result\n");
(self->currTuple)++; (self->currTuple)++;
} }
else { else
{
/* read from the cache or the physical next tuple */ /* read from the cache or the physical next tuple */
retval = QR_next_tuple(res); retval = QR_next_tuple(res);
if (retval < 0) { if (retval < 0)
{
mylog("**** SQLFetch: end_tuples\n"); mylog("**** SQLFetch: end_tuples\n");
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
else if (retval > 0) else if (retval > 0)
(self->currTuple)++; /* all is well */ (self->currTuple)++;/* all is well */
else { else
{
mylog("SQLFetch: error\n"); mylog("SQLFetch: error\n");
self->errornumber = STMT_EXEC_ERROR; self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Error fetching next row"; self->errormsg = "Error fetching next row";
...@@ -647,12 +734,14 @@ ColumnInfoClass *ci; ...@@ -647,12 +734,14 @@ ColumnInfoClass *ci;
result = SQL_SUCCESS; result = SQL_SUCCESS;
self->last_fetch_count = 1; self->last_fetch_count = 1;
/* If the bookmark column was bound then return a bookmark. /*
Since this is used with SQLExtendedFetch, and the rowset size * If the bookmark column was bound then return a bookmark. Since this
may be greater than 1, and an application can use row or column wise * is used with SQLExtendedFetch, and the rowset size may be greater
binding, use the code in copy_and_convert_field() to handle that. * than 1, and an application can use row or column wise binding, use
* the code in copy_and_convert_field() to handle that.
*/ */
if (self->bookmark.buffer) { if (self->bookmark.buffer)
{
char buf[32]; char buf[32];
sprintf(buf, "%ld", SC_get_bookmark(self)); sprintf(buf, "%ld", SC_get_bookmark(self));
...@@ -660,14 +749,16 @@ ColumnInfoClass *ci; ...@@ -660,14 +749,16 @@ ColumnInfoClass *ci;
SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used); SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used);
} }
for (lf=0; lf < num_cols; lf++) { for (lf = 0; lf < num_cols; lf++)
{
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer); 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 */ /* reset for SQLGetData */
self->bindings[lf].data_left = -1; self->bindings[lf].data_left = -1;
if (self->bindings[lf].buffer != NULL) { if (self->bindings[lf].buffer != NULL)
{
/* this column has a binding */ /* this column has a binding */
/* type = QR_get_field_type(res, lf); */ /* type = QR_get_field_type(res, lf); */
...@@ -675,23 +766,24 @@ ColumnInfoClass *ci; ...@@ -675,23 +766,24 @@ ColumnInfoClass *ci;
mylog("type = %d\n", type); mylog("type = %d\n", type);
if (self->manual_result) { if (self->manual_result)
{
value = QR_get_value_manual(res, self->currTuple, lf); value = QR_get_value_manual(res, self->currTuple, lf);
mylog("manual_result\n"); mylog("manual_result\n");
} }
else if (globals.use_declarefetch) else if (globals.use_declarefetch)
value = QR_get_value_backend(res, lf); value = QR_get_value_backend(res, lf);
else { else
value = QR_get_value_backend_row(res, self->currTuple, lf); value = QR_get_value_backend_row(res, self->currTuple, lf);
}
mylog("value = '%s'\n", (value==NULL)?"<NULL>":value); mylog("value = '%s'\n", (value == NULL) ? "<NULL>" : value);
retval = copy_and_convert_field_bindinfo(self, type, value, lf); retval = copy_and_convert_field_bindinfo(self, type, value, lf);
mylog("copy_and_convert: retval = %d\n", retval); mylog("copy_and_convert: retval = %d\n", retval);
switch(retval) { switch (retval)
{
case COPY_OK: case COPY_OK:
break; /* OK, do next bound column */ break; /* OK, do next bound column */
...@@ -715,7 +807,8 @@ ColumnInfoClass *ci; ...@@ -715,7 +807,8 @@ ColumnInfoClass *ci;
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
break; break;
case COPY_GENERAL_ERROR: /* error msg already filled in */ case COPY_GENERAL_ERROR: /* error msg already
* filled in */
SC_log_error(func, "", self); SC_log_error(func, "", self);
result = SQL_ERROR; result = SQL_ERROR;
break; break;
...@@ -738,35 +831,40 @@ ColumnInfoClass *ci; ...@@ -738,35 +831,40 @@ ColumnInfoClass *ci;
} }
RETCODE SC_execute(StatementClass *self) RETCODE
SC_execute(StatementClass * self)
{ {
static char *func="SC_execute"; static char *func = "SC_execute";
ConnectionClass *conn; ConnectionClass *conn;
QResultClass *res; QResultClass *res;
char ok, was_ok, was_nonfatal; char ok,
Int2 oldstatus, numcols; was_ok,
QueryInfo qi; was_nonfatal;
Int2 oldstatus,
numcols;
QueryInfo qi;
conn = SC_get_conn(self); conn = SC_get_conn(self);
/* Begin a transaction if one is not already in progress */ /* Begin a transaction if one is not already in progress */
/* /*
Basically we don't have to begin a transaction in * Basically we don't have to begin a transaction in autocommit mode
autocommit mode because Postgres backend runs in * because Postgres backend runs in autocomit mode. We issue "BEGIN"
autocomit mode. * in the following cases. 1) we use declare/fetch and the statement
We issue "BEGIN" in the following cases. * is SELECT (because declare/fetch must be called in a transaction).
1) we use declare/fetch and the statement is SELECT * 2) we are not in autocommit state and the statement is of type
(because declare/fetch must be called in a transaction). * UPDATE.
2) we are not in autocommit state and the statement
is of type UPDATE.
*/ */
if ( ! self->internal && ! CC_is_in_trans(conn) && if (!self->internal && !CC_is_in_trans(conn) &&
((globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || (! CC_is_in_autocommit(conn) && STMT_UPDATE(self)))) { ((globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || (!CC_is_in_autocommit(conn) && STMT_UPDATE(self))))
{
mylog(" about to begin a transaction on statement = %u\n", self); mylog(" about to begin a transaction on statement = %u\n", self);
res = CC_send_query(conn, "BEGIN", NULL); res = CC_send_query(conn, "BEGIN", NULL);
if ( ! res) { if (!res)
{
self->errormsg = "Could not begin a transaction"; self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR; self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self); SC_log_error(func, "", self);
...@@ -779,7 +877,8 @@ QueryInfo qi; ...@@ -779,7 +877,8 @@ QueryInfo qi;
QR_Destructor(res); QR_Destructor(res);
if (!ok) { if (!ok)
{
self->errormsg = "Could not begin a transaction"; self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR; self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self); SC_log_error(func, "", self);
...@@ -795,9 +894,14 @@ QueryInfo qi; ...@@ -795,9 +894,14 @@ QueryInfo qi;
/* If it's a SELECT statement, use a cursor. */ /* If it's a SELECT statement, use a cursor. */
/* Note that the declare cursor has already been prepended to the statement */
/*
* Note that the declare cursor has already been prepended to the
* statement
*/
/* in copy_statement... */ /* in copy_statement... */
if (self->statement_type == STMT_TYPE_SELECT) { if (self->statement_type == STMT_TYPE_SELECT)
{
char fetch[128]; char fetch[128];
...@@ -808,38 +912,50 @@ QueryInfo qi; ...@@ -808,38 +912,50 @@ QueryInfo qi;
self->result = CC_send_query(conn, self->stmt_with_params, NULL); self->result = CC_send_query(conn, self->stmt_with_params, NULL);
if (globals.use_declarefetch && self->result != NULL && if (globals.use_declarefetch && self->result != NULL &&
QR_command_successful(self->result)) { QR_command_successful(self->result))
{
QR_Destructor(self->result); QR_Destructor(self->result);
/* That worked, so now send the fetch to start getting data back */ /*
* That worked, so now send the fetch to start getting data
* back
*/
qi.result_in = NULL; qi.result_in = NULL;
qi.cursor = self->cursor_name; qi.cursor = self->cursor_name;
qi.row_size = globals.fetch_max; qi.row_size = globals.fetch_max;
/* Most likely the rowset size will not be set by the application until /*
after the statement is executed, so might as well use the cache size. * Most likely the rowset size will not be set by the
The qr_next_tuple() function will correct for any discrepancies in * application until after the statement is executed, so might
sizes and adjust the cache accordingly. * as well use the cache size. The qr_next_tuple() function
* will correct for any discrepancies in sizes and adjust the
* cache accordingly.
*/ */
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name); sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
self->result = CC_send_query( conn, fetch, &qi); self->result = CC_send_query(conn, fetch, &qi);
} }
mylog(" done sending the query:\n"); mylog(" done sending the query:\n");
} }
else { /* not a SELECT statement so don't use a cursor */ else
{ /* not a SELECT statement so don't use a
* cursor */
mylog(" it's NOT a select statement: stmt=%u\n", self); mylog(" it's NOT a select statement: stmt=%u\n", self);
self->result = CC_send_query(conn, self->stmt_with_params, NULL); self->result = CC_send_query(conn, self->stmt_with_params, NULL);
/* We shouldn't send COMMIT. Postgres backend does the /*
autocommit if neccessary. (Zoltan, 04/26/2000) * We shouldn't send COMMIT. Postgres backend does the autocommit
* if neccessary. (Zoltan, 04/26/2000)
*/ */
/* Even in case of autocommit, started transactions
must be committed. (Hiroshi, 09/02/2001) /*
* Even in case of autocommit, started transactions must be
* committed. (Hiroshi, 09/02/2001)
*/ */
if ( ! self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn) && STMT_UPDATE(self)) { if (!self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn) && STMT_UPDATE(self))
{
res = CC_send_query(conn, "COMMIT", NULL); res = CC_send_query(conn, "COMMIT", NULL);
QR_Destructor(res); QR_Destructor(res);
CC_set_no_trans(conn); CC_set_no_trans(conn);
...@@ -850,17 +966,19 @@ QueryInfo qi; ...@@ -850,17 +966,19 @@ QueryInfo qi;
self->status = STMT_FINISHED; self->status = STMT_FINISHED;
/* Check the status of the result */ /* Check the status of the result */
if (self->result) { if (self->result)
{
was_ok = QR_command_successful(self->result); was_ok = QR_command_successful(self->result);
was_nonfatal = QR_command_nonfatal(self->result); was_nonfatal = QR_command_nonfatal(self->result);
if ( was_ok) if (was_ok)
self->errornumber = STMT_OK; self->errornumber = STMT_OK;
else else
self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND; self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;
self->currTuple = -1; /* set cursor before the first tuple in the list */ self->currTuple = -1; /* set cursor before the first tuple in
* the list */
self->current_col = -1; self->current_col = -1;
self->rowset_start = -1; self->rowset_start = -1;
...@@ -868,9 +986,11 @@ QueryInfo qi; ...@@ -868,9 +986,11 @@ QueryInfo qi;
numcols = QR_NumResultCols(self->result); numcols = QR_NumResultCols(self->result);
/* now allocate the array to hold the binding info */ /* now allocate the array to hold the binding info */
if (numcols > 0) { if (numcols > 0)
{
extend_bindings(self, numcols); extend_bindings(self, numcols);
if (self->bindings == NULL) { if (self->bindings == NULL)
{
self->errornumber = STMT_NO_MEMORY_ERROR; self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "Could not get enough free memory to store the binding information"; self->errormsg = "Could not get enough free memory to store the binding information";
SC_log_error(func, "", self); SC_log_error(func, "", self);
...@@ -878,32 +998,40 @@ QueryInfo qi; ...@@ -878,32 +998,40 @@ QueryInfo qi;
} }
} }
/* in autocommit mode declare/fetch error must be aborted */ /* in autocommit mode declare/fetch error must be aborted */
if ( ! was_ok && ! self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) if (!was_ok && !self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
CC_abort(conn); CC_abort(conn);
} else { /* Bad Error -- The error message will be in the Connection */ }
else
{ /* Bad Error -- The error message will be
* in the Connection */
if (self->statement_type == STMT_TYPE_CREATE) { if (self->statement_type == STMT_TYPE_CREATE)
{
self->errornumber = STMT_CREATE_TABLE_ERROR; self->errornumber = STMT_CREATE_TABLE_ERROR;
self->errormsg = "Error creating the table"; self->errormsg = "Error creating the table";
/* This would allow the table to already exists, thus appending
rows to it. BUT, if the table didn't have the same attributes, /*
it would fail. * This would allow the table to already exists, thus
return SQL_SUCCESS_WITH_INFO; * appending rows to it. BUT, if the table didn't have the
* same attributes, it would fail. return
* SQL_SUCCESS_WITH_INFO;
*/ */
} }
else { else
{
self->errornumber = STMT_EXEC_ERROR; self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Error while executing the query"; self->errormsg = "Error while executing the query";
} }
if ( ! self->internal) if (!self->internal)
CC_abort(conn); CC_abort(conn);
} }
if (self->errornumber == STMT_OK) if (self->errornumber == STMT_OK)
return SQL_SUCCESS; return SQL_SUCCESS;
else { else
{
/* Modified, 2000-04-29, Zoltan */ /* Modified, 2000-04-29, Zoltan */
if (self->errornumber == STMT_INFO_ONLY) if (self->errornumber == STMT_INFO_ONLY)
self->errormsg = "Error while executing the query (non-fatal)"; self->errormsg = "Error while executing the query (non-fatal)";
...@@ -915,12 +1043,13 @@ QueryInfo qi; ...@@ -915,12 +1043,13 @@ QueryInfo qi;
} }
void void
SC_log_error(char *func, char *desc, StatementClass *self) SC_log_error(char *func, char *desc, StatementClass * self)
{ {
#ifdef PRN_NULLCHECK #ifdef PRN_NULLCHECK
#define nullcheck(a) (a ? a : "(NULL)") #define nullcheck(a) (a ? a : "(NULL)")
#endif #endif
if (self) { if (self)
{
qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
qlog(" ------------------------------------------------------------\n"); qlog(" ------------------------------------------------------------\n");
...@@ -937,8 +1066,10 @@ SC_log_error(char *func, char *desc, StatementClass *self) ...@@ -937,8 +1066,10 @@ SC_log_error(char *func, char *desc, StatementClass *self)
qlog(" ----------------QResult Info -------------------------------\n"); qlog(" ----------------QResult Info -------------------------------\n");
if (self->result) { if (self->result)
{
QResultClass *res = self->result; QResultClass *res = self->result;
qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn); qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);
qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor)); qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor));
qlog(" message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice)); qlog(" message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice));
......
...@@ -33,21 +33,28 @@ ...@@ -33,21 +33,28 @@
#define TRUE (BOOL)1 #define TRUE (BOOL)1
#endif #endif
typedef enum { typedef enum
STMT_ALLOCATED, /* The statement handle is allocated, but not used so far */ {
STMT_ALLOCATED, /* The statement handle is allocated, but
* not used so far */
STMT_READY, /* the statement is waiting to be executed */ STMT_READY, /* the statement is waiting to be executed */
STMT_PREMATURE, /* ODBC states that it is legal to call e.g. SQLDescribeCol before STMT_PREMATURE, /* ODBC states that it is legal to call
a call to SQLExecute, but after SQLPrepare. To get all the necessary * e.g. SQLDescribeCol before a call to
information in such a case, we simply execute the query _before_ the * SQLExecute, but after SQLPrepare. To
actual call to SQLExecute, so that statement is considered to be "premature". * get all the necessary information in
*/ * such a case, we simply execute the
* query _before_ the actual call to
* SQLExecute, so that statement is
* considered to be "premature". */
STMT_FINISHED, /* statement execution has finished */ STMT_FINISHED, /* statement execution has finished */
STMT_EXECUTING /* statement execution is still going on */ STMT_EXECUTING /* statement execution is still going on */
} STMT_Status; } STMT_Status;
#define STMT_TRUNCATED -2 #define STMT_TRUNCATED -2
#define STMT_INFO_ONLY -1 /* not an error message, just a notification to be returned by SQLError */ #define STMT_INFO_ONLY -1 /* not an error message, just a
#define STMT_OK 0 /* will be interpreted as "no error pending" */ * notification to be returned by SQLError */
#define STMT_OK 0 /* will be interpreted as "no error
* pending" */
#define STMT_EXEC_ERROR 1 #define STMT_EXEC_ERROR 1
#define STMT_STATUS_ERROR 2 #define STMT_STATUS_ERROR 2
#define STMT_SEQUENCE_ERROR 3 #define STMT_SEQUENCE_ERROR 3
...@@ -77,7 +84,8 @@ typedef enum { ...@@ -77,7 +84,8 @@ typedef enum {
#define STMT_BAD_ERROR 27 #define STMT_BAD_ERROR 27
/* statement types */ /* statement types */
enum { enum
{
STMT_TYPE_UNKNOWN = -2, STMT_TYPE_UNKNOWN = -2,
STMT_TYPE_OTHER = -1, STMT_TYPE_OTHER = -1,
STMT_TYPE_SELECT = 0, STMT_TYPE_SELECT = 0,
...@@ -95,7 +103,8 @@ enum { ...@@ -95,7 +103,8 @@ enum {
/* Parsing status */ /* Parsing status */
enum { enum
{
STMT_PARSE_NONE = 0, STMT_PARSE_NONE = 0,
STMT_PARSE_COMPLETE, STMT_PARSE_COMPLETE,
STMT_PARSE_INCOMPLETE, STMT_PARSE_INCOMPLETE,
...@@ -103,19 +112,22 @@ enum { ...@@ -103,19 +112,22 @@ enum {
}; };
/* Result style */ /* Result style */
enum { enum
{
STMT_FETCH_NONE = 0, STMT_FETCH_NONE = 0,
STMT_FETCH_NORMAL, STMT_FETCH_NORMAL,
STMT_FETCH_EXTENDED, STMT_FETCH_EXTENDED,
}; };
typedef struct { typedef struct
{
COL_INFO *col_info; /* cached SQLColumns info for this table */ COL_INFO *col_info; /* cached SQLColumns info for this table */
char name[MAX_TABLE_LEN+1]; char name[MAX_TABLE_LEN + 1];
char alias[MAX_TABLE_LEN+1]; char alias[MAX_TABLE_LEN + 1];
} TABLE_INFO; } TABLE_INFO;
typedef struct { typedef struct
{
TABLE_INFO *ti; /* resolve to explicit table names */ TABLE_INFO *ti; /* resolve to explicit table names */
int precision; int precision;
int display_size; int display_size;
...@@ -127,15 +139,17 @@ typedef struct { ...@@ -127,15 +139,17 @@ typedef struct {
char quote; char quote;
char dquote; char dquote;
char numeric; char numeric;
char dot[MAX_TABLE_LEN+1]; char dot[MAX_TABLE_LEN + 1];
char name[MAX_COLUMN_LEN+1]; char name[MAX_COLUMN_LEN + 1];
char alias[MAX_COLUMN_LEN+1]; char alias[MAX_COLUMN_LEN + 1];
} FIELD_INFO; } FIELD_INFO;
/******** Statement Handle ***********/ /******** Statement Handle ***********/
struct StatementClass_ { struct StatementClass_
ConnectionClass *hdbc; /* pointer to ConnectionClass this statement belongs to */ {
ConnectionClass *hdbc; /* pointer to ConnectionClass this
* statement belongs to */
QResultClass *result; /* result of the current statement */ QResultClass *result; /* result of the current statement */
HSTMT FAR *phstmt; HSTMT FAR *phstmt;
StatementOptions options; StatementOptions options;
...@@ -153,15 +167,22 @@ struct StatementClass_ { ...@@ -153,15 +167,22 @@ struct StatementClass_ {
int parameters_allocated; int parameters_allocated;
ParameterInfoClass *parameters; ParameterInfoClass *parameters;
Int4 currTuple; /* current absolute row number (GetData, SetPos, SQLFetch) */ Int4 currTuple; /* current absolute row number (GetData,
int save_rowset_size; /* saved rowset size in case of change/FETCH_NEXT */ * SetPos, SQLFetch) */
int rowset_start; /* start of rowset (an absolute row number) */ int save_rowset_size; /* saved rowset size in case of
int bind_row; /* current offset for Multiple row/column binding */ * change/FETCH_NEXT */
int last_fetch_count; /* number of rows retrieved in last fetch/extended fetch */ int rowset_start; /* start of rowset (an absolute row
int current_col; /* current column for GetData -- used to handle multiple calls */ * number) */
int bind_row; /* current offset for Multiple row/column
* binding */
int last_fetch_count; /* number of rows retrieved in
* last fetch/extended fetch */
int current_col; /* current column for GetData -- used to
* handle multiple calls */
int lobj_fd; /* fd of the current large object */ int lobj_fd; /* fd of the current large object */
char *statement; /* if non--null pointer to the SQL statement that has been executed */ char *statement; /* if non--null pointer to the SQL
* statement that has been executed */
TABLE_INFO **ti; TABLE_INFO **ti;
FIELD_INFO **fi; FIELD_INFO **fi;
...@@ -172,19 +193,25 @@ struct StatementClass_ { ...@@ -172,19 +193,25 @@ struct StatementClass_ {
int statement_type; /* According to the defines above */ int statement_type; /* According to the defines above */
int data_at_exec; /* Number of params needing SQLPutData */ int data_at_exec; /* Number of params needing SQLPutData */
int current_exec_param; /* The current parameter for SQLPutData */ int current_exec_param; /* The current parameter for
* SQLPutData */
char put_data; /* Has SQLPutData been called yet? */ char put_data; /* Has SQLPutData been called yet? */
char errormsg_created; /* has an informative error msg been created? */ char errormsg_created; /* has an informative error msg
* been created? */
char manual_result; /* Is the statement result manually built? */ char manual_result; /* Is the statement result manually built? */
char prepare; /* is this statement a prepared statement or direct */ char prepare; /* is this statement a prepared statement
* or direct */
char internal; /* Is this statement being called internally? */ char internal; /* Is this statement being called
* internally? */
char cursor_name[MAX_CURSOR_LEN+1]; char cursor_name[MAX_CURSOR_LEN + 1];
char stmt_with_params[STD_STATEMENT_LEN]; /* statement after parameter substitution */ char stmt_with_params[STD_STATEMENT_LEN]; /* statement after
* parameter
* substitution */
}; };
...@@ -197,22 +224,22 @@ struct StatementClass_ { ...@@ -197,22 +224,22 @@ struct StatementClass_ {
/* Statement prototypes */ /* Statement prototypes */
StatementClass *SC_Constructor(void); StatementClass *SC_Constructor(void);
void InitializeStatementOptions(StatementOptions *opt); void InitializeStatementOptions(StatementOptions * opt);
char SC_Destructor(StatementClass *self); char SC_Destructor(StatementClass * self);
int statement_type(char *statement); int statement_type(char *statement);
char parse_statement(StatementClass *stmt); char parse_statement(StatementClass * stmt);
void SC_pre_execute(StatementClass *self); void SC_pre_execute(StatementClass * self);
char SC_unbind_cols(StatementClass *self); char SC_unbind_cols(StatementClass * self);
char SC_recycle_statement(StatementClass *self); char SC_recycle_statement(StatementClass * self);
void SC_clear_error(StatementClass *self); void SC_clear_error(StatementClass * self);
char SC_get_error(StatementClass *self, int *number, char **message); char SC_get_error(StatementClass * self, int *number, char **message);
char *SC_create_errormsg(StatementClass *self); char *SC_create_errormsg(StatementClass * self);
RETCODE SC_execute(StatementClass *self); RETCODE SC_execute(StatementClass * self);
RETCODE SC_fetch(StatementClass *self); RETCODE SC_fetch(StatementClass * self);
void SC_free_params(StatementClass *self, char option); void SC_free_params(StatementClass * self, char option);
void SC_log_error(char *func, char *desc, StatementClass *self); void SC_log_error(char *func, char *desc, StatementClass * self);
unsigned long SC_get_bookmark(StatementClass *self); unsigned long SC_get_bookmark(StatementClass * self);
#endif #endif
...@@ -18,39 +18,43 @@ ...@@ -18,39 +18,43 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
void set_tuplefield_null(TupleField *tuple_field) void
set_tuplefield_null(TupleField * tuple_field)
{ {
tuple_field->len = 0; tuple_field->len = 0;
tuple_field->value = NULL; /* strdup(""); */ tuple_field->value = NULL; /* strdup(""); */
} }
void set_tuplefield_string(TupleField *tuple_field, char *string) void
set_tuplefield_string(TupleField * tuple_field, char *string)
{ {
tuple_field->len = strlen(string); tuple_field->len = strlen(string);
tuple_field->value = malloc(strlen(string)+1); tuple_field->value = malloc(strlen(string) + 1);
strcpy(tuple_field->value, string); strcpy(tuple_field->value, string);
} }
void set_tuplefield_int2(TupleField *tuple_field, Int2 value) void
set_tuplefield_int2(TupleField * tuple_field, Int2 value)
{ {
char buffer[10]; char buffer[10];
sprintf(buffer,"%d", value); sprintf(buffer, "%d", value);
tuple_field->len = strlen(buffer)+1; tuple_field->len = strlen(buffer) + 1;
/* +1 ... is this correct (better be on the save side-...) */ /* +1 ... is this correct (better be on the save side-...) */
tuple_field->value = strdup(buffer); tuple_field->value = strdup(buffer);
} }
void set_tuplefield_int4(TupleField *tuple_field, Int4 value) void
set_tuplefield_int4(TupleField * tuple_field, Int4 value)
{ {
char buffer[15]; char buffer[15];
sprintf(buffer,"%ld", value); sprintf(buffer, "%ld", value);
tuple_field->len = strlen(buffer)+1; tuple_field->len = strlen(buffer) + 1;
/* +1 ... is this correct (better be on the save side-...) */ /* +1 ... is this correct (better be on the save side-...) */
tuple_field->value = strdup(buffer); tuple_field->value = strdup(buffer);
} }
...@@ -17,14 +17,17 @@ ...@@ -17,14 +17,17 @@
#include "psqlodbc.h" #include "psqlodbc.h"
/* Used by backend data AND manual result sets */ /* Used by backend data AND manual result sets */
struct TupleField_ { struct TupleField_
{
Int4 len; /* length of the current Tuple */ Int4 len; /* length of the current Tuple */
void *value; /* an array representing the value */ void *value; /* an array representing the value */
}; };
/* Used ONLY for manual result sets */ /* Used ONLY for manual result sets */
struct TupleNode_ { struct TupleNode_
struct TupleNode_ *prev, *next; {
struct TupleNode_ *prev,
*next;
TupleField tuple[1]; TupleField tuple[1];
}; };
...@@ -36,9 +39,9 @@ struct TupleNode_ { ...@@ -36,9 +39,9 @@ struct TupleNode_ {
#define set_nullfield_int2(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int2(FLD, (VAL)) : set_tuplefield_null(FLD)) #define set_nullfield_int2(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int2(FLD, (VAL)) : set_tuplefield_null(FLD))
#define set_nullfield_int4(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int4(FLD, (VAL)) : set_tuplefield_null(FLD)) #define set_nullfield_int4(FLD, VAL) ((VAL) != -1 ? set_tuplefield_int4(FLD, (VAL)) : set_tuplefield_null(FLD))
void set_tuplefield_null(TupleField *tuple_field); void set_tuplefield_null(TupleField * tuple_field);
void set_tuplefield_string(TupleField *tuple_field, char *string); void set_tuplefield_string(TupleField * tuple_field, char *string);
void set_tuplefield_int2(TupleField *tuple_field, Int2 value); void set_tuplefield_int2(TupleField * tuple_field, Int2 value);
void set_tuplefield_int4(TupleField *tuple_field, Int4 value); void set_tuplefield_int4(TupleField * tuple_field, Int4 value);
#endif #endif
...@@ -18,12 +18,13 @@ ...@@ -18,12 +18,13 @@
TupleListClass * TupleListClass *
TL_Constructor(UInt4 fieldcnt) TL_Constructor(UInt4 fieldcnt)
{ {
TupleListClass *rv; TupleListClass *rv;
mylog("in TL_Constructor\n"); mylog("in TL_Constructor\n");
rv = (TupleListClass *) malloc(sizeof(TupleListClass)); rv = (TupleListClass *) malloc(sizeof(TupleListClass));
if (rv) { if (rv)
{
rv->num_fields = fieldcnt; rv->num_fields = fieldcnt;
rv->num_tuples = 0; rv->num_tuples = 0;
...@@ -39,19 +40,20 @@ TupleListClass *rv; ...@@ -39,19 +40,20 @@ TupleListClass *rv;
} }
void void
TL_Destructor(TupleListClass *self) TL_Destructor(TupleListClass * self)
{ {
int lf; int lf;
TupleNode *node, *tp; TupleNode *node,
*tp;
mylog("TupleList: in DESTRUCTOR\n"); mylog("TupleList: in DESTRUCTOR\n");
node = self->list_start; node = self->list_start;
while(node != NULL) { while (node != NULL)
for (lf=0; lf < self->num_fields; lf++) {
if (node->tuple[lf].value != NULL) { for (lf = 0; lf < self->num_fields; lf++)
if (node->tuple[lf].value != NULL)
free(node->tuple[lf].value); free(node->tuple[lf].value);
}
tp = node->next; tp = node->next;
free(node); free(node);
node = tp; node = tp;
...@@ -64,12 +66,14 @@ TupleNode *node, *tp; ...@@ -64,12 +66,14 @@ TupleNode *node, *tp;
void * void *
TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno) TL_get_fieldval(TupleListClass * self, Int4 tupleno, Int2 fieldno)
{ {
Int4 lf; Int4 lf;
Int4 delta, from_end; Int4 delta,
char end_is_closer, start_is_closer; from_end;
TupleNode *rv; char end_is_closer,
start_is_closer;
TupleNode *rv;
if (self->last_indexed == -1) if (self->last_indexed == -1)
/* we have an empty tuple list */ /* we have an empty tuple list */
...@@ -84,9 +88,10 @@ TupleNode *rv; ...@@ -84,9 +88,10 @@ TupleNode *rv;
/* illegel field number range */ /* illegel field number range */
return NULL; return NULL;
/* check if we are accessing the same tuple that was used in /*
the last fetch (e.g: for fetching all the fields one after * check if we are accessing the same tuple that was used in the last
another. Do this to speed things up * fetch (e.g: for fetching all the fields one after another. Do this
* to speed things up
*/ */
if (tupleno == self->last_indexed) if (tupleno == self->last_indexed)
return self->lastref->tuple[fieldno].value; return self->lastref->tuple[fieldno].value;
...@@ -94,56 +99,76 @@ TupleNode *rv; ...@@ -94,56 +99,76 @@ TupleNode *rv;
/* now for the tricky part... */ /* now for the tricky part... */
/* /*
Since random access is quite inefficient for linked lists we use * Since random access is quite inefficient for linked lists we use
the lastref pointer that points to the last element referenced * the lastref pointer that points to the last element referenced by a
by a get_fieldval() call in conjunction with the its index number * get_fieldval() call in conjunction with the its index number that
that is stored in last_indexed. (So we use some locality of * is stored in last_indexed. (So we use some locality of reference
reference principle to speed things up) * principle to speed things up)
*/ */
delta = tupleno - self->last_indexed; delta = tupleno - self->last_indexed;
/* if delta is positive, we have to go forward */ /* if delta is positive, we have to go forward */
/* now check if we are closer to the start or the end of the list /*
than to our last_indexed pointer * now check if we are closer to the start or the end of the list than
* to our last_indexed pointer
*/ */
from_end = (self->num_tuples - 1) - tupleno; from_end = (self->num_tuples - 1) - tupleno;
start_is_closer = labs(delta) > tupleno; start_is_closer = labs(delta) > tupleno;
/* true if we are closer to the start of the list than to the
last_indexed pointer /*
* true if we are closer to the start of the list than to the
* last_indexed pointer
*/ */
end_is_closer = labs(delta) > from_end; end_is_closer = labs(delta) > from_end;
/* true if we are closer at the end of the list */ /* true if we are closer at the end of the list */
if (end_is_closer) { if (end_is_closer)
{
/* scanning from the end is the shortest way. so we do that... */ /* scanning from the end is the shortest way. so we do that... */
rv = self->list_end; rv = self->list_end;
for (lf=0; lf < from_end; lf++) for (lf = 0; lf < from_end; lf++)
rv = rv->prev; rv = rv->prev;
} else if (start_is_closer) { }
/* the shortest way is to start the search from the head of the list */ else if (start_is_closer)
{
/*
* the shortest way is to start the search from the head of the
* list
*/
rv = self->list_start; rv = self->list_start;
for (lf=0; lf < tupleno; lf++) for (lf = 0; lf < tupleno; lf++)
rv = rv->next; rv = rv->next;
} else { }
else
{
/* the closest way is starting from our lastref - pointer */ /* the closest way is starting from our lastref - pointer */
rv = self->lastref; rv = self->lastref;
/* at first determine whether we have to search forward or backwards */
if (delta < 0) { /*
* at first determine whether we have to search forward or
* backwards
*/
if (delta < 0)
{
/* we have to search backwards */ /* we have to search backwards */
for(lf=0; lf < (-1)*delta; lf++) for (lf = 0; lf < (-1) * delta; lf++)
rv = rv->prev; rv = rv->prev;
} else { }
else
{
/* ok, we have to search forward... */ /* ok, we have to search forward... */
for (lf=0; lf < delta; lf++) for (lf = 0; lf < delta; lf++)
rv = rv->next; rv = rv->next;
} }
} }
/* now we have got our return pointer, so update the lastref /*
and the last_indexed values * now we have got our return pointer, so update the lastref and the
* last_indexed values
*/ */
self->lastref = rv; self->lastref = rv;
self->last_indexed = tupleno; self->last_indexed = tupleno;
...@@ -154,24 +179,31 @@ TupleNode *rv; ...@@ -154,24 +179,31 @@ TupleNode *rv;
char char
TL_add_tuple(TupleListClass *self, TupleNode *new_field) TL_add_tuple(TupleListClass * self, TupleNode * new_field)
{ {
/* we append the tuple at the end of the doubly linked list
of the tuples we have already read in /*
* we append the tuple at the end of the doubly linked list of the
* tuples we have already read in
*/ */
new_field->prev = NULL; new_field->prev = NULL;
new_field->next = NULL; new_field->next = NULL;
if (self->list_start == NULL) { if (self->list_start == NULL)
{
/* the list is empty, we have to add the first tuple */ /* the list is empty, we have to add the first tuple */
self->list_start = new_field; self->list_start = new_field;
self->list_end = new_field; self->list_end = new_field;
self->lastref = new_field; self->lastref = new_field;
self->last_indexed = 0; self->last_indexed = 0;
} else { }
/* there is already an element in the list, so add the new else
one at the end of the list {
/*
* there is already an element in the list, so add the new one at
* the end of the list
*/ */
self->list_end->next = new_field; self->list_end->next = new_field;
new_field->prev = self->list_end; new_field->prev = self->list_end;
...@@ -182,5 +214,3 @@ TL_add_tuple(TupleListClass *self, TupleNode *new_field) ...@@ -182,5 +214,3 @@ TL_add_tuple(TupleListClass *self, TupleNode *new_field)
/* this method of building a list cannot fail, so we return 1 */ /* this method of building a list cannot fail, so we return 1 */
return 1; return 1;
} }
...@@ -15,10 +15,13 @@ ...@@ -15,10 +15,13 @@
#include "psqlodbc.h" #include "psqlodbc.h"
struct TupleListClass_ { struct TupleListClass_
{
Int4 num_fields; Int4 num_fields;
Int4 num_tuples; Int4 num_tuples;
TupleNode *list_start, *list_end, *lastref; TupleNode *list_start,
*list_end,
*lastref;
Int4 last_indexed; Int4 last_indexed;
}; };
...@@ -26,8 +29,8 @@ struct TupleListClass_ { ...@@ -26,8 +29,8 @@ struct TupleListClass_ {
/* Create a TupleList. Each tuple consits of fieldcnt columns */ /* Create a TupleList. Each tuple consits of fieldcnt columns */
TupleListClass *TL_Constructor(UInt4 fieldcnt); TupleListClass *TL_Constructor(UInt4 fieldcnt);
void TL_Destructor(TupleListClass *self); void TL_Destructor(TupleListClass * self);
void *TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno); void *TL_get_fieldval(TupleListClass * self, Int4 tupleno, Int2 fieldno);
char TL_add_tuple(TupleListClass *self, TupleNode *new_field); char TL_add_tuple(TupleListClass * self, TupleNode * new_field);
#endif #endif
...@@ -3,7 +3,7 @@ This can format all PostgreSQL *.c and *.h files, excluding libpq++, ...@@ -3,7 +3,7 @@ This can format all PostgreSQL *.c and *.h files, excluding libpq++,
On 09/06/1997, from the top directory, I ran: On 09/06/1997, from the top directory, I ran:
find . -name '*.[ch]' -type f -print | egrep -v '\+\+|/odbc/|s_lock.h' | xargs -n100 pgindent find . -name '*.[ch]' -type f -print | egrep -v '\+\+|s_lock.h' | xargs -n100 pgindent
The stock BSD indent has two bugs. First, a comment after the word 'else' The stock BSD indent has two bugs. First, a comment after the word 'else'
causes the rest of the file to be ignored. Second, it silently ignores causes the rest of the file to be ignored. Second, it silently ignores
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment