[2002-03-28]

1) Prepare to separate 4 kinds of Descriptor handles.
2) Detect the transaction status more naturally.
3) Improve Parse Statement functionality for the use
   of updatable cursors.
4) Improve updatable cursors.
5) Implement SQLGetDescField() and improve SQLColAttribute().
6) etc.
This commit is contained in:
Hiroshi Inoue 2002-03-28 08:08:07 +00:00
parent e6774dc355
commit 6852741c18
40 changed files with 2702 additions and 1297 deletions

View File

@ -17,6 +17,7 @@
#include "environ.h"
#include "statement.h"
#include "descriptor.h"
#include "qresult.h"
#include "pgtypes.h"
#include <stdlib.h>
@ -41,6 +42,7 @@ PGAPI_BindParameter(
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_BindParameter";
APDFields *opts;
mylog("%s: entering...\n", func);
@ -51,103 +53,54 @@ PGAPI_BindParameter(
}
SC_clear_error(stmt);
if (stmt->parameters_allocated < ipar)
{
ParameterInfoClass *old_parameters;
int i,
old_parameters_allocated;
old_parameters = stmt->parameters;
old_parameters_allocated = stmt->parameters_allocated;
stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass) * (ipar));
if (!stmt->parameters)
{
stmt->errornumber = STMT_NO_MEMORY_ERROR;
stmt->errormsg = "Could not allocate memory for statement parameters";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
stmt->parameters_allocated = ipar;
/* copy the old parameters over */
for (i = 0; i < old_parameters_allocated; i++)
{
/* a structure copy should work */
stmt->parameters[i] = old_parameters[i];
}
/* get rid of the old parameters, if there were any */
if (old_parameters)
free(old_parameters);
/*
* zero out the newly allocated parameters (in case they skipped
* some,
*/
/* so we don't accidentally try to use them later) */
for (; i < stmt->parameters_allocated; i++)
{
stmt->parameters[i].buflen = 0;
stmt->parameters[i].buffer = 0;
stmt->parameters[i].used = 0;
stmt->parameters[i].paramType = 0;
stmt->parameters[i].CType = 0;
stmt->parameters[i].SQLType = 0;
stmt->parameters[i].precision = 0;
stmt->parameters[i].scale = 0;
stmt->parameters[i].data_at_exec = FALSE;
stmt->parameters[i].lobj_oid = 0;
stmt->parameters[i].EXEC_used = NULL;
stmt->parameters[i].EXEC_buffer = NULL;
}
}
opts = SC_get_APD(stmt);
if (opts->allocated < ipar)
extend_parameter_bindings(opts, ipar);
/* use zero based column numbers for the below part */
ipar--;
/* store the given info */
stmt->parameters[ipar].buflen = cbValueMax;
stmt->parameters[ipar].buffer = rgbValue;
stmt->parameters[ipar].used = pcbValue;
stmt->parameters[ipar].paramType = fParamType;
stmt->parameters[ipar].CType = fCType;
stmt->parameters[ipar].SQLType = fSqlType;
stmt->parameters[ipar].precision = cbColDef;
stmt->parameters[ipar].scale = ibScale;
opts->parameters[ipar].buflen = cbValueMax;
opts->parameters[ipar].buffer = rgbValue;
opts->parameters[ipar].used = pcbValue;
opts->parameters[ipar].paramType = fParamType;
opts->parameters[ipar].CType = fCType;
opts->parameters[ipar].SQLType = fSqlType;
opts->parameters[ipar].precision = cbColDef;
opts->parameters[ipar].scale = ibScale;
/*
* If rebinding a parameter that had data-at-exec stuff in it, then
* free that stuff
*/
if (stmt->parameters[ipar].EXEC_used)
if (opts->parameters[ipar].EXEC_used)
{
free(stmt->parameters[ipar].EXEC_used);
stmt->parameters[ipar].EXEC_used = NULL;
free(opts->parameters[ipar].EXEC_used);
opts->parameters[ipar].EXEC_used = NULL;
}
if (stmt->parameters[ipar].EXEC_buffer)
if (opts->parameters[ipar].EXEC_buffer)
{
if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY)
free(stmt->parameters[ipar].EXEC_buffer);
stmt->parameters[ipar].EXEC_buffer = NULL;
if (opts->parameters[ipar].SQLType != SQL_LONGVARBINARY)
free(opts->parameters[ipar].EXEC_buffer);
opts->parameters[ipar].EXEC_buffer = NULL;
}
if (pcbValue && stmt->options.param_offset_ptr)
pcbValue += (*stmt->options.param_offset_ptr >> 2);
if (pcbValue && opts->param_offset_ptr)
pcbValue += (*opts->param_offset_ptr >> 2);
/* Data at exec macro only valid for C char/binary data */
if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
*pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
stmt->parameters[ipar].data_at_exec = TRUE;
opts->parameters[ipar].data_at_exec = TRUE;
else
stmt->parameters[ipar].data_at_exec = FALSE;
opts->parameters[ipar].data_at_exec = FALSE;
/* Clear premature result */
if (stmt->status == STMT_PREMATURE)
SC_recycle_statement(stmt);
mylog("PGAPI_BindParamater: 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("PGAPI_BindParamater: 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, opts->parameters[ipar].data_at_exec);
return SQL_SUCCESS;
}
@ -165,6 +118,7 @@ PGAPI_BindCol(
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_BindCol";
ARDFields *opts;
mylog("%s: entering...\n", func);
@ -178,8 +132,8 @@ PGAPI_BindCol(
}
SC_clear_error(stmt);
opts = SC_get_ARD(stmt);
if (stmt->status == STMT_EXECUTING)
{
stmt->errormsg = "Can't bind columns while statement is still executing.";
@ -188,13 +142,14 @@ PGAPI_BindCol(
return SQL_ERROR;
}
SC_clear_error(stmt);
/* If the bookmark column is being bound, then just save it */
if (icol == 0)
{
if (rgbValue == NULL)
{
stmt->bookmark.buffer = NULL;
stmt->bookmark.used = NULL;
opts->bookmark->buffer = NULL;
opts->bookmark->used = NULL;
}
else
{
@ -215,8 +170,8 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
return SQL_ERROR;
}
stmt->bookmark.buffer = rgbValue;
stmt->bookmark.used = pcbValue;
opts->bookmark->buffer = rgbValue;
opts->bookmark->used = pcbValue;
}
return SQL_SUCCESS;
}
@ -226,11 +181,11 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
* 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);
if (icol > opts->allocated)
extend_column_bindings(opts, icol);
/* check to see if the bindings were allocated */
if (!stmt->bindings)
if (!opts->bindings)
{
stmt->errormsg = "Could not allocate memory for bindings.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
@ -242,25 +197,29 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
icol--;
/* Reset for SQLGetData */
stmt->bindings[icol].data_left = -1;
opts->bindings[icol].data_left = -1;
if (rgbValue == NULL)
{
/* we have to unbind the column */
stmt->bindings[icol].buflen = 0;
stmt->bindings[icol].buffer = NULL;
stmt->bindings[icol].used = NULL;
stmt->bindings[icol].returntype = SQL_C_CHAR;
opts->bindings[icol].buflen = 0;
opts->bindings[icol].buffer = NULL;
opts->bindings[icol].used = NULL;
opts->bindings[icol].returntype = SQL_C_CHAR;
if (opts->bindings[icol].ttlbuf)
free(opts->bindings[icol].ttlbuf);
opts->bindings[icol].ttlbuf = NULL;
opts->bindings[icol].ttlbuflen = 0;
}
else
{
/* ok, bind that column */
stmt->bindings[icol].buflen = cbValueMax;
stmt->bindings[icol].buffer = rgbValue;
stmt->bindings[icol].used = pcbValue;
stmt->bindings[icol].returntype = fCType;
opts->bindings[icol].buflen = cbValueMax;
opts->bindings[icol].buffer = rgbValue;
opts->bindings[icol].used = pcbValue;
opts->bindings[icol].returntype = fCType;
mylog(" bound buffer[%d] = %u\n", icol, stmt->bindings[icol].buffer);
mylog(" bound buffer[%d] = %u\n", icol, opts->bindings[icol].buffer);
}
return SQL_SUCCESS;
@ -286,6 +245,7 @@ PGAPI_DescribeParam(
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_DescribeParam";
APDFields *opts;
mylog("%s: entering...\n", func);
@ -296,7 +256,8 @@ PGAPI_DescribeParam(
}
SC_clear_error(stmt);
if ((ipar < 1) || (ipar > stmt->parameters_allocated))
opts = SC_get_APD(stmt);
if ((ipar < 1) || (ipar > opts->allocated))
{
stmt->errormsg = "Invalid parameter number for PGAPI_DescribeParam.";
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
@ -312,16 +273,16 @@ PGAPI_DescribeParam(
*/
/* parameter markers, not bound parameters. */
if (pfSqlType)
*pfSqlType = stmt->parameters[ipar].SQLType;
*pfSqlType = opts->parameters[ipar].SQLType;
if (pcbColDef)
*pcbColDef = stmt->parameters[ipar].precision;
*pcbColDef = opts->parameters[ipar].precision;
if (pibScale)
*pibScale = stmt->parameters[ipar].scale;
*pibScale = opts->parameters[ipar].scale;
if (pfNullable)
*pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType);
*pfNullable = pgtype_nullable(stmt, opts->parameters[ipar].paramType);
return SQL_SUCCESS;
}
@ -336,11 +297,13 @@ PGAPI_ParamOptions(
{
static char *func = "PGAPI_ParamOptions";
StatementClass *stmt = (StatementClass *) hstmt;
APDFields *opts;
mylog("%s: entering... %d %x\n", func, crow, pirow);
stmt->options.paramset_size = crow;
stmt->options.param_processed_ptr = (SQLUINTEGER *)pirow;
opts = SC_get_APD(stmt);
opts->paramset_size = crow;
SC_get_IPD(stmt)->param_processed_ptr = (UInt4 *) pirow;
return SQL_SUCCESS;
}
@ -433,46 +396,156 @@ create_empty_bindings(int num_columns)
return new_bindings;
}
void
extend_bindings(StatementClass *stmt, int num_columns)
extend_parameter_bindings(APDFields *self, int num_params)
{
static char *func = "extend_bindings";
BindInfoClass *new_bindings;
int i;
static char *func = "extend_parameter_bindings";
ParameterInfoClass *new_bindings;
mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns);
mylog("%s: entering ... self=%u, parameters_allocated=%d, num_params=%d\n", func, self, self->allocated, num_params);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (stmt->bindings_allocated < num_columns)
if (self->allocated < num_params)
{
new_bindings = (ParameterInfoClass *) realloc(self->parameters, sizeof(ParameterInfoClass) * num_params);
if (!new_bindings)
{
mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_params, self->allocated);
self->parameters = NULL;
self->allocated = 0;
return;
}
memset(&new_bindings[self->allocated], 0,
sizeof(ParameterInfoClass) * (num_params - self->allocated));
self->parameters = new_bindings;
self->allocated = num_params;
}
mylog("exit extend_parameter_bindings\n");
}
void
reset_a_parameter_binding(APDFields *self, int ipar)
{
static char *func = "reset_a_parameter_binding";
mylog("%s: entering ... self=%u, parameters_allocated=%d, ipar=%d\n", func, self, self->allocated, ipar);
if (ipar < 1 || ipar > self->allocated)
return;
ipar--;
self->parameters[ipar].buflen = 0;
self->parameters[ipar].buffer = 0;
self->parameters[ipar].used = 0;
self->parameters[ipar].paramType = 0;
self->parameters[ipar].CType = 0;
if (self->parameters[ipar].EXEC_used)
{
free(self->parameters[ipar].EXEC_used);
self->parameters[ipar].EXEC_used = NULL;
}
if (self->parameters[ipar].EXEC_buffer)
{
if (self->parameters[ipar].SQLType != SQL_LONGVARBINARY)
free(self->parameters[ipar].EXEC_buffer);
self->parameters[ipar].EXEC_buffer = NULL;
}
self->parameters[ipar].SQLType = 0;
self->parameters[ipar].precision = 0;
self->parameters[ipar].scale = 0;
self->parameters[ipar].data_at_exec = FALSE;
self->parameters[ipar].lobj_oid = 0;
}
/*
* Free parameters and free the memory.
*/
void
APD_free_params(APDFields *self, char option)
{
int i;
mylog("APD_free_params: ENTER, self=%d\n", self);
if (!self->parameters)
return;
for (i = 0; i < self->allocated; i++)
{
if (self->parameters[i].data_at_exec)
{
if (self->parameters[i].EXEC_used)
{
free(self->parameters[i].EXEC_used);
self->parameters[i].EXEC_used = NULL;
}
if (self->parameters[i].EXEC_buffer)
{
if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
free(self->parameters[i].EXEC_buffer);
self->parameters[i].EXEC_buffer = NULL;
}
}
}
if (option == STMT_FREE_PARAMS_ALL)
{
if (self->parameters);
free(self->parameters);
self->parameters = NULL;
self->allocated = 0;
}
mylog("APD_free_params: EXIT\n");
}
void
extend_column_bindings(ARDFields *self, int num_columns)
{
static char *func = "extend_column_bindings";
BindInfoClass *new_bindings;
int i;
mylog("%s: entering ... self=%u, bindings_allocated=%d, num_columns=%d\n", func, self, self->allocated, num_columns);
/*
* if we have too few, allocate room for more, and copy the old
* entries into the new structure
*/
if (self->allocated < num_columns)
{
new_bindings = create_empty_bindings(num_columns);
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, self->allocated);
if (stmt->bindings)
if (self->bindings)
{
free(stmt->bindings);
stmt->bindings = NULL;
free(self->bindings);
self->bindings = NULL;
}
stmt->bindings_allocated = 0;
self->allocated = 0;
return;
}
if (stmt->bindings)
if (self->bindings)
{
for (i = 0; i < stmt->bindings_allocated; i++)
new_bindings[i] = stmt->bindings[i];
for (i = 0; i < self->allocated; i++)
new_bindings[i] = self->bindings[i];
free(stmt->bindings);
free(self->bindings);
}
stmt->bindings = new_bindings;
stmt->bindings_allocated = num_columns;
self->bindings = new_bindings;
self->allocated = num_columns;
}
/*
@ -485,5 +558,53 @@ extend_bindings(StatementClass *stmt, int num_columns)
/* SQLExecDirect(...) # returns 5 cols */
/* SQLExecDirect(...) # returns 10 cols (now OK) */
mylog("exit extend_bindings\n");
mylog("exit extend_column_bindings\n");
}
void
reset_a_column_binding(ARDFields *self, int icol)
{
static char *func = "reset_a_column_binding";
mylog("%s: entering ... self=%u, bindings_allocated=%d, icol=%d\n", func, self, self->allocated, icol);
if (icol > self->allocated)
return;
/* use zero based col numbers from here out */
if (0 == icol)
{
self->bookmark->buffer = NULL;
self->bookmark->used = NULL;
}
else
{
icol--;
/* we have to unbind the column */
self->bindings[icol].buflen = 0;
self->bindings[icol].buffer = NULL;
self->bindings[icol].used = NULL;
self->bindings[icol].data_left = -1;
self->bindings[icol].returntype = SQL_C_CHAR;
if (self->bindings[icol].ttlbuf)
free(self->bindings[icol].ttlbuf);
self->bindings[icol].ttlbuf = NULL;
self->bindings[icol].ttlbuflen = 0;
}
}
void ARD_unbind_cols(ARDFields *self, BOOL freeall)
{
Int2 lf;
for (lf = 1; lf <= self->allocated; lf++)
reset_a_column_binding(self, lf);
if (freeall)
{
if (self->bindings)
free(self->bindings);
self->bindings = NULL;
self->allocated = 0;
}
}

View File

@ -50,6 +50,9 @@ struct ParameterInfoClass_
};
BindInfoClass *create_empty_bindings(int num_columns);
void extend_bindings(StatementClass *stmt, int num_columns);
void extend_column_bindings(ARDFields *opts, int num_columns);
void reset_a_column_binding(ARDFields *opts, int icol);
void extend_parameter_bindings(APDFields *opts, int num_columns);
void reset_a_parameter_binding(APDFields *opts, int ipar);
#endif

View File

@ -298,8 +298,8 @@ CC_Constructor()
/* Statements under this conn will inherit these options */
InitializeStatementOptions(&rv->stmtOptions);
InitializeARDFields(&rv->ardOptions);
InitializeAPDFields(&rv->apdOptions);
}
return rv;
}
@ -381,8 +381,6 @@ CC_begin(ConnectionClass *self)
{
ret = QR_command_successful(res);
QR_Destructor(res);
if (ret)
CC_set_in_trans(self);
}
else
return FALSE;
@ -403,9 +401,6 @@ CC_commit(ConnectionClass *self)
{
QResultClass *res = CC_send_query(self, "COMMIT", NULL, CLEAR_RESULT_ON_ABORT);
mylog("CC_commit: sending COMMIT!\n");
CC_set_no_trans(self);
if (res != NULL)
{
ret = QR_command_successful(res);
@ -429,9 +424,6 @@ CC_abort(ConnectionClass *self)
{
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, CLEAR_RESULT_ON_ABORT);
mylog("CC_abort: sending ABORT!\n");
CC_set_no_trans(self);
if (res != NULL)
QR_Destructor(res);
else
@ -1118,6 +1110,23 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
}
void CC_on_commit(ConnectionClass *conn, BOOL set_no_trans)
{
if (CC_is_in_trans(conn))
{
if (set_no_trans)
CC_set_no_trans(conn);
}
}
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans)
{
if (CC_is_in_trans(conn))
{
if (set_no_trans)
CC_set_no_trans(conn);
}
}
/*
* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
* the same existing QResultClass (this occurs when the tuple cache is depleted and
@ -1134,7 +1143,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
*retres = NULL,
*res = NULL;
BOOL clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
create_keyset = ((flag & CREATE_KEYSET) != 0);
create_keyset = ((flag & CREATE_KEYSET) != 0),
issue_begin = ((flag & GO_INTO_TRANSACTION) != 0 && !CC_is_in_trans(self));
char swallow,
*wq;
int id;
@ -1146,7 +1156,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
query_completed = FALSE,
before_64 = PG_VERSION_LT(self, 6.4),
aborted = FALSE,
used_passed_result_object = FALSE;
used_passed_result_object = FALSE,
set_no_trans;
/* ERROR_MSG_LENGTH is suffcient */
static char msgbuffer[ERROR_MSG_LENGTH + 1];
@ -1173,7 +1184,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
{
self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send Query to backend";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
return NULL;
}
@ -1182,10 +1193,12 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
{
self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send Query to backend";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
return NULL;
}
if (issue_begin)
SOCK_put_n_char(sock, "begin;", 6);
SOCK_put_string(sock, query);
SOCK_flush_output(sock);
@ -1193,7 +1206,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
{
self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send Query to backend";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
return NULL;
}
@ -1230,7 +1243,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
self->errormsg = "No response from the backend";
mylog("send_query: 'id' - %s\n", self->errormsg);
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
ReadyToReturn = TRUE;
retres = NULL;
break;
@ -1254,7 +1267,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
self->errornumber = CONNECTION_NO_RESPONSE;
self->errormsg = "No response from backend while receiving a portal query command";
mylog("send_query: 'C' - %s\n", self->errormsg);
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
ReadyToReturn = TRUE;
retres = NULL;
}
@ -1270,6 +1283,24 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
if (strnicmp(cmdbuffer, "BEGIN", 5) == 0)
{
CC_set_in_trans(self);
if (issue_begin)
{
issue_begin = FALSE;
continue;
}
}
else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
CC_on_commit(self, TRUE);
else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
CC_on_abort(self, TRUE);
else if (strnicmp(cmdbuffer, "END", 3) == 0)
CC_on_commit(self, TRUE);
else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
CC_on_abort(self, TRUE);
if (QR_command_successful(res))
QR_set_status(res, PGRES_COMMAND_OK);
QR_set_command(res, cmdbuffer);
@ -1352,14 +1383,15 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
qlog("ERROR from backend during send_query: '%s'\n", msgbuffer);
/* We should report that an error occured. Zoltan */
set_no_trans = FALSE;
if (!strncmp(msgbuffer, "FATAL", 5))
{
self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
CC_set_no_trans(self);
set_no_trans = TRUE;
}
else
self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
CC_on_abort(self, set_no_trans);
QR_set_status(res, PGRES_FATAL_ERROR);
QR_set_message(res, msgbuffer);
QR_set_aborted(res, TRUE);
@ -1377,9 +1409,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
if (query_completed)
{
res->next = QR_Constructor();
if (create_keyset)
QR_set_haskeyset(res->next);
mylog("send_query: 'T' no result_in: res = %u\n", res->next);
if (!res->next)
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
@ -1388,6 +1417,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
retres = NULL;
break;
}
if (create_keyset)
QR_set_haskeyset(res->next);
mylog("send_query: 'T' no result_in: res = %u\n", res->next);
res = res->next;
if (qi)
@ -1448,7 +1480,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
default:
self->errornumber = CONNECTION_BACKEND_CRAZY;
self->errormsg = "Unexpected protocol character from backend (send_query)";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
mylog("send_query: error - %s\n", self->errormsg);
ReadyToReturn = TRUE;
@ -1536,7 +1568,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
{
self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send function to backend";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
return FALSE;
}
@ -1545,7 +1577,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
{
self->errornumber = CONNECTION_COULD_NOT_SEND;
self->errormsg = "Could not send function to backend";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
return FALSE;
}
@ -1594,6 +1626,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
case 'E':
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
self->errormsg = msgbuffer;
CC_on_abort(self, FALSE);
mylog("send_function(V): 'E' - %s\n", self->errormsg);
qlog("ERROR from backend during send_function: '%s'\n", self->errormsg);
@ -1606,7 +1639,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
default:
self->errornumber = CONNECTION_BACKEND_CRAZY;
self->errormsg = "Unexpected protocol character from backend (send_function, args)";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
mylog("send_function: error - %s\n", self->errormsg);
return FALSE;
@ -1640,7 +1673,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
case 'E':
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
self->errormsg = msgbuffer;
CC_on_abort(self, FALSE);
mylog("send_function(G): 'E' - %s\n", self->errormsg);
qlog("ERROR from backend during send_function: '%s'\n", self->errormsg);
@ -1661,7 +1694,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
default:
self->errornumber = CONNECTION_BACKEND_CRAZY;
self->errormsg = "Unexpected protocol character from backend (send_function, result)";
CC_set_no_trans(self);
CC_on_abort(self, TRUE);
mylog("send_function: error - %s\n", self->errormsg);
return FALSE;

View File

@ -13,6 +13,7 @@
#include <stdlib.h>
#include <string.h>
#include "descriptor.h"
typedef enum
@ -242,6 +243,8 @@ struct ConnectionClass_
HENV henv; /* environment this connection was created
* on */
StatementOptions stmtOptions;
ARDFields ardOptions;
APDFields apdOptions;
char *errormsg;
int errornumber;
CONN_Status status;
@ -315,8 +318,11 @@ void CC_lookup_pg_version(ConnectionClass *conn);
void CC_initialize_pg_version(ConnectionClass *conn);
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
int CC_get_max_query_len(const ConnectionClass *self);
void CC_on_commit(ConnectionClass *conn, BOOL set_no_trans);
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans);
/* CC_send_query_options */
#define CLEAR_RESULT_ON_ABORT 1L
#define CREATE_KEYSET (1L << 1) /* create keyset for updatable curosrs */
#define GO_INTO_TRANSACTION (1L << 2) /* issue begin in advance */
#endif

View File

@ -107,7 +107,7 @@ char *mapFuncs[][2] = {
{"DAYNAME", "to_char($1, 'Day')" },
{"DAYOFMONTH", "cast(extract(day from $1) as integer)" },
{"DAYOFWEEK", "(cast(extract(dow from $1) as integer) + 1)" },
{"DAYOFYEAR", "cast(extract(doy from $1) as integer)" },
{"DAYOFYEAR", "cast(extract(doy from $1) as integer)" },
{"HOUR", "cast(extract(hour from $1) as integer)" },
{"MINUTE", "cast(extract(minute from $1) as integer)" },
{"MONTH", "cast(extract(month from $1) as integer)" },
@ -311,8 +311,9 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
int
copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col)
{
BindInfoClass *bic = &(stmt->bindings[col]);
UInt4 offset = stmt->options.row_offset_ptr ? *stmt->options.row_offset_ptr : 0;
ARDFields *opts = SC_get_ARD(stmt);
BindInfoClass *bic = &(opts->bindings[col]);
UInt4 offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) (bic->buffer + offset),
(SDWORD) bic->buflen, (SDWORD *) (bic->used + (offset >> 2)));
@ -325,6 +326,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue)
{
static char *func = "copy_and_convert_field";
ARDFields *opts = SC_get_ARD(stmt);
Int4 len = 0,
copy_len = 0;
SIMPLE_TIME st;
@ -335,7 +337,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
char *rgbValueBindRow;
const char *ptr;
int bind_row = stmt->bind_row;
int bind_size = stmt->options.bind_size;
int bind_size = opts->bind_size;
int result = COPY_OK;
BOOL changed, true_is_minus1 = FALSE;
const char *neut_str = value;
@ -349,7 +351,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if (stmt->current_col >= 0)
{
pbic = &stmt->bindings[stmt->current_col];
pbic = &opts->bindings[stmt->current_col];
if (pbic->data_left == -2)
pbic->data_left = (cbValueMax > 0) ? 0 : -1; /* This seems to be *
* needed for ADO ? */
@ -404,7 +406,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
else
{
stmt->errornumber = STMT_RETURN_NULL_WITHOUT_INDICATOR;
stmt->errormsg = "StrLen_or_IndPtr was a null pointer and NULL data was retrieved";
stmt->errormsg = "StrLen_or_IndPtr was a null pointer and NULL data was retrieved";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
@ -651,7 +653,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
pbic->data_left = -1;
}
else
pbic = &stmt->bindings[stmt->current_col];
pbic = &opts->bindings[stmt->current_col];
if (pbic->data_left < 0)
{
BOOL lf_conv = SC_get_conn(stmt)->connInfo.lf_conversion;
@ -759,7 +761,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if (cbValueMax < 2 * (SDWORD) ucount)
result = COPY_RESULT_TRUNCATED;
len = ucount * 2;
free(str);
free(str);
}
else
{
@ -923,6 +925,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
case SQL_C_ULONG:
len = 4;
inolog("rgb=%x + %d, pcb=%x, set %s\n", rgbValue, bind_row * bind_size, pcbValue, neut_str);
if (bind_size > 0)
*(UDWORD *) ((char *) rgbValue + (bind_row * bind_size)) = atol(neut_str);
else
@ -960,7 +963,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
pbic->data_left = -1;
}
else
pbic = &stmt->bindings[stmt->current_col];
pbic = &opts->bindings[stmt->current_col];
if (!pbic->ttlbuf)
pbic->ttlbuflen = 0;
if (len = strlen(neut_str), len >= (int) pbic->ttlbuflen)
@ -1026,7 +1029,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len;
if (result == COPY_OK && stmt->current_col >= 0)
stmt->bindings[stmt->current_col].data_left = 0;
opts->bindings[stmt->current_col].data_left = 0;
return result;
}
@ -1283,16 +1286,14 @@ copy_statement_with_parameters(StatementClass *stmt)
char token_save[64];
int token_len;
BOOL prev_token_end;
UInt4 offset = stmt->options.param_offset_ptr ? *stmt->options.param_offset_ptr : 0;
APDFields *opts = SC_get_APD(stmt);
UInt4 offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
UInt4 current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
BOOL lf_conv = ci->lf_conversion;
#ifdef MULTIBYTE
encoded_str encstr;
#endif /* MULTIBYTE */
#ifdef DRIVER_CURSOR_IMPLEMENT
BOOL search_from_pos = FALSE;
#endif /* DRIVER_CURSOR_IMPLEMENT */
Int4 from_pos = -1, where_pos = -1;
if (ci->disallow_premature)
@ -1324,17 +1325,20 @@ copy_statement_with_parameters(StatementClass *stmt)
{
if (stmt->parse_status == STMT_PARSE_NONE)
parse_statement(stmt);
if (stmt->parse_status != STMT_PARSE_COMPLETE)
/*if (stmt->parse_status != STMT_PARSE_COMPLETE)
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
else if (!stmt->ti || stmt->ntab != 1)
else*/ if (!stmt->updatable)
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
else
{
/** search_from_pos = TRUE; **/
from_pos = stmt->from_pos;
where_pos = stmt->where_pos;
}
}
#else
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
#endif /* DRIVER_CURSOR_IMPLEMENT */
/* If the application hasn't set a cursor name, then generate one */
@ -1433,8 +1437,7 @@ copy_statement_with_parameters(StatementClass *stmt)
*/
else if (oldchar == '{')
{
char *begin = &old_statement[opos];
const char *end;
const char *begin = &old_statement[opos], *end;
/* procedure calls */
if (stmt->statement_type == STMT_TYPE_PROCCALL)
@ -1466,8 +1469,8 @@ copy_statement_with_parameters(StatementClass *stmt)
proc_no_param = FALSE;
continue;
}
if (convert_escape(begin, stmt, &npos, &new_stsize, &end) !=
CONVERT_ESCAPE_OK)
if (convert_escape(begin, stmt, &npos, &new_stsize, &end
) != CONVERT_ESCAPE_OK)
{
stmt->errormsg = "ODBC escape convert error";
stmt->errornumber = STMT_EXEC_ERROR;
@ -1522,15 +1525,6 @@ copy_statement_with_parameters(StatementClass *stmt)
memmove(new_statement, new_statement + declare_pos, npos - declare_pos);
npos -= declare_pos;
}
#ifdef DRIVER_CURSOR_IMPLEMENT
else if (search_from_pos && /* where's from clause */
strnicmp(token_save, "from", 4) == 0)
{
search_from_pos = FALSE;
npos -= 5;
CVT_APPEND_STR(", CTID, OID from");
}
#endif /* DRIVER_CURSOR_IMPLEMENT */
}
if (token_len == 3)
{
@ -1574,7 +1568,7 @@ copy_statement_with_parameters(StatementClass *stmt)
*/
param_number++;
if (param_number >= stmt->parameters_allocated)
if (param_number >= opts->allocated)
{
if (stmt->pre_executing)
{
@ -1590,34 +1584,34 @@ copy_statement_with_parameters(StatementClass *stmt)
}
/* Assign correct buffers based on data at exec param or not */
if (stmt->parameters[param_number].data_at_exec)
if (opts->parameters[param_number].data_at_exec)
{
used = stmt->parameters[param_number].EXEC_used ? *stmt->parameters[param_number].EXEC_used : SQL_NTS;
buffer = stmt->parameters[param_number].EXEC_buffer;
used = opts->parameters[param_number].EXEC_used ? *opts->parameters[param_number].EXEC_used : SQL_NTS;
buffer = opts->parameters[param_number].EXEC_buffer;
}
else
{
UInt4 bind_size = stmt->options.param_bind_type;
UInt4 bind_size = opts->param_bind_type;
UInt4 ctypelen;
buffer = stmt->parameters[param_number].buffer + offset;
buffer = opts->parameters[param_number].buffer + offset;
if (current_row > 0)
{
if (bind_size > 0)
buffer += (bind_size * current_row);
else if (ctypelen = ctype_length(stmt->parameters[param_number].CType), ctypelen > 0)
else if (ctypelen = ctype_length(opts->parameters[param_number].CType), ctypelen > 0)
buffer += current_row * ctypelen;
else
buffer += current_row * stmt->parameters[param_number].buflen;
else
buffer += current_row * opts->parameters[param_number].buflen;
}
if (stmt->parameters[param_number].used)
if (opts->parameters[param_number].used)
{
UInt4 p_offset = offset;
if (bind_size > 0)
p_offset = offset + bind_size * current_row;
else
p_offset = offset + sizeof(SDWORD) * current_row;
used = *(SDWORD *)((char *)stmt->parameters[param_number].used + p_offset);
used = *(SDWORD *)((char *)opts->parameters[param_number].used + p_offset);
}
else
used = SQL_NTS;
@ -1649,8 +1643,8 @@ copy_statement_with_parameters(StatementClass *stmt)
}
}
param_ctype = stmt->parameters[param_number].CType;
param_sqltype = stmt->parameters[param_number].SQLType;
param_ctype = opts->parameters[param_number].CType;
param_sqltype = opts->parameters[param_number].SQLType;
mylog("copy_statement_with_params: from(fcType)=%d, to(fSqlType)=%d\n", param_ctype, param_sqltype);
@ -1907,8 +1901,8 @@ copy_statement_with_parameters(StatementClass *stmt)
case SQL_LONGVARBINARY:
if (stmt->parameters[param_number].data_at_exec)
lobj_oid = stmt->parameters[param_number].lobj_oid;
if (opts->parameters[param_number].data_at_exec)
lobj_oid = opts->parameters[param_number].lobj_oid;
else
{
/* begin transaction if needed */
@ -2048,13 +2042,14 @@ copy_statement_with_parameters(StatementClass *stmt)
}
#ifdef DRIVER_CURSOR_IMPLEMENT
if (search_from_pos)
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (!stmt->load_statement && from_pos >=0)
{
stmt->load_statement = malloc(npos + 1);
memcpy(stmt->load_statement, new_statement, npos);
stmt->load_statement[npos] = '\0';
if (stmt->load_statement[npos - 1] == ';')
stmt->load_statement[npos - 1] = '\0';
else
stmt->load_statement[npos] = '\0';
}
#endif /* DRIVER_CURSOR_IMPLEMENT */
if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
@ -2083,7 +2078,7 @@ mapFunction(const char *func, int param_count)
if (mapFuncs[i][0][0] == '%')
{
if (mapFuncs[i][0][1] - '0' == param_count &&
!stricmp(mapFuncs[i][0] + 2, func))
!stricmp(mapFuncs[i][0] + 2, func))
return mapFuncs[i][1];
}
else if (!stricmp(mapFuncs[i][0], func))
@ -2101,7 +2096,7 @@ static int processParameters(const ConnectionClass *conn, const char *value, cha
* inner_convert_escape()
* work with embedded escapes sequences
*/
static
int inner_convert_escape(const ConnectionClass *conn, const char *value,
char *result, UInt4 maxLen, const char **input_resume,
@ -2114,7 +2109,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
const char *valptr;
UInt4 vlen, prtlen, input_consumed, param_consumed, extra_len;
Int4 param_pos[16][2];
valptr = value;
if (*valptr == '{') /* skip the first { */
valptr++;
@ -2126,7 +2121,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
valptr++;
while ((*valptr != '\0') && isspace((unsigned char) *valptr))
valptr++;
if (end = my_strchr(conn, valptr, '}'), NULL == end)
{
mylog("%s couldn't find the ending }\n",func);
@ -2138,7 +2133,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
valnts[vlen] = '\0';
*input_resume = valptr + vlen; /* resume from the last } */
mylog("%s: key='%s', val='%s'\n", func, key, valnts);
extra_len = 0;
if (isalnum(result[-1])) /* Avoid the concatenation of the function name with the previous word. Aceto */
{
@ -2175,7 +2170,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
{
/* Literal; return the escape part as-is */
strncpy(result, valnts, maxLen);
prtlen = vlen;
prtlen = vlen;
}
else if (strcmp(key, "fn") == 0)
{
@ -2186,7 +2181,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
char *funcEnd = valnts;
char svchar;
const char *mapExpr;
params[sizeof(params)-1] = '\0';
while ((*funcEnd != '\0') && (*funcEnd != '(') &&
@ -2200,7 +2195,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
funcEnd++;
/*
* We expect left parenthesis here, else return fn body as-is
* We expect left parenthesis here, else return fn body as-is
* since it is one of those "function constants".
*/
if (*funcEnd != '(')
@ -2216,7 +2211,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
*/
valptr += (UInt4)(funcEnd - valnts);
if (subret = processParameters(conn, valptr, params, sizeof(params) - 1, &input_consumed, &param_consumed, param_pos), CONVERT_ESCAPE_OK != subret)
if (subret = processParameters(conn, valptr, params, sizeof(params) - 1, &input_consumed, &param_consumed, param_pos), CONVERT_ESCAPE_OK != subret)
return CONVERT_ESCAPE_ERROR;
for (param_count = 0;; param_count++)
@ -2225,9 +2220,9 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
break;
}
if (param_count == 1 &&
param_pos[0][1] < param_pos[0][0])
param_pos[0][1] < param_pos[0][0])
param_count = 0;
mapExpr = mapFunction(key, param_count);
if (mapExpr == NULL)
prtlen = snprintf(result, maxLen, "%s%s", key, params);
@ -2259,7 +2254,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
{
pidx = *mapptr - '0' - 1;
if (pidx < 0 ||
param_pos[pidx][0] <0)
param_pos[pidx][0] < 0)
{
qlog("%s %dth param not found for the expression %s\n", pidx + 1, mapExpr);
return CONVERT_ESCAPE_ERROR;
@ -2294,7 +2289,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
/* Bogus key, leave untranslated */
return CONVERT_ESCAPE_ERROR;
}
if (count)
*count = prtlen + extra_len;
if (prtlen < 0 || prtlen >= maxLen) /* buffer overflow */
@ -2304,12 +2299,12 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
}
return CONVERT_ESCAPE_OK;
}
/*
* processParameters()
* Process function parameters and work with embedded escapes sequences.
*/
static
int processParameters(const ConnectionClass *conn, const char *value,
char *result, UInt4 maxLen, UInt4 *input_consumed,
@ -2324,7 +2319,7 @@ int processParameters(const ConnectionClass *conn, const char *value,
#ifdef MULTIBYTE
encoded_str encstr;
#endif /* MULTIBYTE */
buf[sizeof(buf)-1] = '\0';
innerParenthesis = 0;
in_quote = in_dquote = in_escape = leadingSpace = FALSE;
@ -2403,7 +2398,7 @@ int processParameters(const ConnectionClass *conn, const char *value,
}
innerParenthesis++;
break;
case ')':
innerParenthesis--;
if (0 == innerParenthesis)
@ -2414,18 +2409,18 @@ int processParameters(const ConnectionClass *conn, const char *value,
param_pos[param_count][1] = -1;
}
break;
case '}':
stop = TRUE;
break;
case '{':
if (subret = inner_convert_escape(conn, valptr, buf, sizeof(buf) - 1, &valptr, &inner_count), CONVERT_ESCAPE_OK != subret)
return CONVERT_ESCAPE_ERROR;
if (inner_count + count >= maxLen)
return CONVERT_ESCAPE_OVERFLOW;
memcpy(&result[count], buf, inner_count);
memcpy(&result[count], buf, inner_count);
count += inner_count;
ipos = (UInt4) (valptr - value);
continue;
@ -2445,15 +2440,14 @@ int processParameters(const ConnectionClass *conn, const char *value,
*output_count = count;
return CONVERT_ESCAPE_OK;
}
/*
* convert_escape()
* This function returns a pointer to static memory!
*/
int
convert_escape(const char *value, StatementClass *stmt, int *npos, int *stsize,
const char **val_resume)
convert_escape(const char *value, StatementClass *stmt, int *npos, int *stsize, const char **val_resume)
{
int ret, pos = *npos;
UInt4 count;
@ -2920,12 +2914,13 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
BindInfoClass *bindInfo = NULL;
ConnectionClass *conn = SC_get_conn(stmt);
ConnInfo *ci = &(conn->connInfo);
ARDFields *opts = SC_get_ARD(stmt);
int factor = (fCType == SQL_C_CHAR ? 2 : 1);
/* If using SQLGetData, then current_col will be set */
if (stmt->current_col >= 0)
{
bindInfo = &stmt->bindings[stmt->current_col];
bindInfo = &opts->bindings[stmt->current_col];
left = bindInfo->data_left;
}

View File

@ -0,0 +1,96 @@
/* File: descriptor.h
*
* Description: This file contains defines and declarations that are related to
* the entire driver.
*
* Comments: See "notice.txt" for copyright and license information.
*
* $Id: descriptor.h,v 1.1 2002/03/28 08:08:02 inoue Exp $
*
*/
#ifndef __DESCRIPTOR_H__
#define __DESCRIPTOR_H__
#include "psqlodbc.h"
typedef struct
{
COL_INFO *col_info; /* cached SQLColumns info for this table */
char name[MAX_TABLE_LEN + 1];
char alias[MAX_TABLE_LEN + 1];
} TABLE_INFO;
typedef struct
{
TABLE_INFO *ti; /* resolve to explicit table names */
int column_size; /* precision in 2.x */
int decimal_digits; /* scale in 2.x */
int display_size;
int length;
int type;
char nullable;
char func;
char expr;
char quote;
char dquote;
char numeric;
char updatable;
char dot[MAX_TABLE_LEN + 1];
char name[MAX_COLUMN_LEN + 1];
char alias[MAX_COLUMN_LEN + 1];
} FIELD_INFO;
struct ARDFields_
{
StatementClass *stmt;
int rowset_size;
int bind_size; /* size of each structure if using Row
* Binding */
UInt2 *row_operation_ptr;
UInt4 *row_offset_ptr;
BindInfoClass *bookmark;
BindInfoClass *bindings;
int allocated;
};
struct APDFields_
{
StatementClass *stmt;
int paramset_size;
int param_bind_type; /* size of each structure if using Param
* Binding */
UInt2 *param_operation_ptr;
UInt4 *param_offset_ptr;
ParameterInfoClass *parameters;
int allocated;
};
struct IRDFields_
{
StatementClass *stmt;
UInt4 *rowsFetched;
UInt2 *rowStatusArray;
UInt4 nfields;
FIELD_INFO **fi;
};
struct IPDFields_
{
StatementClass *stmt;
UInt4 *param_processed_ptr;
UInt2 *param_status_ptr;
};
void InitializeARDFields(ARDFields *self);
void InitializeAPDFields(APDFields *self);
/* void InitializeIRDFields(IRDFields *self);
void InitializeIPDFiedls(IPDFields *self); */
void ARDFields_free(ARDFields *self);
void APDFields_free(APDFields *self);
void IRDFields_free(IRDFields *self);
void IPDFields_free(IPDFields *self);
void ARD_unbind_cols(ARDFields *self, BOOL freeall);
void APD_free_params(APDFields *self, char option);
#endif

View File

@ -120,6 +120,9 @@ driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable)
}
CheckDlgButton(hdlg, DRV_COMMLOG, comval->commlog);
#ifndef Q_LOG
EnableWindow(GetDlgItem(hdlg, DRV_COMMLOG), FALSE);
#endif /* Q_LOG */
CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer);
CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo);
CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index);
@ -153,6 +156,9 @@ driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable)
CheckDlgButton(hdlg, DRV_PARSE, comval->parse);
CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, comval->cancel_as_freestmt);
CheckDlgButton(hdlg, DRV_DEBUG, comval->debug);
#ifndef MY_LOG
EnableWindow(GetDlgItem(hdlg, DRV_DEBUG), FALSE);
#endif /* MY_LOG */
SetDlgItemInt(hdlg, DRV_CACHE_SIZE, comval->fetch_max, FALSE);
SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, comval->max_varchar_size, FALSE);
SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, comval->max_longvarchar_size, TRUE);
@ -221,7 +227,7 @@ driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile)
int CALLBACK
driver_optionsProc(HWND hdlg,
WORD wMsg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam)
{
@ -293,7 +299,7 @@ driver_optionsProc(HWND hdlg,
int CALLBACK
ds_optionsProc(HWND hdlg,
WORD wMsg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam)
{
@ -334,6 +340,10 @@ ds_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DS_DISALLOWPREMATURE, ci->disallow_premature);
CheckDlgButton(hdlg, DS_LFCONVERSION, ci->lf_conversion);
CheckDlgButton(hdlg, DS_TRUEISMINUS1, ci->true_is_minus1);
CheckDlgButton(hdlg, DS_UPDATABLECURSORS, ci->updatable_cursors);
#ifndef DRIVER_CURSOR_IMPLEMENT
EnableWindow(GetDlgItem(hdlg, DS_UPDATABLECURSORS), FALSE);
#endif /* DRIVER_CURSOR_IMPLEMENT */
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column));
@ -371,6 +381,9 @@ ds_optionsProc(HWND hdlg,
ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE);
ci->lf_conversion = IsDlgButtonChecked(hdlg, DS_LFCONVERSION);
ci->true_is_minus1 = IsDlgButtonChecked(hdlg, DS_TRUEISMINUS1);
#ifdef DRIVER_CURSOR_IMPLEMENT
ci->updatable_cursors = IsDlgButtonChecked(hdlg, DS_UPDATABLECURSORS);
#endif /* DRIVER_CURSOR_IMPLEMENT */
/* OID Options */
sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX));

View File

@ -169,11 +169,11 @@ void SetDlgStuff(HWND hdlg, const ConnInfo *ci);
void GetDlgStuff(HWND hdlg, ConnInfo *ci);
int CALLBACK driver_optionsProc(HWND hdlg,
WORD wMsg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam);
int CALLBACK ds_optionsProc(HWND hdlg,
WORD wMsg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam);
#endif /* WIN32 */

View File

@ -94,7 +94,7 @@ PGAPI_StmtError( HSTMT hstmt,
StatementClass *stmt = (StatementClass *) hstmt;
char *msg;
int status;
BOOL partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),
BOOL partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),
clear_str = ((flag & PODBC_ERROR_CLEAR) != 0);
SWORD msglen, stapos, wrtlen, pcblen;
@ -275,6 +275,9 @@ PGAPI_StmtError( HSTMT hstmt,
case STMT_OPERATION_INVALID:
strcpy(szSqlState, "S1011");
break;
case STMT_INVALID_DESCRIPTOR_IDENTIFIER:
strcpy(szSqlState, "HY091");
break;
case STMT_INVALID_OPTION_IDENTIFIER:
strcpy(szSqlState, "HY092");
break;
@ -313,6 +316,7 @@ PGAPI_ConnectError( HDBC hdbc,
BOOL once_again = FALSE;
SWORD msglen;
mylog("**** PGAPI_ConnectError: hdbc=%u <%d>\n", hdbc, cbErrorMsgMax);
if (RecNumber != 1)
return SQL_NO_DATA_FOUND;
if (cbErrorMsgMax < 0)
@ -361,6 +365,7 @@ PGAPI_ConnectError( HDBC hdbc,
strcpy(szSqlState, "IM002");
/* data source not found */
break;
case CONNECTION_SERVER_NOT_REACHED:
case CONN_OPENDB_ERROR:
strcpy(szSqlState, "08001");
/* unable to connect to data source */
@ -413,6 +418,7 @@ PGAPI_ConnectError( HDBC hdbc,
break;
}
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, msglen, szErrorMsg);
if (once_again)
{
conn->errornumber = status;
@ -436,6 +442,7 @@ PGAPI_EnvError( HENV henv,
char *msg;
int status;
mylog("**** PGAPI_EnvError: henv=%u <%d>\n", henv, cbErrorMsgMax);
if (RecNumber != 1)
return SQL_NO_DATA_FOUND;
if (cbErrorMsgMax < 0)
@ -567,7 +574,7 @@ EN_Destructor(EnvironmentClass *self)
mylog("exit EN_Destructor: rv = %d\n", rv);
#ifdef _MEMORY_DEBUG_
debug_memory_inouecheck();
debug_memory_check();
#endif /* _MEMORY_DEBUG_ */
return rv;
}

View File

@ -206,9 +206,12 @@ PGAPI_Execute(
{
static char *func = "PGAPI_Execute";
StatementClass *stmt = (StatementClass *) hstmt;
APDFields *opts;
IPDFields *ipdopts;
ConnectionClass *conn;
int i,
retval, start_row, end_row;
int cursor_type, scroll_concurrency;
mylog("%s: entering...\n", func);
@ -219,6 +222,9 @@ PGAPI_Execute(
return SQL_INVALID_HANDLE;
}
opts = SC_get_APD(stmt);
cursor_type = stmt->options.cursor_type;
scroll_concurrency = stmt->options.scroll_concurrency;
/*
* If the statement is premature, it means we already executed it from
* an SQLPrepare/SQLDescribeCol type of scenario. So just return
@ -297,24 +303,25 @@ PGAPI_Execute(
if (start_row = stmt->exec_start_row, start_row < 0)
start_row = 0;
if (end_row = stmt->exec_end_row, end_row < 0)
end_row = stmt->options.paramset_size - 1;
end_row = opts->paramset_size - 1;
if (stmt->exec_current_row < 0)
stmt->exec_current_row = start_row;
ipdopts = SC_get_IPD(stmt);
if (stmt->exec_current_row == start_row)
{
if (stmt->options.param_processed_ptr)
*stmt->options.param_processed_ptr = 0;
if (ipdopts->param_processed_ptr)
*ipdopts->param_processed_ptr = 0;
SC_recycle_statement(stmt);
}
next_param_row:
#if (ODBCVER >= 0x0300)
if (stmt->options.param_operation_ptr)
if (opts->param_operation_ptr)
{
while (stmt->options.param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
while (opts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
{
if (stmt->options.param_status_ptr)
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_UNUSED;
if (ipdopts->param_status_ptr)
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_UNUSED;
if (stmt->exec_current_row >= end_row)
{
stmt->exec_current_row = -1;
@ -335,16 +342,16 @@ next_param_row:
* execute of this statement? Therefore check for params and
* re-copy.
*/
UInt4 offset = stmt->options.param_offset_ptr ? *stmt->options.param_offset_ptr : 0;
Int4 bind_size = stmt->options.param_bind_type;
UInt4 offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
Int4 bind_size = opts->param_bind_type;
Int4 current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
stmt->data_at_exec = -1;
for (i = 0; i < stmt->parameters_allocated; i++)
for (i = 0; i < opts->allocated; i++)
{
Int4 *pcVal = stmt->parameters[i].used;
Int4 *pcVal = opts->parameters[i].used;
stmt->parameters[i].data_at_exec = FALSE;
opts->parameters[i].data_at_exec = FALSE;
if (pcVal)
{
if (bind_size > 0)
@ -352,10 +359,10 @@ next_param_row:
else
pcVal = (Int4 *)((char *)pcVal + offset + sizeof(SDWORD) * current_row);
if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
stmt->parameters[i].data_at_exec = TRUE;
opts->parameters[i].data_at_exec = TRUE;
}
/* Check for data at execution parameters */
if (stmt->parameters[i].data_at_exec)
if (opts->parameters[i].data_at_exec)
{
if (stmt->data_at_exec < 0)
stmt->data_at_exec = 1;
@ -394,22 +401,22 @@ next_param_row:
retval = SC_execute(stmt);
if (retval != SQL_ERROR)
{
if (stmt->options.param_processed_ptr)
(*stmt->options.param_processed_ptr)++;
if (ipdopts->param_processed_ptr)
(*ipdopts->param_processed_ptr)++;
}
#if (ODBCVER >= 0x0300)
if (stmt->options.param_status_ptr)
if (ipdopts->param_status_ptr)
{
switch (retval)
{
case SQL_SUCCESS:
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
break;
case SQL_SUCCESS_WITH_INFO:
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
break;
default:
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
break;
}
}
@ -447,7 +454,6 @@ next_param_row:
}
}
/* we are now in a transaction */
CC_set_in_trans(conn);
res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
if (!res)
{
@ -464,13 +470,18 @@ next_param_row:
{
if (issued_begin)
CC_commit(conn);
else if (!in_trans && begin_included)
CC_set_no_trans(conn);
}
stmt->status = STMT_FINISHED;
return SQL_SUCCESS;
}
else
else if (stmt->options.cursor_type != cursor_type ||
stmt->options.scroll_concurrency != scroll_concurrency)
{
stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
stmt->errormsg = "cursor updatability changed";
return SQL_SUCCESS_WITH_INFO;
}
else
return SQL_SUCCESS;
}
@ -534,11 +545,10 @@ PGAPI_Transact(
mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
res = CC_send_query(conn, stmt_string, NULL, CLEAR_RESULT_ON_ABORT);
CC_set_no_trans(conn);
if (!res)
{
/* error msg will be in the connection */
CC_on_abort(conn, TRUE);
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -548,6 +558,7 @@ PGAPI_Transact(
if (!ok)
{
CC_on_abort(conn, TRUE);
CC_log_error(func, "", conn);
return SQL_ERROR;
}
@ -697,6 +708,8 @@ PGAPI_ParamData(
{
static char *func = "PGAPI_ParamData";
StatementClass *stmt = (StatementClass *) hstmt;
APDFields *opts;
IPDFields *ipdopts;
int i,
retval;
ConnInfo *ci;
@ -709,8 +722,9 @@ PGAPI_ParamData(
return SQL_INVALID_HANDLE;
}
ci = &(SC_get_conn(stmt)->connInfo);
opts = SC_get_APD(stmt);
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, opts->allocated);
if (stmt->data_at_exec < 0)
{
@ -720,7 +734,7 @@ PGAPI_ParamData(
return SQL_ERROR;
}
if (stmt->data_at_exec > stmt->parameters_allocated)
if (stmt->data_at_exec > opts->allocated)
{
stmt->errornumber = STMT_SEQUENCE_ERROR;
stmt->errormsg = "Too many execution-time parameters were present";
@ -748,6 +762,7 @@ PGAPI_ParamData(
}
/* Done, now copy the params and then execute the statement */
ipdopts = SC_get_IPD(stmt);
if (stmt->data_at_exec == 0)
{
int end_row;
@ -761,28 +776,29 @@ PGAPI_ParamData(
retval = SC_execute(stmt);
if (retval != SQL_ERROR)
{
if (stmt->options.param_processed_ptr)
(*stmt->options.param_processed_ptr)++;
if (ipdopts->param_processed_ptr)
(*ipdopts->param_processed_ptr)++;
}
#if (ODBCVER >= 0x0300)
if (stmt->options.param_status_ptr)
if (ipdopts->param_status_ptr)
{
switch (retval)
{
case SQL_SUCCESS:
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
break;
case SQL_SUCCESS_WITH_INFO:
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
break;
default:
stmt->options.param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
break;
}
}
#endif /* ODBCVER */
if (stmt->exec_end_row < 0)
end_row = stmt->options.paramset_size - 1;
end_row = stmt->exec_end_row;
if (end_row < 0)
end_row = opts->paramset_size - 1;
if (retval == SQL_ERROR ||
stmt->exec_current_row >= end_row)
{
@ -800,14 +816,14 @@ PGAPI_ParamData(
i = stmt->current_exec_param >= 0 ? stmt->current_exec_param + 1 : 0;
/* At least 1 data at execution parameter, so Fill in the token value */
for (; i < stmt->parameters_allocated; i++)
for (; i < opts->allocated; i++)
{
if (stmt->parameters[i].data_at_exec)
if (opts->parameters[i].data_at_exec)
{
stmt->data_at_exec--;
stmt->current_exec_param = i;
stmt->put_data = FALSE;
*prgbValue = stmt->parameters[i].buffer; /* token */
*prgbValue = opts->parameters[i].buffer; /* token */
break;
}
}
@ -828,6 +844,7 @@ PGAPI_PutData(
{
static char *func = "PGAPI_PutData";
StatementClass *stmt = (StatementClass *) hstmt;
APDFields *opts;
int old_pos,
retval;
ParameterInfoClass *current_param;
@ -841,6 +858,7 @@ PGAPI_PutData(
return SQL_INVALID_HANDLE;
}
opts = SC_get_APD(stmt);
if (stmt->current_exec_param < 0)
{
stmt->errornumber = STMT_SEQUENCE_ERROR;
@ -849,7 +867,7 @@ PGAPI_PutData(
return SQL_ERROR;
}
current_param = &(stmt->parameters[stmt->current_exec_param]);
current_param = &(opts->parameters[stmt->current_exec_param]);
if (!stmt->put_data)
{ /* first call */

View File

@ -107,7 +107,7 @@ PGAPI_GetInfo(
case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
/* very simple bookmark support */
len = 4;
value = ci->drivers.use_declarefetch ? 0 : (SQL_BP_SCROLL);
value = ci->drivers.use_declarefetch ? 0 : (SQL_BP_SCROLL | SQL_BP_DELETE | SQL_BP_UPDATE | SQL_BP_TRANSACTION);
break;
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
@ -495,8 +495,10 @@ PGAPI_GetInfo(
case SQL_POS_OPERATIONS: /* ODBC 2.0 */
len = 4;
value = ci->drivers.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH);
#ifdef DRIVER_CURSOR_IMPLEMENT
if (ci->updatable_cursors)
value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD);
#endif /* DRIVER_CURSOR_IMPLEMENT */
break;
case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
@ -554,8 +556,10 @@ PGAPI_GetInfo(
SQL_SCCO_OPT_ROWVER |
SQL_SCCO_OPT_VALUES) :
(SQL_SCCO_READ_ONLY);
#ifdef DRIVER_CURSOR_IMPLEMENT
if (ci->updatable_cursors)
value |= SQL_SCCO_OPT_ROWVER;
#endif /* DRIVER_CURSOR_IMPLEMENT */
break;
case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
@ -588,8 +592,10 @@ PGAPI_GetInfo(
case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
len = 4;
value = ci->drivers.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0;
#ifdef DRIVER_CURSOR_IMPLEMENT
if (ci->updatable_cursors)
value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES);
#endif /* DRIVER_CURSOR_IMPLEMENT */
break;
case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
@ -753,7 +759,11 @@ PGAPI_GetTypeInfo(
}
SC_set_Result(stmt, res);
extend_bindings(stmt, 15);
#if (ODBCVER >= 0x0399)
extend_column_bindings(SC_get_ARD(stmt), 19);
#else
extend_column_bindings(SC_get_ARD(stmt), 15);
#endif /* ODBCVER */
QR_set_num_fields(res, 15);
QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
@ -771,6 +781,12 @@ PGAPI_GetTypeInfo(
QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
#if (ODBCVER >=0x0399)
QR_set_field_info(res, 15, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(res, 16, "SQL_DATATIME_SUB", PG_TYPE_INT2, 2);
QR_set_field_info(res, 17, "NUM_PREC_RADIX", PG_TYPE_INT4, 4);
QR_set_field_info(res, 18, "INTERVAL_PRECISION", PG_TYPE_INT2, 2);
#endif /* ODBCVER */
for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
{
@ -795,7 +811,7 @@ PGAPI_GetTypeInfo(
set_tuplefield_null(&row->tuple[12]);
/* These values can be NULL */
set_nullfield_int4(&row->tuple[2], pgtype_precision(stmt, pgType, PG_STATIC, PG_STATIC));
set_nullfield_int4(&row->tuple[2], pgtype_column_size(stmt, pgType, PG_STATIC, PG_STATIC));
set_nullfield_string(&row->tuple[3], pgtype_literal_prefix(stmt, pgType));
set_nullfield_string(&row->tuple[4], pgtype_literal_suffix(stmt, pgType));
set_nullfield_string(&row->tuple[5], pgtype_create_params(stmt, pgType));
@ -803,6 +819,12 @@ PGAPI_GetTypeInfo(
set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType));
set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
#if (ODBCVER >=0x0399)
set_nullfield_int2(&row->tuple[15], pgtype_sqldesctype(stmt, pgType));
set_nullfield_int2(&row->tuple[16], pgtype_datetime_sub(stmt, pgType));
set_nullfield_int4(&row->tuple[17], pgtype_radix(stmt, pgType));
set_nullfield_int4(&row->tuple[18], 0);
#endif /* ODBCVER */
QR_add_tuple(res, row);
}
@ -1317,7 +1339,7 @@ PGAPI_Tables(
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
extend_bindings(stmt, 5);
extend_column_bindings(SC_get_ARD(stmt), 5);
/* set the field names */
QR_set_num_fields(res, 5);
@ -1523,13 +1545,15 @@ PGAPI_Columns(
field_name[MAX_INFO_STRING],
field_type_name[MAX_INFO_STRING];
Int2 field_number, sqltype,
reserved_cols,
result_cols,
scale;
decimal_digits;
Int4 field_type,
the_type,
field_length,
mod_length,
precision;
column_size,
ordinal;
char useStaticPrecision;
char not_null[MAX_INFO_STRING],
relhasrules[MAX_INFO_STRING];
@ -1735,11 +1759,12 @@ PGAPI_Columns(
* ourselves.
*/
#if (ODBCVER >= 0x0300)
result_cols = 18;
reserved_cols = 18;
#else
result_cols = 14;
reserved_cols = 12;
#endif /* ODBCVER */
extend_bindings(stmt, result_cols);
result_cols = reserved_cols + 2;
extend_column_bindings(SC_get_ARD(stmt), result_cols);
/* set the field names */
QR_set_num_fields(res, result_cols);
@ -1749,9 +1774,9 @@ PGAPI_Columns(
QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4);
QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4);
QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4); /* COLUMN_SIZE */
QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4); /* BUFFER_LENGTH */
QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2); /* DECIMAL_DIGITS ***/
QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
QR_set_field_info(res, 11, "REMARKS", PG_TYPE_TEXT, 254);
@ -1764,11 +1789,11 @@ PGAPI_Columns(
QR_set_field_info(res, 15, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
QR_set_field_info(res, 16, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
QR_set_field_info(res, 17, "IS_NULLABLE", PG_TYPE_TEXT, 254);
#else
QR_set_field_info(res, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
QR_set_field_info(res, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
#endif /* ODBCVER */
QR_set_field_info(res, reserved_cols, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
QR_set_field_info(res, reserved_cols + 1, "FIELD_TYPE", PG_TYPE_INT4, 4);
ordinal = 1;
result = PGAPI_Fetch(hcol_stmt);
/*
@ -1794,14 +1819,13 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "oid");
sqltype = pgtype_to_sqltype(stmt, the_type);
sqltype = pgtype_to_concise_type(stmt, the_type);
set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], "OID");
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, PG_STATIC));
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
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], "");
@ -1810,15 +1834,15 @@ PGAPI_Columns(
set_tuplefield_null(&row->tuple[12]);
set_tuplefield_int2(&row->tuple[13], sqltype);
set_tuplefield_null(&row->tuple[14]);
set_tuplefield_int4(&row->tuple[15], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[16], 0);
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[16], ordinal);
set_tuplefield_string(&row->tuple[17], "No");
#else
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type);
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[reserved_cols + 1], the_type);
QR_add_tuple(res, row);
ordinal++;
}
}
@ -1834,7 +1858,7 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], field_name);
sqltype = pgtype_to_sqltype(stmt, field_type);
sqltype = pgtype_to_concise_type(stmt, field_type);
set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], field_type_name);
@ -1845,15 +1869,15 @@ PGAPI_Columns(
* 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:
* NUMERIC - the decimal_digits is stored in atttypmod as follows:
*
* precision =((atttypmod - VARHDRSZ) >> 16) & 0xffff
* scale = (atttypmod - VARHDRSZ) & 0xffff
* column_size =((atttypmod - VARHDRSZ) >> 16) & 0xffff
* decimal_digits = (atttypmod - VARHDRSZ) & 0xffff
*
*----------
*/
qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n",
table_name, field_name, field_type, pgtype_to_sqltype, field_type_name);
qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,name='%s'\n",
table_name, field_name, field_type, field_type_name);
useStaticPrecision = TRUE;
@ -1866,15 +1890,18 @@ PGAPI_Columns(
{
useStaticPrecision = FALSE;
precision = (mod_length >> 16) & 0xffff;
scale = mod_length & 0xffff;
column_size = (mod_length >> 16) & 0xffff;
decimal_digits = mod_length & 0xffff;
mylog("%s: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", func, field_type, mod_length, precision, scale);
mylog("%s: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", func, field_type, mod_length, column_size, decimal_digits);
set_tuplefield_int4(&row->tuple[7], precision + 2); /* sign+dec.point */
set_tuplefield_int4(&row->tuple[6], precision);
set_tuplefield_int4(&row->tuple[12], precision + 2); /* sign+dec.point */
set_nullfield_int2(&row->tuple[8], scale);
set_tuplefield_int4(&row->tuple[6], column_size);
set_tuplefield_int4(&row->tuple[7], column_size + 2); /* sign+dec.point */
set_nullfield_int2(&row->tuple[8], decimal_digits);
#if (ODBCVER >= 0x0300)
set_tuplefield_null(&row->tuple[15]);
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols], column_size + 2); /* sign+dec.point */
}
}
@ -1891,54 +1918,42 @@ PGAPI_Columns(
mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
set_tuplefield_int4(&row->tuple[7], mod_length);
set_tuplefield_int4(&row->tuple[6], mod_length);
set_tuplefield_int4(&row->tuple[12], mod_length);
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], mod_length);
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
#if (ODBCVER >= 0x0300)
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, field_type, PG_STATIC, PG_STATIC));
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols], mod_length);
}
if (useStaticPrecision)
{
mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
mylog("%s: field type is OTHER: field_type = %d, pgtype_length = %d\n", func, field_type, pgtype_buffer_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[6], pgtype_precision(stmt, field_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC));
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, field_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
#if (ODBCVER >= 0x0300)
set_tuplefield_null(&row->tuple[15]);
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
}
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
set_tuplefield_string(&row->tuple[11], "");
#if (ODBCVER >= 0x0300)
switch (sqltype)
{
case SQL_TYPE_DATE:
set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
set_tuplefield_int2(&row->tuple[14], SQL_CODE_DATE);
break;
case SQL_TYPE_TIME:
set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIME);
break;
case SQL_TYPE_TIMESTAMP:
set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIMESTAMP);
break;
default:
set_tuplefield_int2(&row->tuple[13], sqltype);
set_tuplefield_null(&row->tuple[14]);
break;
}
set_tuplefield_int4(&row->tuple[15], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[16], field_number);
set_tuplefield_null(&row->tuple[12]);
set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type));
set_nullfield_int2(&row->tuple[14], pgtype_to_datetime_sub(stmt, field_type));
set_tuplefield_int4(&row->tuple[16], ordinal);
set_tuplefield_null(&row->tuple[17]);
#else
set_tuplefield_int4(&row->tuple[13], field_type);
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols + 1], field_type);
QR_add_tuple(res, row);
ordinal++;
result = PGAPI_Fetch(hcol_stmt);
@ -1968,12 +1983,12 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "xmin");
sqltype = pgtype_to_sqltype(stmt, the_type);
sqltype = pgtype_to_concise_type(stmt, the_type);
set_tuplefield_int2(&row->tuple[4], sqltype);
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, PG_STATIC));
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
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], "");
@ -1981,15 +1996,15 @@ PGAPI_Columns(
set_tuplefield_null(&row->tuple[12]);
set_tuplefield_int2(&row->tuple[13], sqltype);
set_tuplefield_null(&row->tuple[14]);
set_tuplefield_int4(&row->tuple[15], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[16], 0);
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[16], ordinal);
set_tuplefield_string(&row->tuple[17], "No");
#else
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type);
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[reserved_cols + 1], the_type);
QR_add_tuple(res, row);
ordinal++;
}
/*
@ -2096,7 +2111,7 @@ PGAPI_SpecialColumns(
res = QR_Constructor();
SC_set_Result(stmt, res);
extend_bindings(stmt, 8);
extend_column_bindings(SC_get_ARD(stmt), 8);
QR_set_num_fields(res, 8);
QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
@ -2117,11 +2132,11 @@ PGAPI_SpecialColumns(
set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION);
set_tuplefield_string(&row->tuple[1], "oid");
set_tuplefield_int2(&row->tuple[2], pgtype_to_sqltype(stmt, PG_TYPE_OID));
set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, PG_TYPE_OID));
set_tuplefield_string(&row->tuple[3], "OID");
set_tuplefield_int4(&row->tuple[4], pgtype_precision(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[5], pgtype_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC));
set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, PG_TYPE_OID, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
QR_add_tuple(res, row);
@ -2137,11 +2152,11 @@ PGAPI_SpecialColumns(
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_int2(&row->tuple[2], pgtype_to_concise_type(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, PG_STATIC));
set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int2(&row->tuple[6], pgtype_decimal_digits(stmt, the_type, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
QR_add_tuple(res, row);
@ -2227,7 +2242,7 @@ PGAPI_Statistics(
* a statement is actually executed, so we'll have to do this
* ourselves.
*/
extend_bindings(stmt, 13);
extend_column_bindings(SC_get_ARD(stmt), 13);
/* set the field names */
QR_set_num_fields(res, 13);
@ -2671,7 +2686,7 @@ PGAPI_PrimaryKeys(
* ourselves.
*/
result_cols = 6;
extend_bindings(stmt, result_cols);
extend_column_bindings(SC_get_ARD(stmt), result_cols);
/* set the field names */
QR_set_num_fields(res, result_cols);
@ -3067,7 +3082,7 @@ PGAPI_ForeignKeys(
* ourselves.
*/
result_cols = 14;
extend_bindings(stmt, result_cols);
extend_column_bindings(SC_get_ARD(stmt), result_cols);
/* set the field names */
QR_set_num_fields(res, result_cols);
@ -3803,7 +3818,7 @@ PGAPI_Procedures(
* results can be retrieved.
*/
stmt->status = STMT_FINISHED;
extend_bindings(stmt, 8);
extend_column_bindings(SC_get_ARD(stmt), 8);
/* set up the current tuple pointer for SQLFetch */
stmt->currTuple = -1;
stmt->rowset_start = -1;
@ -3891,7 +3906,7 @@ PGAPI_TablePrivileges(
* ourselves.
*/
result_cols = 7;
extend_bindings(stmt, result_cols);
extend_column_bindings(SC_get_ARD(stmt), result_cols);
/* set the field names */
stmt->manual_result = TRUE;
@ -3983,7 +3998,7 @@ PGAPI_TablePrivileges(
char *grolist, *uid, *delm;
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
if ((gres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT)))
if (gres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), gres != NULL)
{
grolist = QR_get_value_backend_row(gres, 0, 0);
if (grolist && grolist[0] == '{')

View File

@ -53,14 +53,13 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
| SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
| SQL_CA1_POS_REFRESH);
if (ci->drivers.lie)
value |= (SQL_CA1_BULK_ADD
| SQL_CA1_POS_REFRESH | SQL_CA1_BULK_ADD
| SQL_CA1_BULK_UPDATE_BY_BOOKMARK
| SQL_CA1_BULK_DELETE_BY_BOOKMARK
| SQL_CA1_BULK_FETCH_BY_BOOKMARK
| SQL_CA1_LOCK_EXCLUSIVE
);
if (ci->drivers.lie)
value |= (SQL_CA1_LOCK_EXCLUSIVE
| SQL_CA1_LOCK_UNLOCK
| SQL_CA1_POSITIONED_UPDATE
| SQL_CA1_POSITIONED_DELETE
@ -72,9 +71,10 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
value = 0;
if (ci->updatable_cursors || ci->drivers.lie)
value |= (SQL_CA2_OPT_ROWVER_CONCURRENCY
| SQL_CA2_SENSITIVITY_ADDITIONS
| SQL_CA2_SENSITIVITY_DELETIONS
| SQL_CA2_SENSITIVITY_UPDATES);
| SQL_CA2_SENSITIVITY_UPDATES
/* | SQL_CA2_SENSITIVITY_ADDITIONS */
);
if (ci->drivers.lie)
value |= (SQL_CA2_READ_ONLY_CONCURRENCY
| SQL_CA2_LOCK_CONCURRENCY
@ -97,19 +97,21 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
len = 4;
value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION;
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
| SQL_CA1_POS_REFRESH;
if (ci->updatable_cursors)
value |= (SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
| SQL_CA1_POS_REFRESH);
);
break;
case SQL_STATIC_CURSOR_ATTRIBUTES2:
len = 4;
value = 0;
value = SQL_CA2_READ_ONLY_CONCURRENCY;
if (ci->updatable_cursors)
value |= (SQL_CA2_OPT_ROWVER_CONCURRENCY
| SQL_CA2_SENSITIVITY_ADDITIONS
/* | SQL_CA2_SENSITIVITY_ADDITIONS
| SQL_CA2_SENSITIVITY_DELETIONS
| SQL_CA2_SENSITIVITY_UPDATES);
| SQL_CA2_SENSITIVITY_UPDATES */
);
break;
case SQL_ODBC_INTERFACE_CONFORMANCE:

View File

@ -115,6 +115,11 @@ mylog(char *fmt,...)
va_end(args);
}
}
#else
void
MyLog(char *fmt,...)
{
}
#endif

View File

@ -36,17 +36,18 @@
#define MYLOGDIR "/tmp"
#else
#define MYLOGDIR "c:"
#endif
#endif /* WIN32 */
extern void mylog(char *fmt,...);
#define inolog mylog /* for really temporary debug */
#else
#ifndef WIN32
#define mylog(args...) /* GNU convention for variable arguments */
#else
#define mylog /* mylog */
#endif
#endif
extern void MyLog(char *fmt,...);
#define mylog if (0) MyLog /* mylog */
#endif /* WIN32 */
#endif /* MY_LOG */
#define inolog mylog /* for really temporary debug */
#ifdef Q_LOG
#define QLOGFILE "psqlodbc_"
@ -64,6 +65,7 @@ extern void qlog(char *fmt,...);
#define qlog /* qlog */
#endif
#endif
#define inoqlog qlog
#ifndef WIN32
#define DIRSEPARATOR "/"

View File

@ -59,7 +59,7 @@ pg_CS CS_Table[] =
{ "OTHER", OTHER }
};
int
static int
pg_ismb(int characterset_code)
{
int i=0,MB_CHARACTERSET[]={EUC_JP,EUC_CN,EUC_KR,EUC_TW,UTF8,MULE_INTERNAL,SJIS,BIG5,GBK,UHC,JOHAB};
@ -228,8 +228,8 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code)
character > 0xa0)
stat = 3;
else if (stat == 3 ||
(stat < 2 &&
character > 0xa0))
stat < 2 &&
character > 0xa0)
stat = 2;
else if (stat == 2)
stat = 1;

View File

@ -86,7 +86,4 @@ void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str);
#define make_encoded_str(encstr, conn, str) encoded_str_constr(encstr, conn->ccsc, str)
extern int encoded_nextchar(encoded_str *encstr);
extern int encoded_byte_check(encoded_str *encstr, int abspos);
/* This doesn't seem to be called by anyone, bjm 2002-03-24 */
extern int pg_ismb(int characterset_code);
#define check_client_encoding(X) pg_CS_name(pg_CS_code(X))

View File

@ -204,8 +204,9 @@ SQLFetch(HSTMT StatementHandle)
if (conn->driver_version >= 0x0300)
{
SQLUSMALLINT *rowStatusArray = stmt->options.rowStatusArray;
SQLINTEGER *pcRow = stmt->options.rowsFetched;
IRDFields *irdopts = SC_get_IRD(stmt);
SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
SQLINTEGER *pcRow = irdopts->rowsFetched;
mylog("[[%s]]", func);
return PGAPI_ExtendedFetch(StatementHandle, SQL_FETCH_NEXT, 0,

View File

@ -155,8 +155,9 @@ SQLFetchScroll(HSTMT StatementHandle,
static char *func = "SQLFetchScroll";
StatementClass *stmt = (StatementClass *) StatementHandle;
RETCODE ret;
SQLUSMALLINT *rowStatusArray = stmt->options.rowStatusArray;
SQLINTEGER *pcRow = stmt->options.rowsFetched;
IRDFields *irdopts = SC_get_IRD(stmt);
SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
SQLINTEGER *pcRow = irdopts->rowsFetched;
mylog("[[%s]] %d,%d\n", func, FetchOrientation, FetchOffset);
if (FetchOrientation == SQL_FETCH_BOOKMARK)
@ -208,8 +209,8 @@ SQLGetDescField(SQLHDESC DescriptorHandle,
SQLINTEGER *StringLength)
{
mylog("[[SQLGetDescField]]\n");
mylog("Error not implemented\n");
return SQL_ERROR;
return PGAPI_GetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
Value, BufferLength, StringLength);
}
/* new function */
@ -233,7 +234,7 @@ SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
PTR DiagInfo, SQLSMALLINT BufferLength,
SQLSMALLINT *StringLength)
{
mylog("[[SQLGetDiagField]]\n");
mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", HandleType, Handle, RecNumber, DiagIdentifier);
return SQL_ERROR;
}
@ -285,21 +286,9 @@ SQLGetConnectAttr(HDBC ConnectionHandle,
SQLINTEGER Attribute, PTR Value,
SQLINTEGER BufferLength, SQLINTEGER *StringLength)
{
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
mylog("[[SQLGetConnectAttr]] %d\n", Attribute);
switch (Attribute)
{
case SQL_ATTR_ASYNC_ENABLE:
case SQL_ATTR_AUTO_IPD:
case SQL_ATTR_CONNECTION_DEAD:
case SQL_ATTR_CONNECTION_TIMEOUT:
case SQL_ATTR_METADATA_ID:
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
conn->errormsg = "Unsupported connection option (Set)";
return SQL_ERROR;
}
return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value);
return PGAPI_GetConnectAttr(ConnectionHandle, Attribute,Value,
BufferLength, StringLength);
}
/* SQLGetStmtOption -> SQLGetStmtAttr */
@ -309,91 +298,10 @@ SQLGetStmtAttr(HSTMT StatementHandle,
SQLINTEGER BufferLength, SQLINTEGER *StringLength)
{
static char *func = "SQLGetStmtAttr";
StatementClass *stmt = (StatementClass *) StatementHandle;
RETCODE ret = SQL_SUCCESS;
int len = 0;
mylog("[[%s]] Handle=%u %d\n", func, StatementHandle, Attribute);
switch (Attribute)
{
case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */
Value = stmt->options.bookmark_ptr;
len = 4;
break;
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
Value = stmt->options.param_offset_ptr;
len = 4;
break;
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
*((SQLUINTEGER *) Value) = stmt->options.param_bind_type;
len = 4;
break;
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
Value = stmt->options.param_operation_ptr;
len = 4;
break;
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
Value = stmt->options.param_status_ptr;
len = 4;
break;
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
Value = stmt->options.param_processed_ptr;
len = 4;
break;
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
*((SQLUINTEGER *) Value) = stmt->options.paramset_size;
len = 4;
break;
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
Value = stmt->options.row_offset_ptr;
len = 4;
break;
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
Value = stmt->options.row_operation_ptr;
len = 4;
break;
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
Value = stmt->options.rowStatusArray;
len = 4;
break;
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
Value = stmt->options.rowsFetched;
len = 4;
break;
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
*((SQLUINTEGER *) Value) = stmt->options.rowset_size;
len = 4;
break;
case SQL_ATTR_APP_ROW_DESC: /* 10010 */
case SQL_ATTR_APP_PARAM_DESC: /* 10011 */
case SQL_ATTR_IMP_ROW_DESC: /* 10012 */
case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */
len = 4;
*((HSTMT *) Value) = descHandleFromStatementHandle(StatementHandle, Attribute);
break;
case SQL_ATTR_AUTO_IPD: /* 10001 */
/* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */
case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */
case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */
case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */
case SQL_ATTR_METADATA_ID: /* 10014 */
/*
* case SQL_ATTR_PREDICATE_PTR: case
* SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
*/
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "Unsupported statement option (Get)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
default:
len = 4;
ret = PGAPI_GetStmtOption(StatementHandle, (UWORD) Attribute, Value);
}
if (ret == SQL_SUCCESS && StringLength)
*StringLength = len;
return ret;
return PGAPI_GetStmtAttr(StatementHandle, Attribute, Value,
BufferLength, StringLength);
}
/* SQLSetConnectOption -> SQLSetConnectAttr */
@ -405,18 +313,8 @@ SQLSetConnectAttr(HDBC ConnectionHandle,
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
mylog("[[SQLSetConnectAttr]] %d\n", Attribute);
switch (Attribute)
{
case SQL_ATTR_ASYNC_ENABLE:
case SQL_ATTR_AUTO_IPD:
case SQL_ATTR_CONNECTION_DEAD:
case SQL_ATTR_CONNECTION_TIMEOUT:
case SQL_ATTR_METADATA_ID:
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
conn->errormsg = "Unsupported connection option (Set)";
return SQL_ERROR;
}
return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
return PGAPI_SetConnectAttr(ConnectionHandle, Attribute, Value,
StringLength);
}
/* new function */
@ -497,70 +395,7 @@ SQLSetStmtAttr(HSTMT StatementHandle,
StatementClass *stmt = (StatementClass *) StatementHandle;
mylog("[[%s]] Handle=%u %d,%u\n", func, StatementHandle, Attribute, Value);
switch (Attribute)
{
case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */
case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */
case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */
case SQL_ATTR_APP_ROW_DESC: /* 10010 */
case SQL_ATTR_APP_PARAM_DESC: /* 10011 */
case SQL_ATTR_AUTO_IPD: /* 10001 */
/* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */
case SQL_ATTR_IMP_ROW_DESC: /* 10012 (read-only) */
case SQL_ATTR_IMP_PARAM_DESC: /* 10013 (read-only) */
case SQL_ATTR_METADATA_ID: /* 10014 */
/*
* case SQL_ATTR_PREDICATE_PTR: case
* SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
*/
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "Unsupported statement option (Set)";
SC_log_error(func, "", stmt);
return SQL_ERROR;
case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */
stmt->options.bookmark_ptr = Value;
break;
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
stmt->options.param_offset_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
stmt->options.param_bind_type = (SQLUINTEGER) Value;
break;
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
stmt->options.param_operation_ptr = Value;
break;
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
stmt->options.param_status_ptr = (SQLUSMALLINT *) Value;
break;
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
stmt->options.param_processed_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
stmt->options.paramset_size = (SQLUINTEGER) Value;
break;
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
stmt->options.row_offset_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
stmt->options.row_operation_ptr = Value;
break;
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
stmt->options.rowStatusArray = (SQLUSMALLINT *) Value;
break;
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
stmt->options.rowsFetched = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
stmt->options.rowset_size = (SQLUINTEGER) Value;
break;
default:
return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value);
}
return SQL_SUCCESS;
return PGAPI_SetStmtAttr(StatementHandle, Attribute, Value, StringLength);
}
#define SQL_FUNC_ESET(pfExists, uwAPI) \
@ -630,8 +465,9 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
if (ci->drivers.lie)
SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implemented yet */
SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES); /* 57 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 */
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); 59 deprecated */
if (ci->drivers.lie)
SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 not properly implemented */
SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); /* 59 deprecated ? */
/*
* for (++i; i < SQL_API_SQLBINDPARAMETER; i++)
@ -678,8 +514,75 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR); /* 1019 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR); /* 1020 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL); /* 1021 */
if (ci->drivers.lie)
SQL_FUNC_ESET(pfExists, SQL_API_SQLBULKOPERATIONS); /* 24 not implemented yet */
if (ci->updatable_cursors)
SQL_FUNC_ESET(pfExists, SQL_API_SQLBULKOPERATIONS); /* 24 */
return SQL_SUCCESS;
}
RETCODE SQL_API
SQLBulkOperations(HSTMT hstmt, SQLSMALLINT operation)
{
static char *func = "SQLBulkOperations";
StatementClass *stmt = (StatementClass *) hstmt;
ARDFields *opts = SC_get_ARD(stmt);
RETCODE ret;
UInt4 offset, bind_size = opts->bind_size, *bmark;
int i, processed;
ConnectionClass *conn;
BOOL auto_commit_needed = FALSE;
mylog("[[%s]] operation = %d\n", func, operation);
offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
switch (operation)
{
case SQL_ADD:
ret = PGAPI_SetPos(hstmt, 0, operation, SQL_LOCK_NO_CHANGE);
break;
default:
if (SQL_FETCH_BY_BOOKMARK != operation)
{
conn = SC_get_conn(stmt);
if (auto_commit_needed = CC_is_in_autocommit(conn), auto_commit_needed)
PGAPI_SetConnectOption(conn, SQL_AUTOCOMMIT,
SQL_AUTOCOMMIT_OFF);
}
if (bmark = (UInt4 *) opts->bookmark->buffer, !bmark)
{
stmt->errormsg = "bookmark isn't specified";
return SQL_ERROR;
}
bmark += (offset >> 4);
for (i = 0, processed = 0; i < opts->rowset_size; i++)
{
if (!opts->row_operation_ptr || SQL_ROW_PROCEED == opts->row_operation_ptr[i])
{
switch (operation)
{
case SQL_UPDATE_BY_BOOKMARK:
ret = SC_pos_update(stmt, (UWORD) i, *bmark);
break;
case SQL_DELETE_BY_BOOKMARK:
ret = SC_pos_delete(stmt, (UWORD) i, *bmark);
break;
case SQL_FETCH_BY_BOOKMARK:
ret = SC_pos_refresh(stmt, (UWORD) i, *bmark);
break;
}
processed++;
if (SQL_ERROR == ret)
break;
if (bind_size > 0)
bmark += (bind_size >> 2);
else
bmark++;
}
}
if (auto_commit_needed)
PGAPI_SetConnectOption(conn, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
if (SC_get_IRD(stmt)->rowsFetched)
*SC_get_IRD(stmt)->rowsFetched = processed;
break;
}
return ret;
}

View File

@ -5,7 +5,7 @@
*
* Classes: n/a
*
* API functions: SQLColAttributeW, SQLGetStmtW, SQLSetStmtW,
* API functions: SQLColAttributeW, SQLGetStmtAttrW, SQLSetStmtAttrW,
SQLSetConnectAttrW, SQLGetConnectAttrW,
SQLGetDescFieldW, SQLGetDescRecW, SQLGetDiagFieldW,
SQLGetDiagRecW,
@ -75,6 +75,48 @@ RETCODE SQL_API SQLSetConnectAttrW(HDBC hdbc,
return ret;
}
/* new function */
RETCODE SQL_API
SQLSetDescFieldW(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber,
SQLSMALLINT FieldIdentifier, PTR Value,
SQLINTEGER BufferLength)
{
RETCODE ret;
UInt4 vallen;
char *uval = NULL;
BOOL val_alloced = FALSE;
mylog("[SQLSetDescFieldW]");
if (BufferLength > 0)
{
uval = ucs2_to_utf8(Value, BufferLength / 2, &vallen);
val_alloced = TRUE;
}
else
{
uval = Value;
vallen = BufferLength;
}
ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
uval, vallen);
if (val_alloced)
free(uval);
return ret;
}
RETCODE SQL_API
SQLGetDescFieldW(SQLHDESC hdesc, SQLSMALLINT iRecord, SQLSMALLINT iField,
PTR rgbValue, SQLINTEGER cbValueMax,
SQLINTEGER *pcbValue)
{
RETCODE ret;
char *qstr = NULL, *mtxt = NULL;
mylog("[SQLGetDescFieldW]");
ret = PGAPI_GetDescField(hdesc, iRecord, iField, rgbValue,
cbValueMax, pcbValue);
return ret;
}
RETCODE SQL_API SQLGetDiagRecW(SWORD fHandleType,
SQLHANDLE handle,
SQLSMALLINT iRecord,
@ -131,7 +173,25 @@ RETCODE SQL_API SQLColAttributeW(
RETCODE ret;
mylog("[SQLColAttributeW]");
switch (fDescType)
{
case SQL_DESC_BASE_COLUMN_NAME:
case SQL_DESC_BASE_TABLE_NAME:
case SQL_DESC_CATALOG_NAME:
case SQL_DESC_LABEL:
case SQL_DESC_LITERAL_PREFIX:
case SQL_DESC_LITERAL_SUFFIX:
case SQL_DESC_LOCAL_TYPE_NAME:
case SQL_DESC_NAME:
case SQL_DESC_SCHEMA_NAME:
case SQL_DESC_TABLE_NAME:
case SQL_DESC_TYPE_NAME:
case SQL_COLUMN_NAME:
break;
}
ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
cbDescMax, pcbDesc, pfDesc);
return ret;
}

View File

@ -53,9 +53,9 @@ set_statement_option(ConnectionClass *conn,
case SQL_BIND_TYPE:
/* now support multi-column and multi-row binding */
if (conn)
conn->stmtOptions.bind_size = vParam;
conn->ardOptions.bind_size = vParam;
if (stmt)
stmt->options.bind_size = vParam;
SC_get_ARD(stmt)->bind_size = vParam;
break;
case SQL_CONCURRENCY:
@ -173,7 +173,7 @@ set_statement_option(ConnectionClass *conn,
*/
if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0)
stmt->save_rowset_size = stmt->options.rowset_size;
stmt->save_rowset_size = SC_get_ARD(stmt)->rowset_size;
if (vParam < 1)
{
@ -182,9 +182,9 @@ set_statement_option(ConnectionClass *conn,
}
if (conn)
conn->stmtOptions.rowset_size = vParam;
conn->ardOptions.rowset_size = vParam;
if (stmt)
stmt->options.rowset_size = vParam;
SC_get_ARD(stmt)->rowset_size = vParam;
break;
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
@ -590,16 +590,16 @@ PGAPI_GetStmtOption(
break;
case SQL_BIND_TYPE:
*((SDWORD *) pvParam) = stmt->options.bind_size;
*((SDWORD *) pvParam) = SC_get_ARD(stmt)->bind_size;
break;
case SQL_CONCURRENCY: /* NOT REALLY SUPPORTED */
mylog("GetStmtOption(): SQL_CONCURRENCY\n");
mylog("GetStmtOption(): SQL_CONCURRENCY %d\n", stmt->options.scroll_concurrency);
*((SDWORD *) pvParam) = stmt->options.scroll_concurrency;
break;
case SQL_CURSOR_TYPE: /* PARTIAL SUPPORT */
mylog("GetStmtOption(): SQL_CURSOR_TYPE\n");
mylog("GetStmtOption(): SQL_CURSOR_TYPE %d\n", stmt->options.cursor_type);
*((SDWORD *) pvParam) = stmt->options.cursor_type;
break;
@ -630,7 +630,7 @@ PGAPI_GetStmtOption(
break;
case SQL_ROWSET_SIZE:
*((SDWORD *) pvParam) = stmt->options.rowset_size;
*((SDWORD *) pvParam) = SC_get_ARD(stmt)->rowset_size;
break;
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */

View File

@ -236,19 +236,25 @@ void
getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
{
char *str;
Int2 reserved_cols;
#if (ODBCVER >= 0x0300)
reserved_cols = 18;
#else
reserved_cols = 12;
#endif /* ODBCVER */
if (fi->name[0] == '\0')
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->precision = atoi(QR_get_value_manual(col_info->result, k, 6));
fi->type = atoi(QR_get_value_manual(col_info->result, k, (Int2)(reserved_cols + 1)));
fi->column_size = atoi(QR_get_value_manual(col_info->result, k, 6));
fi->length = atoi(QR_get_value_manual(col_info->result, k, 7));
if (str = QR_get_value_manual(col_info->result, k, 8), str)
fi->scale = atoi(str);
fi->decimal_digits = atoi(str);
else
fi->scale = -1;
fi->decimal_digits = -1;
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, reserved_cols));
}
@ -315,16 +321,17 @@ parse_statement(StatementClass *stmt)
ConnectionClass *conn = stmt->hdbc;
HSTMT hcol_stmt;
StatementClass *col_stmt;
IRDFields *irdflds = SC_get_IRD(stmt);
RETCODE result;
BOOL updatable = TRUE;
mylog("%s: entering...\n", func);
ptr = stmt->statement;
fi = stmt->fi;
fi = irdflds->fi;
ti = stmt->ti;
stmt->nfld = 0;
irdflds->nfields = 0;
stmt->ntab = 0;
stmt->from_pos = -1;
stmt->where_pos = -1;
@ -371,7 +378,7 @@ parse_statement(StatementClass *stmt)
mylog("FROM\n");
continue;
}
}
} /* in_select && unquoted && blevel == 0 */
if (unquoted && blevel == 0)
{
if ((!stricmp(token, "where") ||
@ -386,18 +393,18 @@ parse_statement(StatementClass *stmt)
in_from = FALSE;
in_where = TRUE;
if (!stricmp(token, "where"))
if (stmt->where_pos < 0)
stmt->where_pos = pptr - stmt->statement;
mylog("%s...\n", token);
if (stricmp(token, "where") &&
stricmp(token, "order"))
{
if (stmt->where_pos < 0)
stmt->where_pos = pptr - stmt->statement;
}
else if (stricmp(token, "order"))
updatable = FALSE;
mylog("WHERE...\n");
break;
break;
}
continue;
}
}
} /* unquoted && blevel == 0 */
if (in_select && (in_expr || in_func))
{
/* just eat the expression */
@ -435,7 +442,7 @@ parse_statement(StatementClass *stmt)
}
}
continue;
}
} /* in_select && (in_expr || in_func) */
if (unquoted && !stricmp(token, "select"))
{
@ -464,81 +471,81 @@ parse_statement(StatementClass *stmt)
}
mylog("done distinct\n");
in_distinct = FALSE;
}
} /* in_distinct */
if (!in_field)
{
if (!token[0])
continue;
if (!(stmt->nfld % FLD_INCR))
if (!(irdflds->nfields % FLD_INCR))
{
mylog("reallocing at nfld=%d\n", stmt->nfld);
fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *));
mylog("reallocing at nfld=%d\n", irdflds->nfields);
fi = (FIELD_INFO **) realloc(fi, (irdflds->nfields + FLD_INCR) * sizeof(FIELD_INFO *));
if (!fi)
{
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
stmt->fi = fi;
irdflds->fi = fi;
}
fi[stmt->nfld] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO));
if (fi[stmt->nfld] == NULL)
fi[irdflds->nfields] = (FIELD_INFO *) malloc(sizeof(FIELD_INFO));
if (fi[irdflds->nfields] == NULL)
{
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
/* Initialize the field info */
memset(fi[stmt->nfld], 0, sizeof(FIELD_INFO));
memset(fi[irdflds->nfields], 0, sizeof(FIELD_INFO));
/* double quotes are for qualifiers */
if (dquote)
fi[stmt->nfld]->dquote = TRUE;
fi[irdflds->nfields]->dquote = TRUE;
if (quote)
{
fi[stmt->nfld]->quote = TRUE;
fi[stmt->nfld]->precision = strlen(token);
fi[irdflds->nfields]->quote = TRUE;
fi[irdflds->nfields]->column_size = strlen(token);
}
else if (numeric)
{
mylog("**** got numeric: nfld = %d\n", stmt->nfld);
fi[stmt->nfld]->numeric = TRUE;
mylog("**** got numeric: nfld = %d\n", irdflds->nfields);
fi[irdflds->nfields]->numeric = TRUE;
}
else if (token[0] == '(')
{ /* expression */
mylog("got EXPRESSION\n");
fi[stmt->nfld++]->expr = TRUE;
fi[irdflds->nfields++]->expr = TRUE;
in_expr = TRUE;
blevel = 1;
continue;
}
else
{
strcpy(fi[stmt->nfld]->name, token);
fi[stmt->nfld]->dot[0] = '\0';
strcpy(fi[irdflds->nfields]->name, token);
fi[irdflds->nfields]->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[irdflds->nfields]->name, fi[irdflds->nfields]->dot);
if (delim == ',')
mylog("comma (1)\n");
else
in_field = TRUE;
stmt->nfld++;
irdflds->nfields++;
continue;
}
} /* !in_field */
/*
* We are in a field now
*/
if (in_dot)
{
stmt->nfld--;
strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name);
strcpy(fi[stmt->nfld]->name, token);
stmt->nfld++;
irdflds->nfields--;
strcpy(fi[irdflds->nfields]->dot, fi[irdflds->nfields]->name);
strcpy(fi[irdflds->nfields]->name, token);
irdflds->nfields++;
in_dot = FALSE;
if (delim == ',')
@ -551,13 +558,13 @@ parse_statement(StatementClass *stmt)
if (in_as)
{
stmt->nfld--;
strcpy(fi[stmt->nfld]->alias, token);
mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias);
irdflds->nfields--;
strcpy(fi[irdflds->nfields]->alias, token);
mylog("alias for field '%s' is '%s'\n", fi[irdflds->nfields]->name, fi[irdflds->nfields]->alias);
in_as = FALSE;
in_field = FALSE;
stmt->nfld++;
irdflds->nfields++;
if (delim == ',')
mylog("comma(2)\n");
@ -569,13 +576,13 @@ parse_statement(StatementClass *stmt)
{
in_func = TRUE;
blevel = 1;
fi[stmt->nfld - 1]->func = TRUE;
fi[irdflds->nfields - 1]->func = TRUE;
/*
* name will have the function name -- maybe useful some
* day
*/
mylog("**** got function = '%s'\n", fi[stmt->nfld - 1]->name);
mylog("**** got function = '%s'\n", fi[irdflds->nfields - 1]->name);
continue;
}
@ -595,11 +602,11 @@ parse_statement(StatementClass *stmt)
/* otherwise, it's probably an expression */
in_expr = TRUE;
fi[stmt->nfld - 1]->expr = TRUE;
fi[stmt->nfld - 1]->name[0] = '\0';
fi[stmt->nfld - 1]->precision = 0;
fi[irdflds->nfields - 1]->expr = TRUE;
fi[irdflds->nfields - 1]->name[0] = '\0';
fi[irdflds->nfields - 1]->column_size = 0;
mylog("*** setting expression\n");
}
} /* in_select end */
if (in_from)
{
@ -607,6 +614,8 @@ parse_statement(StatementClass *stmt)
{
if (!token[0])
continue;
if (token[0] == ';')
break;
if (!(stmt->ntab % TAB_INCR))
{
@ -658,12 +667,17 @@ parse_statement(StatementClass *stmt)
continue;
}
strcpy(ti[stmt->ntab - 1]->alias, token);
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias);
in_table = FALSE;
if (delim == ',')
mylog("more than 1 tables\n");
}
if (token[0] == ';')
break;
if (stricmp(token, "as"))
{
strcpy(ti[stmt->ntab - 1]->alias, token);
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias);
in_table = FALSE;
if (delim == ',')
mylog("more than 1 tables\n");
}
} /* in_from */
}
/*
@ -673,7 +687,7 @@ parse_statement(StatementClass *stmt)
parse = TRUE;
/* Resolve field names with tables */
for (i = 0; i < stmt->nfld; i++)
for (i = 0; i < (int) irdflds->nfields; i++)
{
if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
{
@ -687,16 +701,16 @@ parse_statement(StatementClass *stmt)
fi[i]->ti = NULL;
/*
* fi[i]->type = PG_TYPE_TEXT; fi[i]->precision = 0; the
* fi[i]->type = PG_TYPE_TEXT; fi[i]->column_size = 0; the
* following may be better
*/
fi[i]->type = PG_TYPE_UNKNOWN;
if (fi[i]->precision == 0)
if (fi[i]->column_size == 0)
{
fi[i]->type = PG_TYPE_VARCHAR;
fi[i]->precision = 254;
fi[i]->column_size = 254;
}
fi[i]->length = fi[i]->precision;
fi[i]->length = fi[i]->column_size;
continue;
}
/* it's a dot, resolve to table or alias */
@ -721,9 +735,9 @@ parse_statement(StatementClass *stmt)
}
mylog("--------------------------------------------\n");
mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab);
mylog("nfld=%d, ntab=%d\n", irdflds->nfields, stmt->ntab);
for (i = 0; i < stmt->nfld; i++)
for (i = 0; i < (int) irdflds->nfields; i++)
{
mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot);
if (fi[i]->ti)
@ -836,7 +850,7 @@ parse_statement(StatementClass *stmt)
/*
* Now resolve the fields to point to column info
*/
for (i = 0; i < stmt->nfld;)
for (i = 0; i < (int) irdflds->nfields;)
{
fi[i]->updatable = updatable;
/* Dont worry about functions or quotes */
@ -875,8 +889,8 @@ parse_statement(StatementClass *stmt)
increased_cols = total_cols - 1;
/* Allocate some more field pointers if necessary */
old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR;
new_size = stmt->nfld + increased_cols;
old_alloc = ((irdflds->nfields - 1) / FLD_INCR + 1) * FLD_INCR;
new_size = irdflds->nfields + increased_cols;
mylog("k=%d, increased_cols=%d, old_alloc=%d, new_size=%d\n", k, increased_cols, old_alloc, new_size);
@ -891,14 +905,14 @@ parse_statement(StatementClass *stmt)
stmt->parse_status = STMT_PARSE_FATAL;
return FALSE;
}
stmt->fi = fi;
irdflds->fi = fi;
}
/*
* copy any other fields (if there are any) up past the
* expansion
*/
for (j = stmt->nfld - 1; j > i; j--)
for (j = irdflds->nfields - 1; j > i; j--)
{
mylog("copying field %d to %d\n", j, increased_cols + j);
fi[increased_cols + j] = fi[j];
@ -906,8 +920,8 @@ parse_statement(StatementClass *stmt)
mylog("done copying fields\n");
/* Set the new number of fields */
stmt->nfld += increased_cols;
mylog("stmt->nfld now at %d\n", stmt->nfld);
irdflds->nfields += increased_cols;
mylog("irdflds->nfields now at %d\n", irdflds->nfields);
/* copy the new field info */
@ -990,6 +1004,7 @@ parse_statement(StatementClass *stmt)
else
stmt->parse_status = STMT_PARSE_COMPLETE;
stmt->updatable = updatable;
mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
return parse;
}

File diff suppressed because it is too large Load Diff

View File

@ -280,5 +280,8 @@ RETCODE SQL_API PGAPI_SetStmtAttr(HSTMT StatementHandle,
RETCODE SQL_API PGAPI_SetDescField(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
PTR Value, SQLINTEGER BufferLength);
RETCODE SQL_API PGAPI_GetDescField(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
PTR Value, SQLINTEGER BufferLength, SQLINTEGER *StringLength);
#endif /* ODBCVER */
#endif /* define_PG_API_FUNC_H__ */

View File

@ -26,7 +26,7 @@
Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int4 getCharColumnSize(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
/*
* these are the types we support. all of the pgtype_ functions should
@ -230,13 +230,13 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
* types that are unknown. All other pg routines in here return a suitable default.
*/
Int2
pgtype_to_sqltype(StatementClass *stmt, Int4 type)
pgtype_to_concise_type(StatementClass *stmt, Int4 type)
{
ConnectionClass *conn = SC_get_conn(stmt);
ConnInfo *ci = &(conn->connInfo);
#if (ODBCVER >= 0x0300)
EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
#endif
#endif /* ODBCVER */
switch (type)
{
@ -289,7 +289,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
if (!conn->ms_jet)
return SQL_BIGINT;
#endif /* ODBCVER */
return SQL_CHAR;
return SQL_VARCHAR;
case PG_TYPE_NUMERIC:
return SQL_NUMERIC;
@ -338,6 +338,40 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_to_sqldesctype(StatementClass *stmt, Int4 type)
{
Int2 rettype;
switch (rettype = pgtype_to_concise_type(stmt, type))
{
#if (ODBCVER >= 0x0300)
case SQL_TYPE_DATE:
case SQL_TYPE_TIME:
case SQL_TYPE_TIMESTAMP:
return SQL_DATETIME;
#endif /* ODBCVER */
}
return rettype;
}
Int2
pgtype_to_datetime_sub(StatementClass *stmt, Int4 type)
{
switch (pgtype_to_concise_type(stmt, type))
{
#if (ODBCVER >= 0x0300)
case SQL_TYPE_DATE:
return SQL_CODE_DATE;
case SQL_TYPE_TIME:
return SQL_CODE_TIME;
case SQL_TYPE_TIMESTAMP:
return SQL_CODE_TIMESTAMP;
#endif /* ODBCVER */
}
return -1;
}
Int2
pgtype_to_ctype(StatementClass *stmt, Int4 type)
@ -346,7 +380,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
ConnInfo *ci = &(conn->connInfo);
#if (ODBCVER >= 0x0300)
EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
#endif
#endif /* ODBCVER */
switch (type)
{
@ -484,13 +518,13 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
static Int2
getNumericScale(StatementClass *stmt, Int4 type, int col)
getNumericDecimalDigits(StatementClass *stmt, Int4 type, int col)
{
Int4 atttypmod = -1;
QResultClass *result;
ColumnInfoClass *flds;
mylog("getNumericScale: type=%d, col=%d\n", type, col);
mylog("getNumericDecimalDigits: type=%d, col=%d\n", type, col);
if (col < 0)
return PG_NUMERIC_MAX_SCALE;
@ -525,13 +559,13 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
static Int4
getNumericPrecision(StatementClass *stmt, Int4 type, int col)
getNumericColumnSize(StatementClass *stmt, Int4 type, int col)
{
Int4 atttypmod = -1;
QResultClass *result;
ColumnInfoClass *flds;
mylog("getNumericPrecision: type=%d, col=%d\n", type, col);
mylog("getNumericColumnSize: type=%d, col=%d\n", type, col);
if (col < 0)
return PG_NUMERIC_MAX_PRECISION;
@ -566,15 +600,15 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
Int4
getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
getCharColumnSize(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
int p = -1,
int p = -1, attlen = -1,
maxsize;
QResultClass *result;
ColumnInfoClass *flds;
ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as);
mylog("getCharColumnSize: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as);
/* Assign Maximum size based on parameters */
switch (type)
@ -607,7 +641,7 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
maxsize = TEXT_FIELD_SIZE;
}
/*
* Static Precision (i.e., the Maximum Precision of the datatype) This
* Static ColumnSize (i.e., the Maximum ColumnSize of the datatype) This
* has nothing to do with a result set.
*/
if (col < 0)
@ -628,35 +662,37 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
return maxsize;
}
p = QR_get_display_size(result, col); /* longest */
attlen = QR_get_atttypmod(result, col);
/* Size is unknown -- handle according to parameter */
if (QR_get_atttypmod(result, col) > -1)
return QR_get_atttypmod(result, col);
if (attlen > p) /* maybe the length is known */
return attlen;
/* The type is really unknown */
if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
{
p = QR_get_display_size(result, col);
mylog("getCharPrecision: LONGEST: p = %d\n", p);
mylog("getCharColumnSize: LONGEST: p = %d\n", p);
if (p >= 0)
return p;
}
if (p > maxsize)
maxsize = p;
if (handle_unknown_size_as == UNKNOWNS_AS_MAX)
return maxsize;
else /* handle_unknown_size_as == DONT_KNOW */
return -1;
}
static Int2
getTimestampScale(StatementClass *stmt, Int4 type, int col)
getTimestampDecimalDigits(StatementClass *stmt, Int4 type, int col)
{
ConnectionClass *conn = SC_get_conn(stmt);
Int4 atttypmod;
QResultClass *result;
ColumnInfoClass *flds;
mylog("getTimestampScale: type=%d, col=%d\n", type, col);
mylog("getTimestampDecimalDigits: type=%d, col=%d\n", type, col);
if (col < 0)
return 0;
@ -685,12 +721,12 @@ getTimestampScale(StatementClass *stmt, Int4 type, int col)
static Int4
getTimestampPrecision(StatementClass *stmt, Int4 type, int col)
getTimestampColumnSize(StatementClass *stmt, Int4 type, int col)
{
Int4 fixed,
scale;
mylog("getTimestampPrecision: type=%d, col=%d\n", type, col);
mylog("getTimestampColumnSize: type=%d, col=%d\n", type, col);
switch (type)
{
@ -710,11 +746,13 @@ getTimestampPrecision(StatementClass *stmt, Int4 type, int col)
fixed = 19;
break;
}
scale = getTimestampScale(stmt, type, col);
scale = getTimestampDecimalDigits(stmt, type, col);
return (scale > 0) ? fixed + 1 + scale : fixed;
}
/*
* This corresponds to "precision" in ODBC 2.x.
*
* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
* override this length with the atttypmod length from pg_attribute .
*
@ -722,7 +760,7 @@ getTimestampPrecision(StatementClass *stmt, Int4 type, int col)
* This is used for functions SQLDescribeCol and SQLColAttributes.
*/
Int4
pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
pgtype_column_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
@ -750,7 +788,7 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
return 19; /* signed */
case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col);
return getNumericColumnSize(stmt, type, col);
case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY:
@ -769,7 +807,7 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
return 22;
case PG_TYPE_DATETIME:
/* return 22; */
return getTimestampPrecision(stmt, type, col);
return getTimestampColumnSize(stmt, type, col);
case PG_TYPE_BOOL:
{
@ -787,10 +825,26 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
return SQL_NO_TOTAL;
/* Handle Character types and unknown types */
return getCharPrecision(stmt, type, col, handle_unknown_size_as);
return getCharColumnSize(stmt, type, col, handle_unknown_size_as);
}
}
/*
* "precision in ODBC 3.x.
*/
Int4
pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_NUMERIC:
return getNumericColumnSize(stmt, type, col);
case PG_TYPE_DATETIME:
return getTimestampDecimalDigits(stmt, type, col);
}
return -1;
}
Int4
pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
@ -813,7 +867,7 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
return 20; /* signed: 19 digits + sign */
case PG_TYPE_NUMERIC:
dsize = getNumericPrecision(stmt, type, col);
dsize = getNumericColumnSize(stmt, type, col);
return dsize < 0 ? dsize : dsize + 2;
case PG_TYPE_MONEY:
@ -827,20 +881,88 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
/* Character types use regular precision */
default:
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
}
}
/*
* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
* override this length with the atttypmod length from pg_attribute
* The length in bytes of data transferred on an SQLGetData, SQLFetch,
* or SQLFetchScroll operation if SQL_C_DEFAULT is specified.
*/
Int4
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
pgtype_buffer_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
ConnectionClass *conn = SC_get_conn(stmt);
switch (type)
{
case PG_TYPE_INT2:
return 2; /* sizeof(SQLSMALLINT) */
case PG_TYPE_OID:
case PG_TYPE_XID:
case PG_TYPE_INT4:
return 4; /* sizeof(SQLINTEGER) */
case PG_TYPE_INT8:
if (SQL_C_CHAR == pgtype_to_ctype(stmt, type))
return 20; /* signed: 19 digits + sign */
return 8; /* sizeof(SQLSBININT) */
case PG_TYPE_NUMERIC:
return getNumericColumnSize(stmt, type, col) + 2;
case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY:
return 4; /* sizeof(SQLREAL) */
case PG_TYPE_FLOAT8:
return 8; /* sizeof(SQLFLOAT) */
case PG_TYPE_DATE:
case PG_TYPE_TIME:
return 6; /* sizeof(DATE(TIME)_STRUCT) */
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return 16; /* sizeof(TIMESTAMP_STRUCT) */
/* Character types use the default precision */
case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR:
{
int coef = 1;
Int4 prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc;
if (conn->unicode)
return prec * 2;
#ifdef MULTIBYTE
/* after 7.2 */
if (PG_VERSION_GE(conn, 7.2))
coef = 3;
else
#endif /* MULTIBYTE */
if ((conn->connInfo).lf_conversion)
/* CR -> CR/LF */
coef = 2;
if (coef == 1)
return prec;
maxvarc = conn->connInfo.drivers.max_varchar_size;
if (prec <= maxvarc && prec * coef > maxvarc)
return maxvarc;
return coef * prec;
}
default:
return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
}
}
/*
*/
Int4
pgtype_desclength(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
switch (type)
{
case PG_TYPE_INT2:
@ -855,7 +977,7 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
return 20; /* signed: 19 digits + sign */
case PG_TYPE_NUMERIC:
return getNumericPrecision(stmt, type, col) + 2;
return getNumericColumnSize(stmt, type, col) + 2;
case PG_TYPE_FLOAT4:
case PG_TYPE_MONEY:
@ -866,21 +988,33 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
case PG_TYPE_DATE:
case PG_TYPE_TIME:
return 6; /* sizeof(DATE(TIME)_STRUCT) */
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
return 16; /* sizeof(TIMESTAMP_STRUCT) */
/* Character types (and NUMERIC) use the default precision */
case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR:
{
int coef = 1;
Int4 prec = pgtype_precision(stmt, type, col, handle_unknown_size_as), maxvarc;
return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
default:
return pgtype_column_size(stmt, type, col, handle_unknown_size_as);
}
}
/*
* Transfer octet length.
*/
Int4
pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
ConnectionClass *conn = SC_get_conn(stmt);
int coef = 1;
Int4 prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc;
switch (type)
{
case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR:
if (conn->unicode)
return (prec + 1) * 2;
return prec * 2;
#ifdef MULTIBYTE
/* after 7.2 */
if (PG_VERSION_GE(conn, 7.2))
@ -891,20 +1025,22 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
/* CR -> CR/LF */
coef = 2;
if (coef == 1)
return prec + 1;
return prec;
maxvarc = conn->connInfo.drivers.max_varchar_size;
if (prec <= maxvarc && prec * coef > maxvarc)
return maxvarc;
return coef * prec;
}
default:
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
case PG_TYPE_BYTEA:
return prec;
}
return -1;
}
/*
* corrsponds to "scale" in ODBC 2.x.
*/
Int2
pgtype_scale(StatementClass *stmt, Int4 type, int col)
pgtype_decimal_digits(StatementClass *stmt, Int4 type, int col)
{
switch (type)
{
@ -927,16 +1063,30 @@ pgtype_scale(StatementClass *stmt, Int4 type, int col)
return 0;
case PG_TYPE_DATETIME:
/* return 0; */
return getTimestampScale(stmt, type, col);
return getTimestampDecimalDigits(stmt, type, col);
case PG_TYPE_NUMERIC:
return getNumericScale(stmt, type, col);
return getNumericDecimalDigits(stmt, type, col);
default:
return -1;
}
}
/*
* "scale" in ODBC 3.x.
*/
Int2
pgtype_scale(StatementClass *stmt, Int4 type, int col)
{
switch (type)
{
case PG_TYPE_NUMERIC:
return getNumericDecimalDigits(stmt, type, col);
}
return -1;
}
Int2
pgtype_radix(StatementClass *stmt, Int4 type)

View File

@ -72,16 +72,22 @@ extern Int2 sqlTypes[];
Int4 sqltype_to_pgtype(StatementClass *stmt, Int2 fSqlType);
Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type);
Int2 pgtype_to_concise_type(StatementClass *stmt, Int4 type);
Int2 pgtype_to_sqldesctype(StatementClass *stmt, Int4 type);
Int2 pgtype_to_datetime_sub(StatementClass *stmt, Int4 type);
Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type);
char *pgtype_to_name(StatementClass *stmt, Int4 type);
/* 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_column_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); /* corresponds to "precision" in ODBC 2.x */
Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); /* "precsion in ODBC 3.x */
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_buffer_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int4 pgtype_desclength(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int4 pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col);
Int2 pgtype_decimal_digits(StatementClass *stmt, Int4 type, int col); /* corresponds to "scale" in ODBC 2.x */
Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col); /* ODBC 3.x " */
Int2 pgtype_radix(StatementClass *stmt, Int4 type);
Int2 pgtype_nullable(StatementClass *stmt, Int4 type);
Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type);

View File

@ -5,7 +5,7 @@
*
* Comments: See "notice.txt" for copyright and license information.
*
* $Id: psqlodbc.h,v 1.60 2002/03/14 05:42:03 inoue Exp $
* $Id: psqlodbc.h,v 1.61 2002/03/28 08:08:06 inoue Exp $
*
*/
@ -91,7 +91,11 @@ typedef UInt4 Oid;
#ifdef WIN32
#if (ODBCVER >= 0x0300)
#ifdef UNICODE_SUPPORT
#define DRIVER_FILE_NAME "PSQLODBC30W.DLL"
#else
#define DRIVER_FILE_NAME "PSQLODBC30.DLL"
#endif /* UNICODE_SUPPORT */
#else
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
#endif /* ODBCVER */
@ -167,6 +171,11 @@ typedef struct EnvironmentClass_ EnvironmentClass;
typedef struct TupleNode_ TupleNode;
typedef struct TupleField_ TupleField;
typedef struct KeySet_ KeySet;
typedef struct Rollback_ Rollback;
typedef struct ARDFields_ ARDFields;
typedef struct APDFields_ APDFields;
typedef struct IRDFields_ IRDFields;
typedef struct IPDFields_ IPDFields;
typedef struct col_info COL_INFO;
typedef struct lo_arg LO_ARG;
@ -201,25 +210,12 @@ typedef struct StatementOptions_
{
int maxRows;
int maxLength;
int rowset_size;
int keyset_size;
int cursor_type;
int scroll_concurrency;
int retrieve_data;
int bind_size; /* size of each structure if using Row
* Binding */
int use_bookmarks;
UInt4 *rowsFetched;
UInt2 *rowStatusArray;
void *bookmark_ptr;
UInt2 *row_operation_ptr;
UInt4 *row_offset_ptr;
UInt4 paramset_size;
UInt4 param_bind_type;
UInt4 *param_processed_ptr;
UInt2 *param_status_ptr;
UInt2 *param_operation_ptr;
UInt4 *param_offset_ptr;
void *bookmark_ptr;
} StatementOptions;
/* Used to pass extra query info to send_query */
@ -260,6 +256,7 @@ UInt4 ucs2strlen(const SQLWCHAR *ucs2str);
char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen);
UInt4 utf8_to_ucs2(const char * utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 buflen);
#endif /* UNICODE_SUPPORT */
/*#define _MEMORY_DEBUG_ */
#ifdef _MEMORY_DEBUG_
void *debug_alloc(size_t);
void *debug_realloc(void *, size_t);

View File

@ -138,7 +138,7 @@ BEGIN
BS_NOTIFY | WS_TABSTOP,247,205,40,10
END
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 176
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 196
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Advanced Options (DataSource)"
FONT 10, "Terminal"
@ -155,23 +155,25 @@ BEGIN
BS_AUTOCHECKBOX | WS_TABSTOP,45,43,92,10
CONTROL "True is -1",DS_TRUEISMINUS1,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,149,43,86,10
GROUPBOX "Protocol",IDC_STATIC,43,59,180,25
CONTROL "(Trial) Updatable cursors",DS_UPDATABLECURSORS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,45,58,112,10
GROUPBOX "Protocol",IDC_STATIC,43,74,180,25
CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON |
WS_GROUP,53,69,47,10
WS_GROUP,53,84,47,10
CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
131,69,26,10
131,84,26,10
CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
187,69,26,10
GROUPBOX "OID Options",IDC_STATIC,43,89,180,25
187,84,26,10
GROUPBOX "OID Options",IDC_STATIC,43,104,180,25
CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,53,100,59,10
WS_GROUP | WS_TABSTOP,53,115,59,10
CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,161,100,55,10
LTEXT "Connect &Settings:",IDC_STATIC,10,120,35,25
EDITTEXT DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE |
WS_GROUP | WS_TABSTOP,161,115,55,10
LTEXT "Connect &Settings:",IDC_STATIC,10,135,35,25
EDITTEXT DS_CONNSETTINGS,50,135,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
DEFPUSHBUTTON "OK",IDOK,71,150,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,150,50,14
DEFPUSHBUTTON "OK",IDOK,71,165,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,165,50,14
END
#else
DLG_CONFIG DIALOG DISCARDABLE 65, 43, 292, 116
@ -259,7 +261,7 @@ BEGIN
BS_NOTIFY | WS_TABSTOP,233,224,40,10
END
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 176
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 186
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Advanced Options (DataSource)"
FONT 8, "MS Sans Serif"
@ -273,26 +275,28 @@ BEGIN
CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,130,25,85,10
CONTROL "LF <-> CR/LF convert",DS_LFCONVERSION,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,45,40,92,10
BS_AUTOCHECKBOX | WS_TABSTOP,25,40,92,10
CONTROL "True is -1",DS_TRUEISMINUS1,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,149,40,86,10
GROUPBOX "Protocol",IDC_STATIC,15,55,180,25
BS_AUTOCHECKBOX | WS_TABSTOP,130,40,86,10
CONTROL "(Trial) Updatable Cursors",DS_UPDATABLECURSORS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,25,55,102,10
GROUPBOX "Protocol",IDC_STATIC,15,70,180,25
CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | WS_GROUP,25,
65,35,10
80,35,10
CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
75,65,26,10
75,80,26,10
CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
130,65,26,10
GROUPBOX "OID Options",IDC_STATIC,15,86,180,25
130,80,26,10
GROUPBOX "OID Options",IDC_STATIC,15,101,180,25
CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,25,96,59,10
WS_GROUP | WS_TABSTOP,25,111,59,10
CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,115,96,51,10
RTEXT "Connect &Settings:",IDC_STATIC,10,120,35,25
EDITTEXT DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE |
WS_GROUP | WS_TABSTOP,115,111,51,10
RTEXT "Connect &Settings:",IDC_STATIC,10,135,35,25
EDITTEXT DS_CONNSETTINGS,50,135,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
DEFPUSHBUTTON "OK",IDOK,71,150,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,150,50,14
DEFPUSHBUTTON "OK",IDOK,71,165,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,165,50,14
END
#endif

View File

@ -0,0 +1,16 @@
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI]
[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers]
"PostgreSQL30W"="Installed"
[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL30W]
"APILevel"="1"
"ConnectFunctions"="YYN"
"Driver"="PSQLODBC30W.DLL"
"DriverODBCVer"="03.00"
"FileUsage"="0"
"Setup"="PSQLODBC30W.DLL"
"SQLLevel"="1"
"UsageCount"=dword:00000001

View File

@ -74,9 +74,9 @@ SQLSetDescField @96
SQLSetDescRec @97
SQLSetEnvAttr @98
SQLSetStmtAttr @99
SQLBulkOperations @100
SQLDummyOrdinal @199
dconn_FDriverConnectProc @200
DllMain @201
ConfigDSN @202

View File

@ -1,4 +1,4 @@
LIBRARY psqlodbc30
LIBRARY psqlodbc30w
EXPORTS
SQLAllocConnect @1
SQLAllocEnv @2
@ -71,6 +71,7 @@ SQLSetDescField @96
SQLSetDescRec @97
SQLSetEnvAttr @98
SQLSetStmtAttr @99
SQLBulkOperations @100
SQLDummyOrdinal @199
dconn_FDriverConnectProc @200

View File

@ -123,6 +123,8 @@ QR_Constructor()
rv->rowset_size = 1;
rv->haskeyset = 0;
rv->keyset = NULL;
rv->rb_count = 0;
rv->rollback = NULL;
}
mylog("exit QR_Constructor\n");
@ -228,6 +230,12 @@ QR_free_memory(QResultClass *self)
free(self->keyset);
self->keyset = NULL;
}
if (self->rollback)
{
free(self->rollback);
self->rb_count = 0;
self->rollback = NULL;
}
self->fcount = 0;
@ -280,6 +288,8 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
{
self->status = PGRES_FIELDS_OK;
self->num_fields = CI_get_num_fields(self->fields);
if (self->haskeyset)
self->num_fields -= 2;
}
else
{
@ -302,15 +312,18 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
/* allocate memory for the tuple cache */
mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
self->count_allocated = 0;
self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
if (self->num_fields > 0)
{
self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Could not get memory for tuple cache.");
return FALSE;
}
}
if (self->haskeyset)
self->keyset = (KeySet *) calloc(sizeof(KeySet), tuple_size);
if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Could not get memory for tuple cache.");
return FALSE;
}
self->count_allocated = tuple_size;
self->inTuples = TRUE;
@ -415,6 +428,7 @@ QR_next_tuple(QResultClass *self)
char fetch[128];
QueryInfo qi;
ConnInfo *ci = NULL;
BOOL set_no_trans;
if (fetch_count < fcount)
{
@ -484,12 +498,16 @@ QR_next_tuple(QResultClass *self)
if (!self->backend_tuples || self->cache_size > self->count_allocated)
{
self->count_allocated = 0;
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
if (!self->backend_tuples)
if (self->num_fields > 0)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples.");
return FALSE;
self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
self->num_fields * sizeof(TupleField) * self->cache_size);
if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples.");
return FALSE;
}
}
if (self->haskeyset)
self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * self->cache_size);
@ -555,13 +573,16 @@ QR_next_tuple(QResultClass *self)
mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
tuple_size *= 2;
self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
tuple_size * self->num_fields * sizeof(TupleField));
if (!self->backend_tuples)
if (self->num_fields > 0)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples.");
return FALSE;
self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
tuple_size * self->num_fields * sizeof(TupleField));
if (!self->backend_tuples)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Out of memory while reading tuples.");
return FALSE;
}
}
if (self->haskeyset)
self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * tuple_size);
@ -606,8 +627,10 @@ QR_next_tuple(QResultClass *self)
QR_set_message(self, msgbuffer);
self->status = PGRES_FATAL_ERROR;
set_no_trans = FALSE;
if (!strncmp(msgbuffer, "FATAL", 5))
CC_set_no_trans(self->conn);
set_no_trans = TRUE;
CC_on_abort(self->conn, set_no_trans);
qlog("ERROR from backend in next_tuple: '%s'\n", msgbuffer);
@ -626,7 +649,7 @@ QR_next_tuple(QResultClass *self)
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");
self->status = PGRES_FATAL_ERROR;
CC_set_no_trans(self->conn);
CC_on_abort(self->conn, TRUE);
return FALSE;
}
}
@ -647,16 +670,21 @@ QR_read_tuple(QResultClass *self, char binary)
Int2 bitcnt;
Int4 len;
char *buffer;
int num_fields = self->num_fields; /* speed up access */
int ci_num_fields = QR_NumResultCols(self); /* speed up access */
int num_fields = self->num_fields; /* speed up access */
SocketClass *sock = CC_get_socket(self->conn);
ColumnInfoClass *flds;
int effective_cols;
char tidoidbuf[32];
/* set the current row to read the fields into */
effective_cols = ci_num_fields;
this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
if (self->haskeyset)
{
this_keyset = self->keyset + self->fcount;
this_keyset->status = 0;
effective_cols -= 2;
}
bitmaplen = (Int2) num_fields / BYTELEN;
@ -672,8 +700,9 @@ QR_read_tuple(QResultClass *self, char binary)
bitmap_pos = 0;
bitcnt = 0;
bmp = bitmap[bitmap_pos];
flds = self->fields;
for (field_lf = 0; field_lf < num_fields; field_lf++)
for (field_lf = 0; field_lf < ci_num_fields; field_lf++)
{
/* Check if the current field is NULL */
if (!(bmp & 0200))
@ -692,14 +721,27 @@ QR_read_tuple(QResultClass *self, char binary)
if (!binary)
len -= VARHDRSZ;
buffer = (char *) malloc(len + 1);
if (field_lf >= effective_cols)
buffer = tidoidbuf;
else
buffer = (char *) malloc(len + 1);
SOCK_get_n_char(sock, buffer, len);
buffer[len] = '\0';
mylog("qresult: len=%d, buffer='%s'\n", len, buffer);
this_tuplefield[field_lf].len = len;
this_tuplefield[field_lf].value = buffer;
if (field_lf >= effective_cols)
{
if (field_lf == effective_cols)
sscanf(buffer, "(%lu,%hu)",
&this_keyset->blocknum, &this_keyset->offset);
else
this_keyset->oid = strtoul(buffer, NULL, 10);
}
else
{
this_tuplefield[field_lf].len = len;
this_tuplefield[field_lf].value = buffer;
/*
* This can be used to set the longest length of the column
@ -710,9 +752,9 @@ QR_read_tuple(QResultClass *self, char binary)
* row!
*/
flds = self->fields;
if (flds && flds->display_size && flds->display_size[field_lf] < len)
flds->display_size[field_lf] = len;
if (flds && flds->display_size && flds->display_size[field_lf] < len)
flds->display_size[field_lf] = len;
}
}
/*
@ -728,15 +770,6 @@ QR_read_tuple(QResultClass *self, char binary)
else
bmp <<= 1;
}
if (this_keyset)
{
if (this_tuplefield[num_fields - 2].value)
sscanf(this_tuplefield[num_fields - 2].value, "(%lu,%hu)",
&this_keyset->blocknum, &this_keyset->offset);
if (this_tuplefield[num_fields - 1].value)
sscanf(this_tuplefield[num_fields - 1].value, "%lu",
&this_keyset->oid);
}
self->currTuple++;
return TRUE;
}

View File

@ -73,8 +73,9 @@ struct QResultClass_
* progress? */
char aborted; /* was aborted? */
char haskeyset; /* this result contains keyset ? */
KeySet *keyset;
KeySet *keyset;
UInt4 rb_count; /* count of rollback info */
Rollback *rollback;
};
#define QR_get_fields(self) (self->fields)

View File

@ -54,6 +54,7 @@
#define DS_DISALLOWPREMATURE 1061
#define DS_LFCONVERSION 1062
#define DS_TRUEISMINUS1 1063
#define DS_UPDATABLECURSORS 1064
/* Next default values for new objects */
/* */
@ -61,7 +62,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1062
#define _APS_NEXT_CONTROL_VALUE 1065
#define _APS_NEXT_SYMED_VALUE 101
#endif /* */

File diff suppressed because it is too large Load Diff

View File

@ -56,7 +56,7 @@ typedef struct tagSETUPDLG
/* Prototypes */
void INTFUNC CenterDialog(HWND hdlg);
int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
int CALLBACK ConfigDlgProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
@ -211,7 +211,7 @@ CenterDialog(HWND hdlg)
*/
int CALLBACK
ConfigDlgProc(HWND hdlg,
WORD wMsg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam)
{

View File

@ -117,6 +117,10 @@ PGAPI_AllocStmt(HDBC hdbc,
/* Copy default statement options based from Connection options */
stmt->options = conn->stmtOptions;
stmt->ardopts = conn->ardOptions;
stmt->ardopts.bookmark = (BindInfoClass *) malloc(sizeof(BindInfoClass));
stmt->ardopts.bookmark->buffer = NULL;
stmt->ardopts.bookmark->used = NULL;
stmt->stmt_size_limit = CC_get_max_query_len(conn);
/* Save the handle for later */
@ -205,17 +209,35 @@ void
InitializeStatementOptions(StatementOptions *opt)
{
memset(opt, 0, sizeof(StatementOptions));
opt->maxRows = 0; /* driver returns all rows */
opt->maxLength = 0; /* driver returns all data for char/binary */
opt->rowset_size = 1;
opt->maxRows = 0; /* driver returns all rows */
opt->maxLength = 0; /* driver returns all data for char/binary */
opt->keyset_size = 0; /* fully keyset driven is the default */
opt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
opt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
opt->bind_size = 0; /* default is to bind by column */
opt->retrieve_data = SQL_RD_ON;
opt->use_bookmarks = SQL_UB_OFF;
}
/*
* ARDFields initialize
*/
void
InitializeARDFields(ARDFields *opt)
{
memset(opt, 0, sizeof(ARDFields));
opt->rowset_size = 1;
opt->bind_size = 0; /* default is to bind by column */
}
/*
* APDFields initialize
*/
void
InitializeAPDFields(APDFields *opt)
{
memset(opt, 0, sizeof(APDFields));
opt->paramset_size = 1;
opt->param_bind_type = 0; /* default is column-wise binding */
opt->param_bind_type = 0; /* default is to bind by column */
}
@ -246,15 +268,6 @@ SC_Constructor(void)
rv->stmt_size_limit = -1;
rv->statement_type = STMT_TYPE_UNKNOWN;
rv->bindings = NULL;
rv->bindings_allocated = 0;
rv->bookmark.buffer = NULL;
rv->bookmark.used = NULL;
rv->parameters_allocated = 0;
rv->parameters = 0;
rv->currTuple = -1;
rv->rowset_start = -1;
rv->current_col = -1;
@ -274,22 +287,65 @@ SC_Constructor(void)
/* Parse Stuff */
rv->ti = NULL;
rv->fi = NULL;
rv->ntab = 0;
rv->nfld = 0;
rv->parse_status = STMT_PARSE_NONE;
/* Clear Statement Options -- defaults will be set in AllocStmt */
memset(&rv->options, 0, sizeof(StatementOptions));
memset(&rv->ardopts, 0, sizeof(ARDFields));
memset(&rv->apdopts, 0, sizeof(APDFields));
memset(&rv->irdopts, 0, sizeof(IRDFields));
memset(&rv->ipdopts, 0, sizeof(IPDFields));
rv->pre_executing = FALSE;
rv->inaccurate_result = FALSE;
rv->miscinfo = 0;
rv->updatable = FALSE;
}
return rv;
}
void ARDFields_free(ARDFields * self)
{
if (self->bookmark)
{
free(self->bookmark);
self->bookmark = NULL;
}
/*
* the memory pointed to by the bindings is not deallocated by the
* driver but by the application that uses that driver, so we don't
* have to care
*/
ARD_unbind_cols(self, TRUE);
}
void APDFields_free(APDFields * self)
{
/* param bindings */
APD_free_params(self, STMT_FREE_PARAMS_ALL);
}
void IRDFields_free(IRDFields * self)
{
/* Free the parsed field information */
if (self->fi)
{
int i;
for (i = 0; i < (int) self->nfields; i++)
if (self->fi[i])
free(self->fi[i]);
free(self->fi);
self->fi = NULL;
}
}
void IPDFields_free(IPDFields * self)
{
}
char
SC_Destructor(StatementClass *self)
{
@ -322,47 +378,25 @@ SC_Destructor(StatementClass *self)
if (self->load_statement)
free(self->load_statement);
SC_free_params(self, STMT_FREE_PARAMS_ALL);
/*
* the memory pointed to by the bindings is not deallocated by the
* driver but by the application that uses that driver, so we don't
* have to care
*/
/* about that here. */
if (self->bindings)
{
int lf;
for (lf = 0; lf < self->bindings_allocated; lf++)
{
if (self->bindings[lf].ttlbuf != NULL)
free(self->bindings[lf].ttlbuf);
}
free(self->bindings);
}
/* Free the parsed table information */
/* Free the parsed table information */
if (self->ti)
{
int i;
int i;
for (i = 0; i < self->ntab; i++)
free(self->ti[i]);
if (self->ti[i]);
free(self->ti[i]);
free(self->ti);
self->ti = NULL;
}
/* Free the parsed field information */
if (self->fi)
{
int i;
for (i = 0; i < self->nfld; i++)
free(self->fi[i]);
free(self->fi);
}
ARDFields_free(&(self->ardopts));
APDFields_free(&(self->apdopts));
IRDFields_free(&(self->irdopts));
IPDFields_free(&(self->ipdopts));
free(self);
mylog("SC_Destructor: EXIT\n");
@ -378,46 +412,16 @@ SC_Destructor(StatementClass *self)
void
SC_free_params(StatementClass *self, char option)
{
int i;
mylog("SC_free_params: ENTER, self=%d\n", self);
if (!self->parameters)
return;
for (i = 0; i < self->parameters_allocated; i++)
{
if (self->parameters[i].data_at_exec == TRUE)
{
if (self->parameters[i].EXEC_used)
{
free(self->parameters[i].EXEC_used);
self->parameters[i].EXEC_used = NULL;
}
if (self->parameters[i].EXEC_buffer)
{
if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
free(self->parameters[i].EXEC_buffer);
self->parameters[i].EXEC_buffer = NULL;
}
}
}
APD_free_params(SC_get_APD(self), option);
self->data_at_exec = -1;
self->current_exec_param = -1;
self->put_data = FALSE;
if (option == STMT_FREE_PARAMS_ALL)
{
free(self->parameters);
self->parameters = NULL;
self->parameters_allocated = 0;
self->exec_start_row = -1;
self->exec_end_row = -1;
self->exec_current_row = -1;
}
mylog("SC_free_params: EXIT\n");
}
@ -493,31 +497,22 @@ SC_recycle_statement(StatementClass *self)
return FALSE;
}
/* Free the parsed table information */
/* Free the parsed table information */
if (self->ti)
{
int i;
int i;
for (i = 0; i < self->ntab; i++)
free(self->ti[i]);
free(self->ti);
if (self->ti)
free(self->ti);
self->ti = NULL;
self->ntab = 0;
}
/* Free the parsed field information */
if (self->fi)
{
int i;
IRDFields_free(SC_get_IRD(self));
for (i = 0; i < self->nfld; i++)
free(self->fi[i]);
free(self->fi);
self->fi = NULL;
self->nfld = 0;
}
self->parse_status = STMT_PARSE_NONE;
self->updatable = FALSE;
/* Free any cursors */
if (res = SC_get_Result(self), res)
@ -605,19 +600,11 @@ SC_pre_execute(StatementClass *self)
char
SC_unbind_cols(StatementClass *self)
{
Int2 lf;
ARDFields *opts = SC_get_ARD(self);
for (lf = 0; lf < self->bindings_allocated; lf++)
{
self->bindings[lf].data_left = -1;
self->bindings[lf].buflen = 0;
self->bindings[lf].buffer = NULL;
self->bindings[lf].used = NULL;
self->bindings[lf].returntype = SQL_C_CHAR;
}
self->bookmark.buffer = NULL;
self->bookmark.used = NULL;
ARD_unbind_cols(opts, FALSE);
opts->bookmark->buffer = NULL;
opts->bookmark->used = NULL;
return 1;
}
@ -732,6 +719,7 @@ SC_fetch(StatementClass *self)
{
static char *func = "SC_fetch";
QResultClass *res = SC_get_Curres(self);
ARDFields *opts;
int retval,
result;
@ -791,25 +779,26 @@ SC_fetch(StatementClass *self)
result = SQL_SUCCESS;
self->last_fetch_count = 1;
opts = SC_get_ARD(self);
/*
* If the bookmark column was bound then return a bookmark. Since this
* is used with SQLExtendedFetch, and the rowset size may be greater
* than 1, and an application can use row or column wise binding, use
* the code in copy_and_convert_field() to handle that.
*/
if (self->bookmark.buffer)
if (opts->bookmark->buffer)
{
char buf[32];
UInt4 offset = self->options.row_offset_ptr ? *self->options.row_offset_ptr : 0;
UInt4 offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
sprintf(buf, "%ld", SC_get_bookmark(self));
result = copy_and_convert_field(self, 0, buf,
SQL_C_ULONG, self->bookmark.buffer + offset, 0,
self->bookmark.used ? self->bookmark.used + (offset >> 2) : NULL);
SQL_C_ULONG, opts->bookmark->buffer + offset, 0,
opts->bookmark->used ? opts->bookmark->used + (offset >> 2) : NULL);
}
#ifdef DRIVER_CURSOR_IMPLEMENT
if (self->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
if (res->haskeyset)
{
num_cols -= 2;
}
@ -818,12 +807,12 @@ SC_fetch(StatementClass *self)
return SQL_SUCCESS;
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, opts = %u, opts->bindings = %u, buffer[] = %u\n", num_cols, lf, opts, opts->bindings, opts->bindings[lf].buffer);
/* reset for SQLGetData */
self->bindings[lf].data_left = -1;
opts->bindings[lf].data_left = -1;
if (self->bindings[lf].buffer != NULL)
if (opts->bindings[lf].buffer != NULL)
{
/* this column has a binding */
@ -871,7 +860,7 @@ SC_fetch(StatementClass *self)
self->errornumber = STMT_TRUNCATED;
self->errormsg = "Fetched item was truncated.";
qlog("The %dth item was truncated\n", lf + 1);
qlog("The buffer size = %d", self->bindings[lf].buflen);
qlog("The buffer size = %d", opts->bindings[lf].buflen);
qlog(" and the value is '%s'\n", value);
result = SQL_SUCCESS_WITH_INFO;
break;
@ -905,12 +894,14 @@ SC_execute(StatementClass *self)
{
static char *func = "SC_execute";
ConnectionClass *conn;
APDFields *apdopts;
char was_ok, was_nonfatal;
QResultClass *res = NULL;
Int2 oldstatus,
numcols;
QueryInfo qi;
ConnInfo *ci;
UDWORD qflag = 0;
conn = SC_get_conn(self);
@ -931,13 +922,15 @@ SC_execute(StatementClass *self)
(!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER)))
{
mylog(" about to begin a transaction on statement = %u\n", self);
if (!CC_begin(conn))
{
self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self);
return SQL_ERROR;
}
if (PG_VERSION_GE(conn, 7.1))
qflag |= GO_INTO_TRANSACTION;
else if (!CC_begin(conn))
{
self->errormsg = "Could not begin a transaction";
self->errornumber = STMT_EXEC_ERROR;
SC_log_error(func, "", self);
return SQL_ERROR;
}
}
oldstatus = conn->status;
@ -954,7 +947,7 @@ SC_execute(StatementClass *self)
if (self->statement_type == STMT_TYPE_SELECT)
{
char fetch[128];
UDWORD qflag = (SQL_CONCUR_ROWVER == self->options.scroll_concurrency ? CREATE_KEYSET : 0);
qflag |= (SQL_CONCUR_READ_ONLY != self->options.scroll_concurrency ? CREATE_KEYSET : 0);
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
@ -964,6 +957,7 @@ SC_execute(StatementClass *self)
QR_command_successful(res))
{
QR_Destructor(res);
qflag &= (~ GO_INTO_TRANSACTION);
/*
* That worked, so now send the fetch to start getting data
@ -990,7 +984,7 @@ SC_execute(StatementClass *self)
{
/* not a SELECT statement so don't use a cursor */
mylog(" it's NOT a select statement: stmt=%u\n", self);
res = CC_send_query(conn, self->stmt_with_params, NULL, 0);
res = CC_send_query(conn, self->stmt_with_params, NULL, qflag);
/*
* We shouldn't send COMMIT. Postgres backend does the autocommit
@ -1037,8 +1031,9 @@ SC_execute(StatementClass *self)
/* now allocate the array to hold the binding info */
if (numcols > 0)
{
extend_bindings(self, numcols);
if (self->bindings == NULL)
ARDFields *opts = SC_get_ARD(self);
extend_column_bindings(opts, numcols);
if (opts->bindings == NULL)
{
QR_Destructor(res);
self->errornumber = STMT_NO_MEMORY_ERROR;
@ -1083,12 +1078,13 @@ SC_execute(StatementClass *self)
last->next = res;
}
apdopts = SC_get_APD(self);
if (self->statement_type == STMT_TYPE_PROCCALL &&
(self->errornumber == STMT_OK ||
self->errornumber == STMT_INFO_ONLY) &&
self->parameters &&
self->parameters[0].buffer &&
self->parameters[0].paramType == SQL_PARAM_OUTPUT)
apdopts->parameters &&
apdopts->parameters[0].buffer &&
apdopts->parameters[0].paramType == SQL_PARAM_OUTPUT)
{ /* get the return value of the procedure
* call */
RETCODE ret;
@ -1097,7 +1093,7 @@ SC_execute(StatementClass *self)
ret = SC_fetch(hstmt);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
{
ret = PGAPI_GetData(hstmt, 1, self->parameters[0].CType, self->parameters[0].buffer, self->parameters[0].buflen, self->parameters[0].used);
ret = PGAPI_GetData(hstmt, 1, apdopts->parameters[0].CType, apdopts->parameters[0].buffer, apdopts->parameters[0].buflen, apdopts->parameters[0].used);
if (ret != SQL_SUCCESS)
{
self->errornumber = STMT_EXEC_ERROR;
@ -1133,19 +1129,21 @@ SC_log_error(const char *func, const char *desc, const StatementClass *self)
if (self)
{
QResultClass *res = SC_get_Result(self);
const ARDFields *opts = SC_get_ARD(self);
const APDFields *apdopts = SC_get_APD(self);
qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
qlog(" ------------------------------------------------------------\n");
qlog(" hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, res);
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(" bindings=%u, bindings_allocated=%d\n", opts->bindings, opts->allocated);
qlog(" parameters=%u, parameters_allocated=%d\n", apdopts->parameters, apdopts->allocated);
qlog(" statement_type=%d, statement='%s'\n", self->statement_type, nullcheck(self->statement));
qlog(" stmt_with_params='%s'\n", nullcheck(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->options.maxRows, self->options.rowset_size, self->options.keyset_size, self->options.cursor_type, self->options.scroll_concurrency);
qlog(" maxRows=%d, rowset_size=%d, keyset_size=%d, cursor_type=%d, scroll_concurrency=%d\n", self->options.maxRows, opts->rowset_size, self->options.keyset_size, self->options.cursor_type, self->options.scroll_concurrency);
qlog(" cursor_name='%s'\n", nullcheck(self->cursor_name));
qlog(" ----------------QResult Info -------------------------------\n");

View File

@ -12,6 +12,7 @@
#include "psqlodbc.h"
#include "bind.h"
#include "descriptor.h"
#ifndef FALSE
@ -77,6 +78,7 @@ typedef enum
#define STMT_INVALID_OPTION_IDENTIFIER 28
#define STMT_RETURN_NULL_WITHOUT_INDICATOR 29
#define STMT_ERROR_IN_ROW 30
#define STMT_INVALID_DESCRIPTOR_IDENTIFIER 31
/* statement types */
enum
@ -115,33 +117,6 @@ enum
STMT_FETCH_EXTENDED,
};
typedef struct
{
COL_INFO *col_info; /* cached SQLColumns info for this table */
char name[MAX_TABLE_LEN + 1];
char alias[MAX_TABLE_LEN + 1];
} TABLE_INFO;
typedef struct
{
TABLE_INFO *ti; /* resolve to explicit table names */
int precision;
int scale;
int display_size;
int length;
int type;
char nullable;
char func;
char expr;
char quote;
char dquote;
char numeric;
char updatable;
char dot[MAX_TABLE_LEN + 1];
char name[MAX_COLUMN_LEN + 1];
char alias[MAX_COLUMN_LEN + 1];
} FIELD_INFO;
/******** Statement Handle ***********/
struct StatementClass_
@ -152,19 +127,23 @@ struct StatementClass_
QResultClass *curres; /* the current result in the chain */
HSTMT FAR *phstmt;
StatementOptions options;
ARDFields ardopts;
IRDFields irdopts;
APDFields apdopts;
IPDFields ipdopts;
STMT_Status status;
char *errormsg;
int errornumber;
/* information on bindings */
BindInfoClass *bindings; /* array to store the binding information */
BindInfoClass bookmark;
int bindings_allocated;
/*** BindInfoClass *bindings; ***/ /* array to store the binding information */
/*** BindInfoClass bookmark;
int bindings_allocated; ***/
/* information on statement parameters */
int parameters_allocated;
ParameterInfoClass *parameters;
/*** int parameters_allocated;
ParameterInfoClass *parameters; ***/
Int4 currTuple; /* current absolute row number (GetData,
* SetPos, SQLFetch) */
@ -184,8 +163,6 @@ struct StatementClass_
* statement that has been executed */
TABLE_INFO **ti;
FIELD_INFO **fi;
int nfld;
int ntab;
int parse_status;
@ -219,6 +196,7 @@ struct StatementClass_
char inaccurate_result; /* Current status is PREMATURE but
* result is inaccurate */
char miscinfo;
char updatable;
SWORD errorpos;
SWORD error_recsize;
char *load_statement; /* to (re)load updatable individual rows */
@ -231,6 +209,10 @@ struct StatementClass_
#define SC_get_Result(a) (a->result)
#define SC_set_Curres(a, b) (a->curres = b)
#define SC_get_Curres(a) (a->curres)
#define SC_get_ARD(a) (&(a->ardopts))
#define SC_get_APD(a) (&(a->apdopts))
#define SC_get_IRD(a) (&(a->irdopts))
#define SC_get_IPD(a) (&(a->ipdopts))
/* options for SC_free_params() */
#define STMT_FREE_PARAMS_ALL 0
@ -262,5 +244,9 @@ RETCODE SC_fetch(StatementClass *self);
void SC_free_params(StatementClass *self, char option);
void SC_log_error(const char *func, const char *desc, const StatementClass *self);
unsigned long SC_get_bookmark(StatementClass *self);
RETCODE SC_pos_update(StatementClass *self, UWORD irow, UDWORD index);
RETCODE SC_pos_delete(StatementClass *self, UWORD irow, UDWORD index);
RETCODE SC_pos_refresh(StatementClass *self, UWORD irow, UDWORD index);
RETCODE SC_pos_add(StatementClass *self, UWORD irow);
#endif

View File

@ -38,10 +38,21 @@ struct KeySet_
UDWORD blocknum;
UDWORD oid;
};
#define KEYSET_INFO_PUBLIC 0x0f
#define DRV_SELF_ADDED (1L << 4)
#define DRV_SELF_DELETED (1L << 5)
#define DRV_SELF_UPDATED (1L << 6)
/* Rollback(index + original TID) info */
struct Rollback_
{
UDWORD index;
UDWORD blocknum;
UWORD offset;
};
#define KEYSET_INFO_PUBLIC 0x07
#define CURS_SELF_ADDING (1L << 3)
#define CURS_SELF_DELETING (1L << 4)
#define CURS_SELF_UPDATING (1L << 5)
#define CURS_SELF_ADDED (1L << 6)
#define CURS_SELF_DELETED (1L << 7)
#define CURS_SELF_UPDATED (1L << 8)
#define CURS_NEEDS_REREAD (1L << 9)
/* These macros are wrappers for the corresponding set_tuplefield functions
but these handle automatic NULL determination and call set_tuplefield_null()

View File

@ -96,9 +96,9 @@ CLEAN :
CPP=cl.exe
!IF "$(CFG)" == "MultibyteRelease"
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "MULTIBYTE" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "MULTIBYTE" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
!ELSE
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
!ENDIF
.c{$(INTDIR)}.obj::

View File

@ -1,7 +1,7 @@
#
# File: win32_30w.mak
#
# Description: psqlodbc30 Unicode version Makefile for Win32.
# Description: psqlodbc30w Unicode version Makefile for Win32.
#
# Configurations: Unicode30Debug, Unicode30
# Build Types: ALL, CLEAN
@ -45,7 +45,7 @@ OUTDIR=.\Unicode30
OUTDIRBIN=.\Unicode30
INTDIR=.\Unicode30
ALL : "$(OUTDIRBIN)\psqlodbc30.dll"
ALL : "$(OUTDIRBIN)\psqlodbc30w.dll"
CLEAN :
@ -82,7 +82,7 @@ CLEAN :
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\psqlodbc30.dll"
-@erase "$(OUTDIR)\psqlodbc30w.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
-@erase "$(OUTDIR)\psqlodbc.lib"
@ -131,7 +131,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIRBIN)\psqlodbc30.dll" /implib:"$(OUTDIR)\psqlodbc.lib"
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIRBIN)\psqlodbc30w.dll" /implib:"$(OUTDIR)\psqlodbc.lib"
DEF_FILE= "psqlodbc_api30w.def"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
@ -167,14 +167,14 @@ LINK32_OBJS= \
"$(INTDIR)\odbcapi30.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
"$(OUTDIRBIN)\psqlodbc30w.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "Unicode30Debug"
ALL : "$(OUTDIR)\psqlodbc30.dll"
ALL : "$(OUTDIR)\psqlodbc30w.dll"
CLEAN :
@ -212,7 +212,7 @@ CLEAN :
-@erase "$(INTDIR)\odbcapi30.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\psqlodbc30.dll"
-@erase "$(OUTDIR)\psqlodbc30w.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
-@erase "$(OUTDIR)\psqlodbc.ilk"
-@erase "$(OUTDIR)\psqlodbc.lib"
@ -263,7 +263,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIR)\psqlodbc30.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIR)\psqlodbc30w.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept
DEF_FILE= "psqlodbc_api30w.def"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
@ -299,7 +299,7 @@ LINK32_OBJS= \
"$(INTDIR)\odbcapi30.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
"$(OUTDIR)\psqlodbc30w.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<