Update to v.0246

This commit is contained in:
Byron Nikolaidis 1998-06-16 21:29:19 +00:00
parent fd262dac8c
commit a80771f0a7
20 changed files with 842 additions and 422 deletions

View File

@ -37,9 +37,12 @@ RETCODE SQL_API SQLBindParameter(
SDWORD FAR *pcbValue)
{
StatementClass *stmt = (StatementClass *) hstmt;
char *func="SQLBindParameter";
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if(stmt->parameters_allocated < ipar) {
ParameterInfoClass *old_parameters;
@ -52,6 +55,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
if ( ! stmt->parameters) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Could not allocate memory for statement parameters";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -133,53 +137,51 @@ RETCODE SQL_API SQLBindCol(
SDWORD FAR *pcbValue)
{
StatementClass *stmt = (StatementClass *) hstmt;
Int2 numcols;
Int2 numcols = 0;
char *func="SQLBindCol";
mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (icol < 1) {
/* currently we do not support bookmarks */
stmt->errormsg = "Bookmarks are not currently supported.";
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
icol--; /* use zero based col numbers */
SC_clear_error(stmt);
if( ! stmt->result) {
stmt->errormsg = "Can't bind columns with a NULL query result structure.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
return SQL_ERROR;
}
if( stmt->status == STMT_EXECUTING) {
stmt->errormsg = "Can't bind columns while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
numcols = QR_NumResultCols(stmt->result);
mylog("SQLBindCol: numcols = %d\n", numcols);
if (icol >= numcols) {
stmt->errornumber = STMT_COLNUM_ERROR;
stmt->errormsg = "Column number too big";
return SQL_ERROR;
}
// allocate enough bindings if not already done
// Most likely, execution of a statement would have setup the
// necessary bindings. But some apps call BindCol before any
// statement is executed.
if ( icol > stmt->bindings_allocated)
extend_bindings(stmt, icol);
// check to see if the bindings were allocated
if ( ! stmt->bindings) {
stmt->errormsg = "Bindings were not allocated properly.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Could not allocate memory for bindings.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
if ((cbValueMax == 0) || (rgbValue == NULL)) {
icol--; /* use zero based col numbers from here out */
if (rgbValue == NULL) {
/* we have to unbind the column */
stmt->bindings[icol].buflen = 0;
stmt->bindings[icol].buffer = NULL;
@ -216,13 +218,17 @@ RETCODE SQL_API SQLDescribeParam(
SWORD FAR *pfNullable)
{
StatementClass *stmt = (StatementClass *) hstmt;
char *func = "SQLDescribeParam";
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) {
stmt->errormsg = "Invalid parameter number for SQLDescribeParam.";
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -254,6 +260,9 @@ RETCODE SQL_API SQLParamOptions(
UDWORD crow,
UDWORD FAR *pirow)
{
char *func = "SQLParamOptions";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
@ -273,21 +282,26 @@ RETCODE SQL_API SQLNumParams(
StatementClass *stmt = (StatementClass *) hstmt;
char in_quote = FALSE;
unsigned int i;
char *func = "SQLNumParams";
if(!stmt)
if(!stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (pcpar)
*pcpar = 0;
else
else {
SC_log_error(func, "pcpar was null", stmt);
return SQL_ERROR;
}
if(!stmt->statement) {
// no statement has been allocated
stmt->errormsg = "SQLNumParams called with no statement ready.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
} else {
@ -341,6 +355,14 @@ mylog("in extend_bindings: stmt=%u, bindings_allocated=%d, num_columns=%d\n", st
if(stmt->bindings_allocated < num_columns) {
new_bindings = create_empty_bindings(num_columns);
if ( ! new_bindings) {
if (stmt->bindings) {
free(stmt->bindings);
stmt->bindings = NULL;
}
stmt->bindings_allocated = 0;
return;
}
if(stmt->bindings) {
for(i=0; i<stmt->bindings_allocated; i++)
@ -349,18 +371,17 @@ mylog("in extend_bindings: stmt=%u, bindings_allocated=%d, num_columns=%d\n", st
free(stmt->bindings);
}
stmt->bindings = new_bindings; // null indicates error
stmt->bindings = new_bindings;
stmt->bindings_allocated = num_columns;
} else {
/* if we have too many, make sure the extra ones are emptied out */
/* so we don't accidentally try to use them for anything */
for(i = num_columns; i < stmt->bindings_allocated; i++) {
stmt->bindings[i].buflen = 0;
stmt->bindings[i].buffer = NULL;
stmt->bindings[i].used = NULL;
}
}
}
// There is no reason to zero out extra bindings if there are
// more than needed. If an app has allocated extra bindings,
// let it worry about it by unbinding those columns.
// SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings
// SQLExecDirect(...) # returns 5 cols
// SQLExecDirect(...) # returns 10 cols (now OK)
mylog("exit extend_bindings\n");
}

View File

@ -35,7 +35,7 @@ RETCODE SQL_API SQLAllocConnect(
{
EnvironmentClass *env = (EnvironmentClass *)henv;
ConnectionClass *conn;
char *func="SQLAllocConnect";
conn = CC_Constructor();
mylog("**** SQLAllocConnect: henv = %u, conn = %u\n", henv, conn);
@ -44,6 +44,7 @@ ConnectionClass *conn;
env->errormsg = "Couldn't allocate memory for Connection object.";
env->errornumber = ENV_ALLOC_ERROR;
*phdbc = SQL_NULL_HDBC;
EN_log_error(func, "", env);
return SQL_ERROR;
}
@ -52,6 +53,7 @@ ConnectionClass *conn;
env->errornumber = ENV_ALLOC_ERROR;
CC_Destructor(conn);
*phdbc = SQL_NULL_HDBC;
EN_log_error(func, "", env);
return SQL_ERROR;
}
@ -74,9 +76,12 @@ RETCODE SQL_API SQLConnect(
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
char *func = "SQLConnect";
if ( ! conn)
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
ci = &conn->connInfo;
@ -96,9 +101,11 @@ ConnInfo *ci;
qlog("conn = %u, SQLConnect(DSN='%s', UID='%s', PWD='%s')\n", ci->dsn, ci->username, ci->password);
if ( CC_connect(conn, FALSE) <= 0)
if ( CC_connect(conn, FALSE) <= 0) {
// Error messages are filled in
CC_log_error(func, "Error on CC_connect", conn);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
@ -123,17 +130,21 @@ RETCODE SQL_API SQLDisconnect(
HDBC hdbc)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
char *func = "SQLDisconnect";
mylog("**** in SQLDisconnect\n");
if ( ! conn)
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
qlog("conn=%u, SQLDisconnect\n", conn);
if (conn->status == CONN_EXECUTING) {
conn->errornumber = CONN_IN_USE;
conn->errormsg = "A transaction is currently being executed";
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -155,16 +166,20 @@ RETCODE SQL_API SQLFreeConnect(
HDBC hdbc)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
char *func = "SQLFreeConnect";
mylog("**** in SQLFreeConnect: hdbc=%u\n", hdbc);
if ( ! conn)
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/* Remove the connection from the environment */
if ( ! EN_remove_connection(conn->henv, conn)) {
conn->errornumber = CONN_IN_USE;
conn->errormsg = "A transaction is currently being executed";
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -577,8 +592,9 @@ char salt[2];
/******* Send any initial settings *********/
/**********************************************/
if ( ! CC_send_settings(self))
return 0;
// The Unix iodbc errors out on this call because it allocates a statement
// before the connection is established. Therefore, don't check for error here.
CC_send_settings(self);
CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
@ -1155,6 +1171,27 @@ RETCODE result;
result = SQLFreeStmt(hstmt, SQL_DROP);
}
void
CC_log_error(char *func, char *desc, ConnectionClass *self)
{
if (self) {
qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
qlog(" ------------------------------------------------------------\n");
qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
qlog(" ---------------- Socket Info -------------------------------\n");
if (self->sock) {
SocketClass *sock = self->sock;
qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, sock->errormsg);
qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
}
}
else
qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}
/*
void
CC_test(ConnectionClass *self)
@ -1165,23 +1202,28 @@ SDWORD pcbValue;
UDWORD pcrow;
UWORD rgfRowStatus;
char buf[255];
SDWORD buflen;
DATE_STRUCT *ds;
result = SQLAllocStmt( self, &hstmt1);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
return;
}
result = SQLExtendedFetch(hstmt1, SQL_FETCH_ABSOLUTE, -2, &pcrow, &rgfRowStatus);
SQLGetData(hstmt1, 1, SQL_C_CHAR, buf, sizeof(buf), &pcbValue);
qlog("FETCH_ABSOLUTE, -2: result=%d, Col1 = '%s'\n", result, buf);
result = SQLExecDirect(hstmt1, "select * from cpar", SQL_NTS);
qlog("exec result = %d\n", result);
result = SQLBindCol(hstmt1, 2, SQL_C_DATE, buf, 0, &buflen);
qlog("bind result = %d\n", result);
result = SQLFetch(hstmt1);
while (result != SQL_NO_DATA_FOUND) {
ds = (DATE_STRUCT *) buf;
qlog("fetch on stmt1: result=%d, buflen=%d: year=%d, month=%d, day=%d\n", result, buflen, ds->year, ds->month, ds->day);
result = SQLFetch(hstmt1);
qlog("fetch on stmt1\n");
}
SQLFreeStmt(hstmt1, SQL_DROP);
}
*/

View File

@ -133,6 +133,7 @@ typedef struct {
// char unknown_sizes[SMALL_REGISTRY_LEN];
char fake_oid_index[SMALL_REGISTRY_LEN];
char show_oid_column[SMALL_REGISTRY_LEN];
char row_versioning[SMALL_REGISTRY_LEN];
char show_system_tables[SMALL_REGISTRY_LEN];
char focus_password;
} ConnInfo;
@ -188,5 +189,6 @@ char *CC_create_errormsg(ConnectionClass *self);
int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
char CC_send_settings(ConnectionClass *self);
void CC_lookup_lo(ConnectionClass *conn);
void CC_log_error(char *func, char *desc, ConnectionClass *self);
#endif

View File

@ -94,289 +94,272 @@ struct tm *tim;
st.y = tim->tm_year + 1900;
mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, value, cbValueMax);
if(value) {
/********************************************************************
First convert any specific postgres types into more
useable data.
NOTE: Conversions from PG char/varchar of a date/time/timestamp
value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*********************************************************************/
switch(field_type) {
/* $$$ need to add parsing for date/time/timestamp strings in PG_TYPE_CHAR,VARCHAR $$$ */
case PG_TYPE_DATE:
sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
break;
case PG_TYPE_TIME:
sscanf(value, "%2d:%2d:%2d", &st.hh, &st.mm, &st.ss);
break;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
if (strnicmp(value, "invalid", 7) != 0) {
sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
} else { /* The timestamp is invalid so set something conspicuous, like the epoch */
t = 0;
tim = localtime(&t);
st.m = tim->tm_mon + 1;
st.d = tim->tm_mday;
st.y = tim->tm_year + 1900;
st.hh = tim->tm_hour;
st.mm = tim->tm_min;
st.ss = tim->tm_sec;
}
break;
case PG_TYPE_BOOL: { /* change T/F to 1/0 */
char *s = (char *) value;
if (s[0] == 'T' || s[0] == 't')
s[0] = '1';
else
s[0] = '0';
}
break;
/* This is for internal use by SQLStatistics() */
case PG_TYPE_INT28: {
// this is an array of eight integers
short *short_array = (short *)rgbValue;
len = 16;
sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
&short_array[0],
&short_array[1],
&short_array[2],
&short_array[3],
&short_array[4],
&short_array[5],
&short_array[6],
&short_array[7]);
/* There is no corresponding fCType for this. */
if(pcbValue)
*pcbValue = len;
return COPY_OK; /* dont go any further or the data will be trashed */
}
/* This is a large object OID, which is used to store LONGVARBINARY objects. */
case PG_TYPE_LO:
return convert_lo( stmt, value, fCType, rgbValue, cbValueMax, pcbValue, multiple);
default:
if (field_type == stmt->hdbc->lobj_type) /* hack until permanent type available */
return convert_lo( stmt, value, fCType, rgbValue, cbValueMax, pcbValue, multiple);
}
/* Change default into something useable */
if (fCType == SQL_C_DEFAULT) {
fCType = pgtype_to_ctype(stmt, field_type);
mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
}
if(fCType == SQL_C_CHAR) {
/* Special character formatting as required */
switch(field_type) {
case PG_TYPE_DATE:
len = 11;
if (cbValueMax >= len)
sprintf((char *)rgbValue, "%.4d-%.2d-%.2d", st.y, st.m, st.d);
break;
case PG_TYPE_TIME:
len = 9;
if (cbValueMax >= len)
sprintf((char *)rgbValue, "%.2d:%.2d:%.2d", st.hh, st.mm, st.ss);
break;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
len = 19;
if (cbValueMax >= len)
sprintf((char *) rgbValue, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
st.y, st.m, st.d, st.hh, st.mm, st.ss);
break;
case PG_TYPE_BOOL:
len = 1;
if (cbValueMax > len) {
strcpy((char *) rgbValue, value);
mylog("PG_TYPE_BOOL: rgbValue = '%s'\n", rgbValue);
}
break;
case PG_TYPE_BYTEA: // convert binary data to hex strings (i.e, 255 = "FF")
len = convert_pgbinary_to_char(value, rgbValue, cbValueMax);
break;
default:
/* convert linefeeds to carriage-return/linefeed */
convert_linefeeds( (char *) value, rgbValue, cbValueMax);
len = strlen(rgbValue);
mylog(" SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValue = '%s'\n", len, cbValueMax, rgbValue);
break;
}
} else {
/* for SQL_C_CHAR, its 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)
convert_money(value);
switch(fCType) {
case SQL_C_DATE:
len = 6;
if (cbValueMax >= len) {
DATE_STRUCT *ds = (DATE_STRUCT *) rgbValue;
ds->year = st.y;
ds->month = st.m;
ds->day = st.d;
}
break;
case SQL_C_TIME:
len = 6;
if (cbValueMax >= len) {
TIME_STRUCT *ts = (TIME_STRUCT *) rgbValue;
ts->hour = st.hh;
ts->minute = st.mm;
ts->second = st.ss;
}
break;
case SQL_C_TIMESTAMP:
len = 16;
if (cbValueMax >= len) {
TIMESTAMP_STRUCT *ts = (TIMESTAMP_STRUCT *) rgbValue;
ts->year = st.y;
ts->month = st.m;
ts->day = st.d;
ts->hour = st.hh;
ts->minute = st.mm;
ts->second = st.ss;
ts->fraction = 0;
}
break;
case SQL_C_BIT:
len = 1;
if (cbValueMax >= len || field_type == PG_TYPE_BOOL) {
*((UCHAR *)rgbValue) = atoi(value);
mylog("SQL_C_BIT: val = %d, cb = %d, rgb=%d\n", atoi(value), cbValueMax, *((UCHAR *)rgbValue));
}
break;
case SQL_C_STINYINT:
case SQL_C_TINYINT:
len = 1;
if (cbValueMax >= len)
*((SCHAR *) rgbValue) = atoi(value);
break;
case SQL_C_UTINYINT:
len = 1;
if (cbValueMax >= len)
*((UCHAR *) rgbValue) = atoi(value);
break;
case SQL_C_FLOAT:
len = 4;
if(cbValueMax >= len)
*((SFLOAT *)rgbValue) = (float) atof(value);
break;
case SQL_C_DOUBLE:
len = 8;
if(cbValueMax >= len)
*((SDOUBLE *)rgbValue) = atof(value);
break;
case SQL_C_SSHORT:
case SQL_C_SHORT:
len = 2;
if(cbValueMax >= len)
*((SWORD *)rgbValue) = atoi(value);
break;
case SQL_C_USHORT:
len = 2;
if(cbValueMax >= len)
*((UWORD *)rgbValue) = atoi(value);
break;
case SQL_C_SLONG:
case SQL_C_LONG:
len = 4;
if(cbValueMax >= len)
*((SDWORD *)rgbValue) = atol(value);
break;
case SQL_C_ULONG:
len = 4;
if(cbValueMax >= len)
*((UDWORD *)rgbValue) = atol(value);
break;
case SQL_C_BINARY:
// truncate if necessary
// convert octal escapes to bytes
len = convert_from_pgbinary(value, rgbValue, cbValueMax);
mylog("SQL_C_BINARY: len = %d\n", len);
break;
default:
return COPY_UNSUPPORTED_TYPE;
}
}
} else {
if ( ! value) {
/* handle a null just by returning SQL_NULL_DATA in pcbValue, */
/* and doing nothing to the buffer. */
if(pcbValue) {
*pcbValue = SQL_NULL_DATA;
}
}
// store the length of what was copied, if there's a place for it
// unless it was a NULL (in which case it was already set above)
if(pcbValue && value)
*pcbValue = len;
if(len > cbValueMax) {
mylog("!!! COPY_RESULT_TRUNCATED !!!\n");
// Don't return truncated because an application
// (like Access) will try to call GetData again
// to retrieve the rest of the data. Since we
// are not currently ready for this, and the result
// is an endless loop, we better just silently
// truncate the data.
// return COPY_RESULT_TRUNCATED;
// LongVarBinary types do handle truncated multiple get calls
// through convert_lo().
if (pcbValue)
*pcbValue = cbValueMax -1;
return COPY_OK;
}
/********************************************************************
First convert any specific postgres types into more
useable data.
NOTE: Conversions from PG char/varchar of a date/time/timestamp
value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*********************************************************************/
switch(field_type) {
/* $$$ need to add parsing for date/time/timestamp strings in PG_TYPE_CHAR,VARCHAR $$$ */
case PG_TYPE_DATE:
sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
break;
case PG_TYPE_TIME:
sscanf(value, "%2d:%2d:%2d", &st.hh, &st.mm, &st.ss);
break;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
if (strnicmp(value, "invalid", 7) != 0) {
sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
} else { /* The timestamp is invalid so set something conspicuous, like the epoch */
t = 0;
tim = localtime(&t);
st.m = tim->tm_mon + 1;
st.d = tim->tm_mday;
st.y = tim->tm_year + 1900;
st.hh = tim->tm_hour;
st.mm = tim->tm_min;
st.ss = tim->tm_sec;
}
break;
case PG_TYPE_BOOL: { /* change T/F to 1/0 */
char *s = (char *) value;
if (s[0] == 'T' || s[0] == 't')
s[0] = '1';
else
s[0] = '0';
}
break;
/* This is for internal use by SQLStatistics() */
case PG_TYPE_INT28: {
// this is an array of eight integers
short *short_array = (short *)rgbValue;
len = 16;
sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
&short_array[0],
&short_array[1],
&short_array[2],
&short_array[3],
&short_array[4],
&short_array[5],
&short_array[6],
&short_array[7]);
/* There is no corresponding fCType for this. */
if(pcbValue)
*pcbValue = len;
return COPY_OK; /* dont go any further or the data will be trashed */
}
/* This is a large object OID, which is used to store LONGVARBINARY objects. */
case PG_TYPE_LO:
return convert_lo( stmt, value, fCType, rgbValue, cbValueMax, pcbValue, multiple);
default:
if (field_type == stmt->hdbc->lobj_type) /* hack until permanent type available */
return convert_lo( stmt, value, fCType, rgbValue, cbValueMax, pcbValue, multiple);
}
/* Change default into something useable */
if (fCType == SQL_C_DEFAULT) {
fCType = pgtype_to_ctype(stmt, field_type);
mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
}
if(fCType == SQL_C_CHAR) {
/* Special character formatting as required */
/* These really should return error if cbValueMax is not big enough. */
switch(field_type) {
case PG_TYPE_DATE:
len = 10;
if (cbValueMax > len)
sprintf((char *)rgbValue, "%.4d-%.2d-%.2d", st.y, st.m, st.d);
break;
case PG_TYPE_TIME:
len = 8;
if (cbValueMax > len)
sprintf((char *)rgbValue, "%.2d:%.2d:%.2d", st.hh, st.mm, st.ss);
break;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
len = 19;
if (cbValueMax > len)
sprintf((char *) rgbValue, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
st.y, st.m, st.d, st.hh, st.mm, st.ss);
break;
case PG_TYPE_BOOL:
len = 1;
if (cbValueMax > len) {
strcpy((char *) rgbValue, value);
mylog("PG_TYPE_BOOL: rgbValue = '%s'\n", rgbValue);
}
break;
/* Currently, data is SILENTLY TRUNCATED for BYTEA and character data
types if there is not enough room in cbValueMax because the driver
can't handle multiple calls to SQLGetData for these, yet. Most likely,
the buffer passed in will be big enough to handle the maximum limit of
postgres, anyway.
LongVarBinary types are handled correctly above, observing truncation
and all that stuff since there is essentially no limit on the large
object used to store those.
*/
case PG_TYPE_BYTEA: // convert binary data to hex strings (i.e, 255 = "FF")
len = convert_pgbinary_to_char(value, rgbValue, cbValueMax);
break;
default:
/* convert linefeeds to carriage-return/linefeed */
convert_linefeeds( (char *) value, rgbValue, cbValueMax);
len = strlen(rgbValue);
mylog(" SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValue = '%s'\n", len, cbValueMax, rgbValue);
break;
}
} else {
return COPY_OK;
}
/* for SQL_C_CHAR, its 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)
convert_money(value);
switch(fCType) {
case SQL_C_DATE:
len = 6;
{
DATE_STRUCT *ds = (DATE_STRUCT *) rgbValue;
ds->year = st.y;
ds->month = st.m;
ds->day = st.d;
}
break;
case SQL_C_TIME:
len = 6;
{
TIME_STRUCT *ts = (TIME_STRUCT *) rgbValue;
ts->hour = st.hh;
ts->minute = st.mm;
ts->second = st.ss;
}
break;
case SQL_C_TIMESTAMP:
len = 16;
{
TIMESTAMP_STRUCT *ts = (TIMESTAMP_STRUCT *) rgbValue;
ts->year = st.y;
ts->month = st.m;
ts->day = st.d;
ts->hour = st.hh;
ts->minute = st.mm;
ts->second = st.ss;
ts->fraction = 0;
}
break;
case SQL_C_BIT:
len = 1;
*((UCHAR *)rgbValue) = atoi(value);
mylog("SQL_C_BIT: val = %d, cb = %d, rgb=%d\n", atoi(value), cbValueMax, *((UCHAR *)rgbValue));
break;
case SQL_C_STINYINT:
case SQL_C_TINYINT:
len = 1;
*((SCHAR *) rgbValue) = atoi(value);
break;
case SQL_C_UTINYINT:
len = 1;
*((UCHAR *) rgbValue) = atoi(value);
break;
case SQL_C_FLOAT:
len = 4;
*((SFLOAT *)rgbValue) = (float) atof(value);
break;
case SQL_C_DOUBLE:
len = 8;
*((SDOUBLE *)rgbValue) = atof(value);
break;
case SQL_C_SSHORT:
case SQL_C_SHORT:
len = 2;
*((SWORD *)rgbValue) = atoi(value);
break;
case SQL_C_USHORT:
len = 2;
*((UWORD *)rgbValue) = atoi(value);
break;
case SQL_C_SLONG:
case SQL_C_LONG:
len = 4;
*((SDWORD *)rgbValue) = atol(value);
break;
case SQL_C_ULONG:
len = 4;
*((UDWORD *)rgbValue) = atol(value);
break;
case SQL_C_BINARY:
// truncate if necessary
// convert octal escapes to bytes
len = convert_from_pgbinary(value, rgbValue, cbValueMax);
mylog("SQL_C_BINARY: len = %d\n", len);
break;
default:
return COPY_UNSUPPORTED_TYPE;
}
}
// store the length of what was copied, if there's a place for it
if(pcbValue)
*pcbValue = len;
return COPY_OK;
}
/* This function inserts parameters into an SQL statements.
@ -386,6 +369,7 @@ struct tm *tim;
int
copy_statement_with_parameters(StatementClass *stmt)
{
char *func="copy_statement_with_parameters";
unsigned int opos, npos;
char param_string[128], tmp[256], cbuf[TEXT_FIELD_SIZE+5];
int param_number;
@ -400,8 +384,10 @@ char *buffer, *buf;
char in_quote = FALSE;
if ( ! old_statement)
if ( ! old_statement) {
SC_log_error(func, "No statement string", stmt);
return SQL_ERROR;
}
memset(&st, 0, sizeof(SIMPLE_TIME));
@ -624,6 +610,7 @@ char in_quote = FALSE;
stmt->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
new_statement[npos] = '\0'; // just in case
SC_log_error(func, "", stmt);
return SQL_ERROR;
}

View File

@ -226,6 +226,7 @@ char buf[128];
CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables));
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column));
@ -273,6 +274,8 @@ char buf[128];
sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING));
/* OID Options*/
sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX));
sprintf(ci->show_oid_column, "%d", IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
@ -297,7 +300,7 @@ makeConnectString(char *connect_string, ConnInfo *ci)
{
char got_dsn = (ci->dsn[0] != '\0');
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;READONLY=%s;PWD=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s",
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;READONLY=%s;PWD=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s",
got_dsn ? "DSN" : "DRIVER",
got_dsn ? ci->dsn : ci->driver,
ci->database,
@ -310,6 +313,7 @@ char got_dsn = (ci->dsn[0] != '\0');
// ci->unknown_sizes, -- currently only needed in Driver options.
ci->fake_oid_index,
ci->show_oid_column,
ci->row_versioning,
ci->show_system_tables,
ci->conn_settings);
}
@ -355,6 +359,9 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0)
strcpy(ci->fake_oid_index, value);
else if (stricmp(attribute, INI_ROWVERSIONING) == 0)
strcpy(ci->row_versioning, value);
else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0)
strcpy(ci->show_system_tables, value);
@ -398,6 +405,8 @@ getDSNdefaults(ConnInfo *ci)
if (ci->show_system_tables[0] == '\0')
sprintf(ci->show_system_tables, "%d", DEFAULT_SHOWSYSTEMTABLES);
if (ci->row_versioning[0] == '\0')
sprintf(ci->row_versioning, "%d", DEFAULT_ROWVERSIONING);
}
@ -448,6 +457,9 @@ char *DSN = ci->dsn;
if ( ci->fake_oid_index[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_FAKEOIDINDEX, "", ci->fake_oid_index, sizeof(ci->fake_oid_index), ODBC_INI);
if ( ci->row_versioning[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_ROWVERSIONING, "", ci->row_versioning, sizeof(ci->row_versioning), ODBC_INI);
if ( ci->show_system_tables[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_SHOWSYSTEMTABLES, "", ci->show_system_tables, sizeof(ci->show_system_tables), ODBC_INI);
@ -533,6 +545,11 @@ char *DSN = ci->dsn;
ci->fake_oid_index,
ODBC_INI);
SQLWritePrivateProfileString(DSN,
INI_ROWVERSIONING,
ci->row_versioning,
ODBC_INI);
SQLWritePrivateProfileString(DSN,
INI_SHOWSYSTEMTABLES,
ci->show_system_tables,

View File

@ -55,6 +55,7 @@
#define INI_FAKEOIDINDEX "FakeOidIndex"
#define INI_SHOWOIDCOLUMN "ShowOidColumn"
#define INI_ROWVERSIONING "RowVersioning"
#define INI_SHOWSYSTEMTABLES "ShowSystemTables"
#define INI_LIE "Lie"
#define INI_EXTRASYSTABLEPREFIXES "ExtraSysTablePrefixes"
@ -74,6 +75,7 @@
#define DEFAULT_FAKEOIDINDEX 0
#define DEFAULT_SHOWOIDCOLUMN 0
#define DEFAULT_ROWVERSIONING 0
#define DEFAULT_SHOWSYSTEMTABLES 0 // dont show system tables
#define DEFAULT_LIE 0

View File

@ -47,6 +47,7 @@ RETCODE SQL_API SQLDriverConnect(
SWORD FAR *pcbConnStrOut,
UWORD fDriverCompletion)
{
char *func = "SQLDriverConnect";
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
RETCODE dialog_result;
@ -56,8 +57,10 @@ char password_required = FALSE;
mylog("**** SQLDriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, szConnStrIn);
if ( ! conn)
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
qlog("conn=%u, SQLDriverConnect( in)='%s'\n", conn, szConnStrIn);
@ -135,8 +138,10 @@ dialog:
// do the actual connect
retval = CC_connect(conn, password_required);
if (retval < 0) { /* need a password */
if (fDriverCompletion == SQL_DRIVER_NOPROMPT)
if (fDriverCompletion == SQL_DRIVER_NOPROMPT) {
CC_log_error(func, "Need password but Driver_NoPrompt", conn);
return SQL_ERROR; /* need a password but not allowed to prompt so error */
}
else {
password_required = TRUE;
goto dialog;
@ -144,6 +149,7 @@ dialog:
}
else if (retval == 0) {
// error msg filled in above
CC_log_error(func, "Error from CC_Connect", conn);
return SQL_ERROR;
}

View File

@ -25,11 +25,14 @@ ConnectionClass *conns[MAX_CONNECTIONS];
RETCODE SQL_API SQLAllocEnv(HENV FAR *phenv)
{
char *func = "SQLAllocEnv";
mylog("**** in SQLAllocEnv ** \n");
*phenv = (HENV) EN_Constructor();
if ( ! *phenv) {
*phenv = SQL_NULL_HENV;
EN_log_error(func, "Error allocating environment", NULL);
return SQL_ERROR;
}
@ -39,6 +42,7 @@ mylog("**** in SQLAllocEnv ** \n");
RETCODE SQL_API SQLFreeEnv(HENV henv)
{
char *func = "SQLFreeEnv";
EnvironmentClass *env = (EnvironmentClass *) henv;
mylog("**** in SQLFreeEnv: env = %u ** \n", env);
@ -49,6 +53,7 @@ mylog("**** in SQLFreeEnv: env = %u ** \n", env);
}
mylog(" error\n");
EN_log_error(func, "Error freeing environment", env);
return SQL_ERROR;
}
@ -73,9 +78,6 @@ int status;
// CC: return an error of a hstmt
StatementClass *stmt = (StatementClass *) hstmt;
if (NULL == stmt)
return SQL_INVALID_HANDLE;
if (SC_get_error(stmt, &status, &msg)) {
mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg) {
@ -424,3 +426,13 @@ int i;
return FALSE;
}
void
EN_log_error(char *func, char *desc, EnvironmentClass *self)
{
if (self) {
qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
}
else
qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}

View File

@ -29,5 +29,6 @@ char EN_Destructor(EnvironmentClass *self);
char EN_get_error(EnvironmentClass *self, int *number, char **message);
char EN_add_connection(EnvironmentClass *self, ConnectionClass *conn);
char EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn);
void EN_log_error(char *func, char *desc, EnvironmentClass *self);
#endif

View File

@ -32,10 +32,13 @@ RETCODE SQL_API SQLPrepare(HSTMT hstmt,
UCHAR FAR *szSqlStr,
SDWORD cbSqlStr)
{
char *func = "SQLPrepare";
StatementClass *self = (StatementClass *) hstmt;
if ( ! self)
if ( ! self) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/* According to the ODBC specs it is valid to call SQLPrepare mulitple times.
In that case, the bound SQL statement is replaced by the new one
@ -66,12 +69,14 @@ StatementClass *self = (StatementClass *) hstmt;
self->errornumber = STMT_SEQUENCE_ERROR;
self->errormsg = "SQLPrepare(): The handle does not point to a statement that is ready to be executed";
SC_log_error(func, "", self);
return SQL_ERROR;
default:
self->errornumber = STMT_INTERNAL_ERROR;
self->errormsg = "An Internal Error has occured -- Unknown statement status.";
SC_log_error(func, "", self);
return SQL_ERROR;
}
@ -82,6 +87,7 @@ StatementClass *self = (StatementClass *) hstmt;
if ( ! self->statement) {
self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "No memory available to store statement";
SC_log_error(func, "", self);
return SQL_ERROR;
}
@ -92,6 +98,7 @@ StatementClass *self = (StatementClass *) hstmt;
if ( CC_is_readonly(self->hdbc) && STMT_UPDATE(self)) {
self->errornumber = STMT_EXEC_ERROR;
self->errormsg = "Connection is readonly, only select statements are allowed.";
SC_log_error(func, "", self);
return SQL_ERROR;
}
@ -110,9 +117,12 @@ RETCODE SQL_API SQLExecDirect(
SDWORD cbSqlStr)
{
StatementClass *stmt = (StatementClass *) hstmt;
char *func = "SQLExecDirect";
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (stmt->statement)
free(stmt->statement);
@ -123,6 +133,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
if ( ! stmt->statement) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "No memory available to store statement";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -135,6 +146,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
if ( CC_is_readonly(stmt->hdbc) && STMT_UPDATE(stmt)) {
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Connection is readonly, only select statements are allowed.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -147,13 +159,16 @@ StatementClass *stmt = (StatementClass *) hstmt;
RETCODE SQL_API SQLExecute(
HSTMT hstmt)
{
char *func="SQLExecute";
StatementClass *stmt = (StatementClass *) hstmt;
ConnectionClass *conn;
int i, retval;
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/* If the statement is premature, it means we already executed
it from an SQLPrepare/SQLDescribeCol type of scenario. So
@ -161,7 +176,12 @@ int i, retval;
*/
if ( stmt->prepare && stmt->status == STMT_PREMATURE) {
stmt->status = STMT_FINISHED;
return stmt->errormsg == NULL ? SQL_SUCCESS : SQL_ERROR;
if (stmt->errormsg == NULL)
return SQL_SUCCESS;
else {
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
SC_clear_error(stmt);
@ -170,12 +190,14 @@ int i, retval;
if (conn->status == CONN_EXECUTING) {
stmt->errormsg = "Connection is already in use.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
if ( ! stmt->statement) {
stmt->errornumber = STMT_NO_STMTSTRING;
stmt->errormsg = "This handle does not have a SQL statement stored in it";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -193,6 +215,7 @@ int i, retval;
stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -240,6 +263,7 @@ RETCODE SQL_API SQLTransact(
HDBC hdbc,
UWORD fType)
{
char *func = "SQLTransact";
extern ConnectionClass *conns[];
ConnectionClass *conn;
QResultClass *res;
@ -248,8 +272,10 @@ int lf;
mylog("**** SQLTransact: hdbc=%u, henv=%u\n", hdbc, henv);
if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
/* If hdbc is null and henv is valid,
it means transact all connections on that henv.
@ -277,6 +303,7 @@ mylog("**** SQLTransact: hdbc=%u, henv=%u\n", hdbc, henv);
} else {
conn->errornumber = CONN_INVALID_ARGUMENT_NO;
conn->errormsg ="SQLTransact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter";
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -288,15 +315,19 @@ mylog("**** SQLTransact: hdbc=%u, henv=%u\n", hdbc, henv);
res = CC_send_query(conn, stmt_string, NULL, NULL);
CC_set_no_trans(conn);
if ( ! res)
if ( ! res) {
// error msg will be in the connection
CC_log_error(func, "", conn);
return SQL_ERROR;
}
ok = QR_command_successful(res);
QR_Destructor(res);
if (!ok)
if (!ok) {
CC_log_error(func, "", conn);
return SQL_ERROR;
}
}
return SQL_SUCCESS;
}
@ -307,11 +338,14 @@ mylog("**** SQLTransact: hdbc=%u, henv=%u\n", hdbc, henv);
RETCODE SQL_API SQLCancel(
HSTMT hstmt) // Statement to cancel.
{
char *func="SQLCancel";
StatementClass *stmt = (StatementClass *) hstmt;
// Check if this can handle canceling in the middle of a SQLPutData?
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
// Not in the middle of SQLParamData/SQLPutData so cancel like a close.
if (stmt->data_at_exec < 0)
@ -354,11 +388,14 @@ RETCODE SQL_API SQLParamData(
HSTMT hstmt,
PTR FAR *prgbValue)
{
char *func = "SQLParamData";
StatementClass *stmt = (StatementClass *) hstmt;
int i, retval;
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
mylog("SQLParamData, enter: data_at_exec=%d, params_alloc=%d\n",
stmt->data_at_exec, stmt->parameters_allocated);
@ -366,12 +403,14 @@ int i, retval;
if (stmt->data_at_exec < 0) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No execution-time parameters for this statement";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
if (stmt->data_at_exec > stmt->parameters_allocated) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Too many execution-time parameters were present";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -422,19 +461,23 @@ RETCODE SQL_API SQLPutData(
PTR rgbValue,
SDWORD cbValue)
{
char *func = "SQLPutData";
StatementClass *stmt = (StatementClass *) hstmt;
int old_pos, retval;
ParameterInfoClass *current_param;
char *buffer;
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (stmt->current_exec_param < 0) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Previous call was not SQLPutData or SQLParamData";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -450,6 +493,7 @@ char *buffer;
if ( ! current_param->EXEC_used) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (1)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -467,6 +511,7 @@ char *buffer;
if (current_param->lobj_oid == 0) {
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt create large object.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -479,6 +524,7 @@ char *buffer;
if ( stmt->lobj_fd < 0) {
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Couldnt open large object for writing.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -493,6 +539,7 @@ char *buffer;
if ( ! current_param->EXEC_buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (2)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
@ -501,6 +548,7 @@ char *buffer;
if ( ! current_param->EXEC_buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (2)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
@ -530,6 +578,7 @@ char *buffer;
if ( ! buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (3)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
strcat(buffer, rgbValue);
@ -555,6 +604,7 @@ char *buffer;
if ( ! buffer) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Out of memory in SQLPutData (3)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -565,8 +615,10 @@ char *buffer;
current_param->EXEC_buffer = buffer;
}
else
else {
SC_log_error(func, "bad cbValue", stmt);
return SQL_ERROR;
}
}
}

View File

@ -45,24 +45,19 @@ RETCODE SQL_API SQLGetInfo(
SWORD cbInfoValueMax,
SWORD FAR *pcbInfoValue)
{
char *func = "SQLGetInfo";
ConnectionClass *conn = (ConnectionClass *) hdbc;
char *p;
if ( ! conn)
return SQL_INVALID_HANDLE;
/* CC: Some sanity checks */
if ((NULL == (char *)rgbInfoValue) ||
(cbInfoValueMax == 0))
/* removed: */
/* || (NULL == pcbInfoValue) */
/* pcbInfoValue is ignored for non-character output. */
/* some programs (at least Microsoft Query) seem to just send a NULL, */
/* so let them get away with it... */
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (NULL == (char *)rgbInfoValue) {
CC_log_error(func, "Bad rgbInfoValue", conn);
return SQL_INVALID_HANDLE;
}
switch (fInfoType) {
@ -70,13 +65,13 @@ char *p;
// can the user call all functions returned by SQLProcedures?
// I assume access permissions could prevent this in some cases(?)
// anyway, SQLProcedures doesn't exist yet.
*pcbInfoValue = 1;
if (pcbInfoValue) *pcbInfoValue = 1;
strncpy_null((char *)rgbInfoValue, "N", (size_t)cbInfoValueMax);
break;
case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */
// is the user guaranteed "SELECT" on every table?
*pcbInfoValue = 1;
if (pcbInfoValue) *pcbInfoValue = 1;
strncpy_null((char *)rgbInfoValue, "N", (size_t)cbInfoValueMax);
break;
@ -108,7 +103,7 @@ char *p;
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
// do we support column aliases? guess not.
*pcbInfoValue = 1;
if (pcbInfoValue) *pcbInfoValue = 1;
strncpy_null((char *)rgbInfoValue, "N", (size_t)cbInfoValueMax);
break;
@ -294,6 +289,7 @@ char *p;
// do this later
conn->errormsg = "SQL_KEYWORDS parameter to SQLGetInfo not implemented.";
conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
CC_log_error(func, "", conn);
return SQL_ERROR;
break;
@ -398,7 +394,7 @@ char *p;
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.
*pcbInfoValue = 1;
if (pcbInfoValue) *pcbInfoValue = 1;
strncpy_null((char *)rgbInfoValue, "Y", (size_t)cbInfoValueMax);
break;
@ -715,6 +711,7 @@ char *p;
/* unrecognized key */
conn->errormsg = "Unrecognized key passed to SQLGetInfo.";
conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -728,6 +725,7 @@ RETCODE SQL_API SQLGetTypeInfo(
HSTMT hstmt,
SWORD fSqlType)
{
char *func = "SQLGetTypeInfo";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
int i;
@ -736,12 +734,14 @@ Int4 type;
mylog("**** in SQLGetTypeInfo: fSqlType = %d\n", fSqlType);
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
stmt->manual_result = TRUE;
stmt->result = QR_Constructor();
if( ! stmt->result) {
SC_log_error(func, "Error creating result.", stmt);
return SQL_ERROR;
}
@ -976,6 +976,7 @@ RETCODE SQL_API SQLTables(
UCHAR FAR * szTableType,
SWORD cbTableType)
{
char *func = "SQLTables";
StatementClass *stmt = (StatementClass *) hstmt;
StatementClass *tbl_stmt;
TupleNode *row;
@ -993,8 +994,10 @@ int i;
mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
@ -1005,6 +1008,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLTables result.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
tbl_stmt = (StatementClass *) htbl_stmt;
@ -1086,6 +1090,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1095,6 +1100,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1104,6 +1110,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1112,6 +1119,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1120,6 +1128,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if(!stmt->result) {
stmt->errormsg = "Couldn't allocate memory for SQLTables result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1201,6 +1210,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
if(result != SQL_NO_DATA_FOUND) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1229,6 +1239,7 @@ RETCODE SQL_API SQLColumns(
UCHAR FAR * szColumnName,
SWORD cbColumnName)
{
char *func = "SQLColumns";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
HSTMT hcol_stmt;
@ -1238,6 +1249,7 @@ RETCODE result;
char table_owner[MAX_INFO_STRING], table_name[MAX_INFO_STRING], field_name[MAX_INFO_STRING], field_type_name[MAX_INFO_STRING];
Int2 field_number, field_length, mod_length;
Int4 field_type;
Int2 the_type;
char not_null[MAX_INFO_STRING];
ConnInfo *ci;
@ -1245,8 +1257,10 @@ ConnInfo *ci;
mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
@ -1273,6 +1287,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLColumns result.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
col_stmt = (StatementClass *) hcol_stmt;
@ -1282,6 +1297,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = SC_create_errormsg(hcol_stmt);
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1291,6 +1307,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1300,6 +1317,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1309,6 +1327,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1318,6 +1337,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1327,6 +1347,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1336,6 +1357,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1345,6 +1367,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1354,6 +1377,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1363,6 +1387,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = col_stmt->errormsg;
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1371,6 +1396,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if(!stmt->result) {
stmt->errormsg = "Couldn't allocate memory for SQLColumns result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1402,33 +1428,37 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
Always show OID if its a system table
*/
if (result != SQL_ERROR && ! stmt->internal &&
(atoi(ci->show_oid_column) || strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)) {
if (result != SQL_ERROR && ! stmt->internal) {
/* For OID fields */
row = (TupleNode *)malloc(sizeof(TupleNode) +
(12 - 1) * sizeof(TupleField));
if (atoi(ci->show_oid_column) || strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0) {
set_tuplefield_string(&row->tuple[0], "");
// see note in SQLTables()
// set_tuplefield_string(&row->tuple[1], table_owner);
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "oid");
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, PG_TYPE_OID));
set_tuplefield_string(&row->tuple[5], "OID");
/* For OID fields */
the_type = PG_TYPE_OID;
row = (TupleNode *)malloc(sizeof(TupleNode) +
(12 - 1) * sizeof(TupleField));
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, PG_TYPE_OID, PG_STATIC,
PG_STATIC));
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, PG_TYPE_OID, PG_STATIC,
PG_STATIC));
set_tuplefield_string(&row->tuple[0], "");
// see note in SQLTables()
// set_tuplefield_string(&row->tuple[1], table_owner);
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "oid");
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type));
set_tuplefield_string(&row->tuple[5], "OID");
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, PG_TYPE_OID));
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, PG_TYPE_OID));
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
set_tuplefield_string(&row->tuple[11], "");
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC,
PG_STATIC));
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC,
PG_STATIC));
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type));
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
set_tuplefield_string(&row->tuple[11], "");
QR_add_tuple(stmt->result, row);
}
QR_add_tuple(stmt->result, row);
}
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) {
@ -1484,10 +1514,36 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
if(result != SQL_NO_DATA_FOUND) {
stmt->errormsg = SC_create_errormsg(hcol_stmt);
stmt->errornumber = col_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
// Put the row version column at the end so it might not be
// mistaken for a key field.
if ( ! stmt->internal && atoi(ci->row_versioning)) {
/* For Row Versioning fields */
the_type = PG_TYPE_INT4;
row = (TupleNode *)malloc(sizeof(TupleNode) +
(12 - 1) * sizeof(TupleField));
set_tuplefield_string(&row->tuple[0], "");
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "xmin");
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type));
set_tuplefield_string(&row->tuple[5], pgtype_to_name(stmt, the_type));
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type));
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
set_tuplefield_string(&row->tuple[11], "");
QR_add_tuple(stmt->result, row);
}
// also, things need to think that this statement is finished so
// the results can be retrieved.
stmt->status = STMT_FINISHED;
@ -1513,14 +1569,20 @@ RETCODE SQL_API SQLSpecialColumns(
UWORD fScope,
UWORD fNullable)
{
char *func = "SQLSpecialColumns";
TupleNode *row;
StatementClass *stmt = (StatementClass *) hstmt;
ConnInfo *ci;
mylog("**** SQLSpecialColumns(): ENTER, stmt=%u\n", stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
ci = &stmt->hdbc->connInfo;
stmt->manual_result = TRUE;
stmt->result = QR_Constructor();
extend_bindings(stmt, 8);
@ -1551,11 +1613,24 @@ mylog("**** SQLSpecialColumns(): ENTER, stmt=%u\n", stmt);
QR_add_tuple(stmt->result, row);
} else if(fColType == SQL_ROWVER) {
/* can columns automatically update? */
/* for now assume no. */
/* return an empty result. */
}
Int2 the_type = PG_TYPE_INT4;
if (atoi(ci->row_versioning)) {
row = (TupleNode *)malloc(sizeof(TupleNode) + (8 - 1) * sizeof(TupleField));
set_tuplefield_null(&row->tuple[0]);
set_tuplefield_string(&row->tuple[1], "xmin");
set_tuplefield_int2(&row->tuple[2], pgtype_to_sqltype(stmt, the_type));
set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
set_tuplefield_int4(&row->tuple[4], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[5], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
QR_add_tuple(stmt->result, row);
}
}
stmt->status = STMT_FINISHED;
stmt->currTuple = -1;
stmt->current_col = -1;
@ -1575,6 +1650,7 @@ RETCODE SQL_API SQLStatistics(
UWORD fUnique,
UWORD fAccuracy)
{
char *func="SQLStatistics";
StatementClass *stmt = (StatementClass *) hstmt;
char index_query[MAX_STATEMENT_LEN];
HSTMT hindx_stmt;
@ -1599,6 +1675,7 @@ char buf[256];
mylog("**** SQLStatistics(): ENTER, stmt=%u\n", stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
@ -1611,6 +1688,7 @@ mylog("**** SQLStatistics(): ENTER, stmt=%u\n", stmt);
if(!stmt->result) {
stmt->errormsg = "Couldn't allocate memory for SQLStatistics result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -1641,6 +1719,7 @@ mylog("**** SQLStatistics(): ENTER, stmt=%u\n", stmt);
if ( ! table_name) {
stmt->errormsg = "No table name passed to SQLStatistics.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -1887,8 +1966,10 @@ SEEYA:
mylog("SQLStatistics(): EXIT, %s, stmt=%u\n", error ? "error" : "success", stmt);
if (error)
if (error) {
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
else
return SQL_SUCCESS;
}
@ -1904,13 +1985,17 @@ RETCODE SQL_API SQLColumnPrivileges(
UCHAR FAR * szColumnName,
SWORD cbColumnName)
{
char *func="SQLColumnPrivileges";
/* Neither Access or Borland care about this. */
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
RETCODE
getPrimaryKeyString(StatementClass *stmt, char *szTableName, SWORD cbTableName, char *svKey, int *nKey)
{
char *func = "getPrimaryKeyString";
HSTMT htbl_stmt;
StatementClass *tbl_stmt;
RETCODE result;
@ -1930,6 +2015,7 @@ int nk = 0;
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for Primary Key result.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
tbl_stmt = (StatementClass *) htbl_stmt;
@ -1940,6 +2026,7 @@ int nk = 0;
stmt->errormsg = "No Table specified to getPrimaryKeyString.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1950,6 +2037,7 @@ int nk = 0;
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1959,6 +2047,7 @@ int nk = 0;
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -1977,6 +2066,7 @@ int nk = 0;
if(result != SQL_NO_DATA_FOUND) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2034,6 +2124,7 @@ RETCODE SQL_API SQLPrimaryKeys(
UCHAR FAR * szTableName,
SWORD cbTableName)
{
char *func = "SQLPrimaryKeys";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
RETCODE result;
@ -2043,6 +2134,7 @@ int seq = 1, nkeys = 0;
mylog("**** SQLPrimaryKeys(): ENTER, stmt=%u\n", stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
stmt->manual_result = TRUE;
@ -2068,6 +2160,7 @@ mylog("**** SQLPrimaryKeys(): ENTER, stmt=%u\n", stmt);
if(!stmt->result) {
stmt->errormsg = "Couldn't allocate memory for SQLPrimaryKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -2137,6 +2230,7 @@ RETCODE SQL_API SQLForeignKeys(
UCHAR FAR * szFkTableName,
SWORD cbFkTableName)
{
char *func = "SQLForeignKeys";
StatementClass *stmt = (StatementClass *) hstmt;
TupleNode *row;
HSTMT htbl_stmt;
@ -2156,6 +2250,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
memset(primaryKey, 0, sizeof(primaryKey));
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
stmt->manual_result = TRUE;
@ -2165,6 +2260,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Couldn't allocate statement for SQLForeignKeys result.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -2224,6 +2320,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
else {
stmt->errormsg = "No tables specified to SQLForeignKeys.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2232,6 +2329,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2241,6 +2339,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2249,6 +2348,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2258,6 +2358,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2266,6 +2367,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if(!stmt->result) {
stmt->errormsg = "Couldn't allocate memory for SQLForeignKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2356,6 +2458,7 @@ mylog("**** SQLForeignKeys(): ENTER, stmt=%u\n", stmt);
if(result != SQL_NO_DATA_FOUND) {
stmt->errormsg = SC_create_errormsg(htbl_stmt);
stmt->errornumber = tbl_stmt->errornumber;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
@ -2387,6 +2490,9 @@ RETCODE SQL_API SQLProcedureColumns(
UCHAR FAR * szColumnName,
SWORD cbColumnName)
{
char *func="SQLProcedureColumns";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
@ -2399,6 +2505,9 @@ RETCODE SQL_API SQLProcedures(
UCHAR FAR * szProcName,
SWORD cbProcName)
{
char *func="SQLProcedures";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
@ -2411,5 +2520,8 @@ RETCODE SQL_API SQLTablePrivileges(
UCHAR FAR * szTableName,
SWORD cbTableName)
{
char *func="SQLTablePrivileges";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}

View File

@ -31,10 +31,14 @@ RETCODE SQL_API SQLSetConnectOption(
UWORD fOption,
UDWORD vParam)
{
char *func="SQLSetConnectOption";
ConnectionClass *conn = (ConnectionClass *) hdbc;
if ( ! conn)
if ( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch (fOption) {
case SQL_AUTOCOMMIT:
@ -46,6 +50,7 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
if (CC_is_in_trans(conn)) {
conn->errormsg = "Cannot switch commit mode while a transaction is in progres";
conn->errornumber = CONN_TRANSACT_IN_PROGRES;
CC_log_error(func, "", conn);
return SQL_ERROR;
}
*/
@ -64,6 +69,7 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
default:
conn->errormsg = "Illegal parameter value for SQL_AUTOCOMMIT";
conn->errornumber = CONN_INVALID_ARGUMENT_NO;
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -76,9 +82,14 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
break;
default:
{
char option[32];
conn->errormsg = "This option is currently unsupported by the driver";
conn->errornumber = CONN_UNSUPPORTED_OPTION;
sprintf(option, "fOption=%d", fOption);
CC_log_error(func, option, conn);
return SQL_ERROR;
}
}
return SQL_SUCCESS;
@ -92,10 +103,13 @@ RETCODE SQL_API SQLGetConnectOption(
UWORD fOption,
PTR pvParam)
{
char *func="SQLGetConnectOption";
ConnectionClass *conn = (ConnectionClass *) hdbc;
if (! conn)
if (! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch (fOption) {
case SQL_AUTOCOMMIT:
@ -111,10 +125,15 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
break;
default:
{
char option[32];
conn->errormsg = "This option is currently unsupported by the driver";
conn->errornumber = CONN_UNSUPPORTED_OPTION;
sprintf(option, "fOption=%d", fOption);
CC_log_error(func, option, conn);
return SQL_ERROR;
break;
}
}
@ -128,6 +147,7 @@ RETCODE SQL_API SQLSetStmtOption(
UWORD fOption,
UDWORD vParam)
{
char *func="SQLSetStmtOption";
StatementClass *stmt = (StatementClass *) hstmt;
char changed = FALSE;
@ -135,8 +155,10 @@ char changed = FALSE;
// all the time, but it tries to set a huge value for SQL_MAX_LENGTH
// and expects the driver to reduce it to the real value
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch(fOption) {
case SQL_QUERY_TIMEOUT:
@ -170,6 +192,7 @@ char changed = FALSE;
else {
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support keyset size option";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
break;
@ -214,12 +237,18 @@ char changed = FALSE;
case SQL_SIMULATE_CURSOR:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
default:
{
char option[32];
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support this statement option";
sprintf(option, "fOption=%d", fOption);
SC_log_error(func, option, stmt);
return SQL_ERROR;
}
}
if (changed) {
@ -239,14 +268,17 @@ RETCODE SQL_API SQLGetStmtOption(
UWORD fOption,
PTR pvParam)
{
char *func="SQLGetStmtOption";
StatementClass *stmt = (StatementClass *) hstmt;
// thought we could fake Access out by just returning SQL_SUCCESS
// all the time, but it tries to set a huge value for SQL_MAX_LENGTH
// and expects the driver to reduce it to the real value
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
switch(fOption) {
case SQL_QUERY_TIMEOUT:
@ -289,12 +321,18 @@ StatementClass *stmt = (StatementClass *) hstmt;
case SQL_SIMULATE_CURSOR:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
default:
{
char option[32];
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support this statement option";
sprintf(option, "fOption=%d", fOption);
SC_log_error(func, option, stmt);
return SQL_ERROR;
}
}
return SQL_SUCCESS;

View File

@ -46,7 +46,9 @@ Int4 pgtypes_defined[] = {
PG_TYPE_BPCHAR,
PG_TYPE_DATE,
PG_TYPE_TIME,
PG_TYPE_DATETIME,
PG_TYPE_ABSTIME, /* a timestamp, sort of */
PG_TYPE_TIMESTAMP,
PG_TYPE_TEXT,
PG_TYPE_INT2,
PG_TYPE_INT4,
@ -55,7 +57,6 @@ Int4 pgtypes_defined[] = {
PG_TYPE_OID,
PG_TYPE_MONEY,
PG_TYPE_BOOL,
PG_TYPE_DATETIME,
PG_TYPE_BYTEA,
PG_TYPE_LO,
0 };
@ -97,7 +98,8 @@ Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type)
case PG_TYPE_DATE: return SQL_DATE;
case PG_TYPE_TIME: return SQL_TIME;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: return SQL_TIMESTAMP;
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return SQL_TIMESTAMP;
case PG_TYPE_MONEY: return SQL_FLOAT;
case PG_TYPE_BOOL: return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
@ -124,7 +126,8 @@ Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type)
case PG_TYPE_DATE: return SQL_C_DATE;
case PG_TYPE_TIME: return SQL_C_TIME;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: return SQL_C_TIMESTAMP;
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return SQL_C_TIMESTAMP;
case PG_TYPE_MONEY: return SQL_C_FLOAT;
case PG_TYPE_BOOL: return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
@ -161,6 +164,7 @@ char *pgtype_to_name(StatementClass *stmt, Int4 type)
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";
@ -269,7 +273,8 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno
case PG_TYPE_TIME: return 8;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: return 19;
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return 19;
case PG_TYPE_BOOL: return 1;
@ -327,7 +332,8 @@ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_
case PG_TYPE_TIME: return 6;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: return 16;
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return 16;
/* Character types use the default precision */
@ -350,7 +356,8 @@ Int2 pgtype_scale(StatementClass *stmt, Int4 type)
/* Number of digits to the right of the decimal point in "yyyy-mm=dd hh:mm:ss[.f...]" */
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: return 0;
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return 0;
default: return -1;
}
@ -391,7 +398,8 @@ Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type)
case PG_TYPE_DATE:
case PG_TYPE_TIME:
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: return FALSE;
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: return FALSE;
default: return -1;
}

View File

@ -58,6 +58,7 @@
#define PG_TYPE_DATE 1082
#define PG_TYPE_TIME 1083
#define PG_TYPE_DATETIME 1184
#define PG_TYPE_TIMESTAMP 1296
extern Int4 pgtypes_defined[];

View File

@ -50,8 +50,8 @@ typedef UInt4 Oid;
/* Driver stuff */
#define DRIVERNAME "PostgreSQL ODBC"
#define DBMS_NAME "PostgreSQL"
#define DBMS_VERSION "06.30.0244 PostgreSQL 6.3"
#define POSTGRESDRIVERVERSION "06.30.0244"
#define DBMS_VERSION "06.30.0246 PostgreSQL 6.3"
#define POSTGRESDRIVERVERSION "06.30.0246"
#define DRIVER_FILE_NAME "PSQLODBC.DLL"

View File

@ -137,6 +137,8 @@ BEGIN
WS_TABSTOP,130,10,60,14
CONTROL "Show System &Tables",DS_SHOWSYSTEMTABLES,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,25,30,85,10
CONTROL "Row &Versioning",DS_ROWVERSIONING,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,130,30,85,10
GROUPBOX "OID Options",IDC_STATIC,15,50,180,25
CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,25,60,59,10
@ -198,8 +200,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 6,30,2,44
PRODUCTVERSION 6,30,2,44
FILEVERSION 6,30,2,46
PRODUCTVERSION 6,30,2,46
FILEFLAGSMASK 0x3L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -217,12 +219,12 @@ BEGIN
VALUE "Comments", "PostgreSQL ODBC driver for Windows 95\0"
VALUE "CompanyName", "Insight Distribution Systems\0"
VALUE "FileDescription", "PostgreSQL Driver\0"
VALUE "FileVersion", " 6.30.0244\0"
VALUE "FileVersion", " 6.30.0246\0"
VALUE "InternalName", "psqlodbc\0"
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
VALUE "OriginalFilename", "psqlodbc.dll\0"
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
VALUE "ProductVersion", " 6.30.0244\0"
VALUE "ProductVersion", " 6.30.0246\0"
END
END
BLOCK "VarFileInfo"

View File

@ -45,6 +45,7 @@
#define DRV_BOOLS_CHAR 1050
#define DS_SHOWSYSTEMTABLES 1051
#define DRV_EXTRASYSTABLEPREFIXES 1051
#define DS_ROWVERSIONING 1052
// Next default values for new objects
//

View File

@ -36,12 +36,15 @@ RETCODE SQL_API SQLRowCount(
HSTMT hstmt,
SDWORD FAR *pcrow)
{
char *func="SQLRowCount";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
char *msg, *ptr;
if ( ! stmt)
return SQL_ERROR;
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if(stmt->statement_type == STMT_TYPE_SELECT) {
if (stmt->status == STMT_FINISHED) {
@ -74,6 +77,7 @@ char *msg, *ptr;
}
}
SC_log_error(func, "Bad return value", stmt);
return SQL_ERROR;
}
@ -86,11 +90,14 @@ RETCODE SQL_API SQLNumResultCols(
HSTMT hstmt,
SWORD FAR *pccol)
{
char *func="SQLNumResultCols";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *result;
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
SC_clear_error(stmt);
@ -109,6 +116,7 @@ QResultClass *result;
/* no query has been executed on this statement */
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No query has been executed with that handle";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -133,6 +141,7 @@ RETCODE SQL_API SQLDescribeCol(
SWORD FAR *pibScale,
SWORD FAR *pfNullable)
{
char *func="SQLDescribeCol";
/* gets all the information about a specific column */
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *result;
@ -141,8 +150,10 @@ Int4 fieldtype;
int p;
ConnInfo *ci;
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
ci = &(stmt->hdbc->connInfo);
@ -162,6 +173,7 @@ ConnInfo *ci;
/* no query has been executed on this statement */
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "No query has been assigned to this statement.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -169,6 +181,7 @@ ConnInfo *ci;
// we do not support bookmarks
stmt->errormsg = "Bookmarks are not currently supported.";
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -255,14 +268,17 @@ RETCODE SQL_API SQLColAttributes(
SWORD FAR *pcbDesc,
SDWORD FAR *pfDesc)
{
char *func = "SQLColAttributes";
StatementClass *stmt = (StatementClass *) hstmt;
char *value;
Int4 field_type;
ConnInfo *ci;
int unknown_sizes;
if( ! stmt)
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
ci = &(stmt->hdbc->connInfo);
@ -277,6 +293,7 @@ int unknown_sizes;
if ( (NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) {
stmt->errormsg = "Can't get column attributes: no result found.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -284,6 +301,7 @@ int unknown_sizes;
// we do not support bookmarks
stmt->errormsg = "Bookmarks are not currently supported.";
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -436,6 +454,7 @@ RETCODE SQL_API SQLGetData(
SDWORD cbValueMax,
SDWORD FAR *pcbValue)
{
char *func="SQLGetData";
QResultClass *res;
StatementClass *stmt = (StatementClass *) hstmt;
int num_cols, num_rows;
@ -448,6 +467,7 @@ char multiple;
mylog("SQLGetData: enter, stmt=%u\n", stmt);
if( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
res = stmt->result;
@ -455,18 +475,21 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
if (STMT_EXECUTING == stmt->status) {
stmt->errormsg = "Can't get data while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
return 0;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
if (stmt->status != STMT_FINISHED) {
stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "GetData can only be called after the successful execution on a SQL statement";
return 0;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
if (icol == 0) {
stmt->errormsg = "Bookmarks are not currently supported.";
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -478,6 +501,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
if (icol >= num_cols) {
stmt->errormsg = "Invalid column number.";
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -488,6 +512,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
(stmt->currTuple >= num_rows)) {
stmt->errormsg = "Not positioned on a valid row for GetData.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
mylog(" num_rows = %d\n", num_rows);
@ -503,6 +528,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
if (stmt->currTuple == -1 || ! res || QR_end_tuples(res)) {
stmt->errormsg = "Not positioned on a valid row for GetData.";
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -531,11 +557,13 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
case COPY_UNSUPPORTED_TYPE:
stmt->errormsg = "Received an unsupported type from Postgres.";
stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
case COPY_UNSUPPORTED_CONVERSION:
stmt->errormsg = "Couldn't handle the necessary data type conversion.";
stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
case COPY_RESULT_TRUNCATED:
@ -544,14 +572,17 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
return SQL_SUCCESS_WITH_INFO;
case COPY_GENERAL_ERROR: /* error msg already filled in */
SC_log_error(func, "", stmt);
return SQL_ERROR;
case COPY_NO_DATA_FOUND:
SC_log_error(func, "no data found", stmt);
return SQL_NO_DATA_FOUND;
default:
stmt->errormsg = "Unrecognized return value from copy_and_convert_field.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
@ -562,6 +593,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
RETCODE SQL_API SQLFetch(
HSTMT hstmt)
{
char *func = "SQLFetch";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
int retval;
@ -571,14 +603,17 @@ char *value;
ColumnInfoClass *ci;
// TupleField *tupleField;
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
SC_clear_error(stmt);
if ( ! (res = stmt->result)) {
stmt->errormsg = "Null statement result in SQLFetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -587,6 +622,7 @@ ColumnInfoClass *ci;
if (stmt->status == STMT_EXECUTING) {
stmt->errormsg = "Can't fetch while statement is still executing.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -594,6 +630,7 @@ ColumnInfoClass *ci;
if (stmt->status != STMT_FINISHED) {
stmt->errornumber = STMT_STATUS_ERROR;
stmt->errormsg = "Fetch can only be called after the successful execution on a SQL statement";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -602,6 +639,7 @@ ColumnInfoClass *ci;
// function even if SQL_ExecDirect has reported an Error
stmt->errormsg = "Bindings were not allocated properly.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -638,6 +676,7 @@ ColumnInfoClass *ci;
mylog("SQLFetch: error\n");
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Error fetching next row";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
@ -675,11 +714,13 @@ ColumnInfoClass *ci;
if(retval == COPY_UNSUPPORTED_TYPE) {
stmt->errormsg = "Received an unsupported type from Postgres.";
stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
} else if(retval == COPY_UNSUPPORTED_CONVERSION) {
stmt->errormsg = "Couldn't handle the necessary data type conversion.";
stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
} else if(retval == COPY_RESULT_TRUNCATED) {
@ -692,6 +733,7 @@ ColumnInfoClass *ci;
} else if(retval != COPY_OK) {
stmt->errormsg = "Unrecognized return value from copy_and_convert_field.";
stmt->errornumber = STMT_INTERNAL_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -710,6 +752,7 @@ RETCODE SQL_API SQLExtendedFetch(
UDWORD FAR *pcrow,
UWORD FAR *rgfRowStatus)
{
char *func = "SQLExtendedFetch";
StatementClass *stmt = (StatementClass *) hstmt;
int num_tuples;
RETCODE result;
@ -717,11 +760,15 @@ RETCODE result;
mylog("SQLExtendedFetch: stmt=%u\n", stmt);
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if ( globals.use_declarefetch)
if ( globals.use_declarefetch) {
SC_log_error(func, "SQLExtendedFetch with UseDeclareFetch not yet supported", stmt);
return SQL_ERROR;
}
/* Initialize to no rows fetched */
if (rgfRowStatus)
@ -776,6 +823,7 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
break;
default:
SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
return SQL_ERROR;
}
@ -803,7 +851,7 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
RETCODE SQL_API SQLMoreResults(
HSTMT hstmt)
{
return SQL_NO_DATA_FOUND;
return SQL_NO_DATA_FOUND;
}
// This positions the cursor within a block of data.
@ -814,7 +862,10 @@ RETCODE SQL_API SQLSetPos(
UWORD fOption,
UWORD fLock)
{
return SQL_ERROR;
char *func = "SQLSetPos";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
// Sets options that control the behavior of cursors.
@ -825,7 +876,10 @@ RETCODE SQL_API SQLSetScrollOptions(
SDWORD crowKeyset,
UWORD crowRowset)
{
return SQL_ERROR;
char *func = "SQLSetScrollOptions";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
@ -836,20 +890,24 @@ RETCODE SQL_API SQLSetCursorName(
UCHAR FAR *szCursor,
SWORD cbCursor)
{
char *func="SQLSetCursorName";
StatementClass *stmt = (StatementClass *) hstmt;
int len;
mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n",
hstmt, szCursor, cbCursor);
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor;
mylog("cursor len = %d\n", len);
if (len <= 0 || len > sizeof(stmt->cursor_name) - 1) {
stmt->errornumber = STMT_INVALID_CURSOR_NAME;
stmt->errormsg = "Invalid Cursor Name";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
strncpy_null(stmt->cursor_name, szCursor, cbCursor);
@ -864,18 +922,22 @@ RETCODE SQL_API SQLGetCursorName(
SWORD cbCursorMax,
SWORD FAR *pcbCursor)
{
char *func="SQLGetCursorName";
StatementClass *stmt = (StatementClass *) hstmt;
mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n",
hstmt, szCursor, cbCursorMax, pcbCursor);
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if ( stmt->cursor_name[0] == '\0') {
stmt->errornumber = STMT_NO_CURSOR_NAME;
stmt->errormsg = "No Cursor name available";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}

View File

@ -46,11 +46,14 @@ static struct {
RETCODE SQL_API SQLAllocStmt(HDBC hdbc,
HSTMT FAR *phstmt)
{
char *func="SQLAllocStmt";
ConnectionClass *conn = (ConnectionClass *) hdbc;
StatementClass *stmt;
if( ! conn)
if( ! conn) {
CC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
stmt = SC_Constructor();
@ -60,12 +63,14 @@ StatementClass *stmt;
conn->errornumber = CONN_STMT_ALLOC_ERROR;
conn->errormsg = "No more memory to allocate a further SQL-statement";
*phstmt = SQL_NULL_HSTMT;
CC_log_error(func, "", conn);
return SQL_ERROR;
}
if ( ! CC_add_statement(conn, stmt)) {
conn->errormsg = "Maximum number of connections exceeded.";
conn->errornumber = CONN_STMT_ALLOC_ERROR;
CC_log_error(func, "", conn);
SC_Destructor(stmt);
*phstmt = SQL_NULL_HSTMT;
return SQL_ERROR;
@ -80,12 +85,15 @@ StatementClass *stmt;
RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
UWORD fOption)
{
char *func="SQLFreeStmt";
StatementClass *stmt = (StatementClass *) hstmt;
mylog("**** enter SQLFreeStmt: hstmt=%u, fOption=%d\n", hstmt, fOption);
if ( ! stmt)
if ( ! stmt) {
SC_log_error(func, "", NULL);
return SQL_INVALID_HANDLE;
}
if (fOption == SQL_DROP) {
ConnectionClass *conn = stmt->hdbc;
@ -95,6 +103,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
if ( ! CC_remove_statement(conn, stmt)) {
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Statement is currently executing a transaction.";
SC_log_error(func, "", stmt);
return SQL_ERROR; /* stmt may be executing a transaction */
}
@ -116,9 +125,11 @@ StatementClass *stmt = (StatementClass *) hstmt;
/* this should discard all the results, but leave the statement */
/* itself in place (it can be executed again) */
if (!SC_recycle_statement(stmt))
if (!SC_recycle_statement(stmt)) {
// errormsg passed in above
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
} else if(fOption == SQL_RESET_PARAMS) {
SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
@ -126,6 +137,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
} else {
stmt->errormsg = "Invalid option passed to SQLFreeStmt.";
stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -447,6 +459,7 @@ char rv;
RETCODE SC_execute(StatementClass *self)
{
char *func="SC_execute";
ConnectionClass *conn;
QResultClass *res;
char ok, was_ok, was_nonfatal;
@ -466,6 +479,7 @@ Int2 oldstatus, numcols;
if ( ! res) {
self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self);
return SQL_ERROR;
}
@ -478,6 +492,7 @@ Int2 oldstatus, numcols;
if (!ok) {
self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self);
return SQL_ERROR;
}
else
@ -554,6 +569,7 @@ Int2 oldstatus, numcols;
if (self->bindings == NULL) {
self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "Could not get enough free memory to store the binding information";
SC_log_error(func, "", self);
return SQL_ERROR;
}
}
@ -582,6 +598,43 @@ Int2 oldstatus, numcols;
else if (self->errornumber == STMT_INFO_ONLY)
return SQL_SUCCESS_WITH_INFO;
else
else {
SC_log_error(func, "", self);
return SQL_ERROR;
}
}
void
SC_log_error(char *func, char *desc, StatementClass *self)
{
if (self) {
qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
qlog(" ------------------------------------------------------------\n");
qlog(" hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, self->result);
qlog(" manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);
qlog(" bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated);
qlog(" parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated);
qlog(" statement_type=%d, statement='%s'\n", self->statement_type, self->statement);
qlog(" stmt_with_params='%s'\n", self->stmt_with_params);
qlog(" data_at_exec=%d, current_exec_param=%d, put_data=%d\n", self->data_at_exec, self->current_exec_param, self->put_data);
qlog(" currTuple=%d, current_col=%d, lobj_fd=%d\n", self->currTuple, self->current_col, self->lobj_fd);
qlog(" maxRows=%d, rowset_size=%d, keyset_size=%d, cursor_type=%d, scroll_concurrency=%d\n", self->maxRows, self->rowset_size, self->keyset_size, self->cursor_type, self->scroll_concurrency);
qlog(" cursor_name='%s'\n", self->cursor_name);
qlog(" ----------------QResult Info -------------------------------\n");
if (self->result) {
QResultClass *res = self->result;
qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);
qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, res->cursor);
qlog(" message='%s', command='%s', notice='%s'\n", res->message, res->command, res->notice);
qlog(" status=%d, inTuples=%d\n", res->status, res->inTuples);
}
// Log the connection error if there is one
CC_log_error(func, desc, self->hdbc);
}
else
qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}

View File

@ -132,5 +132,6 @@ char SC_get_error(StatementClass *self, int *number, char **message);
char *SC_create_errormsg(StatementClass *self);
RETCODE SC_execute(StatementClass *stmt);
void SC_free_params(StatementClass *self, char option);
void SC_log_error(char *func, char *desc, StatementClass *self);
#endif