mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Update 06-40-0004 -- Add Bookmark support!
This commit is contained in:
@ -162,13 +162,6 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
|
|||||||
return SQL_INVALID_HANDLE;
|
return SQL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (icol < 1) {
|
|
||||||
/* currently we do not support bookmarks */
|
|
||||||
stmt->errormsg = "Bookmarks are not currently supported.";
|
|
||||||
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
|
||||||
SC_log_error(func, "", stmt);
|
|
||||||
return SQL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
SC_clear_error(stmt);
|
SC_clear_error(stmt);
|
||||||
|
|
||||||
@ -179,6 +172,28 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Make sure it is the bookmark data type */
|
||||||
|
if ( fCType != SQL_C_BOOKMARK) {
|
||||||
|
stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
|
||||||
|
stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt->bookmark.buffer = rgbValue;
|
||||||
|
stmt->bookmark.used = pcbValue;
|
||||||
|
}
|
||||||
|
return SQL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate enough bindings if not already done
|
// allocate enough bindings if not already done
|
||||||
// Most likely, execution of a statement would have setup the
|
// Most likely, execution of a statement would have setup the
|
||||||
// necessary bindings. But some apps call BindCol before any
|
// necessary bindings. But some apps call BindCol before any
|
||||||
|
@ -190,6 +190,11 @@ int status;
|
|||||||
case STMT_VALUE_OUT_OF_RANGE:
|
case STMT_VALUE_OUT_OF_RANGE:
|
||||||
strcpy(szSqlState, "22003");
|
strcpy(szSqlState, "22003");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STMT_OPERATION_INVALID:
|
||||||
|
strcpy(szSqlState, "S1011");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
strcpy(szSqlState, "S1000");
|
strcpy(szSqlState, "S1000");
|
||||||
// also a general error
|
// also a general error
|
||||||
|
@ -107,8 +107,9 @@ RETCODE result;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
|
case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
|
||||||
|
/* very simple bookmark support */
|
||||||
len = 4;
|
len = 4;
|
||||||
value = 0;
|
value = globals.use_declarefetch ? 0 : (SQL_BP_SCROLL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
|
case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
|
||||||
@ -221,7 +222,8 @@ RETCODE result;
|
|||||||
SQL_FD_FETCH_LAST |
|
SQL_FD_FETCH_LAST |
|
||||||
SQL_FD_FETCH_PRIOR |
|
SQL_FD_FETCH_PRIOR |
|
||||||
SQL_FD_FETCH_ABSOLUTE |
|
SQL_FD_FETCH_ABSOLUTE |
|
||||||
SQL_FD_FETCH_RELATIVE);
|
SQL_FD_FETCH_RELATIVE |
|
||||||
|
SQL_FD_FETCH_BOOKMARK);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_FILE_USAGE: /* ODBC 2.0 */
|
case SQL_FILE_USAGE: /* ODBC 2.0 */
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
|
#include "qresult.h"
|
||||||
|
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
@ -189,7 +190,6 @@ char changed = FALSE;
|
|||||||
if (conn) conn->stmtOptions.rowset_size = vParam;
|
if (conn) conn->stmtOptions.rowset_size = vParam;
|
||||||
if (stmt) stmt->options.rowset_size = vParam;
|
if (stmt) stmt->options.rowset_size = vParam;
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
|
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
|
||||||
@ -205,18 +205,11 @@ char changed = FALSE;
|
|||||||
}
|
}
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
|
|
||||||
case SQL_USE_BOOKMARKS: /* NOT SUPPORTED */
|
case SQL_USE_BOOKMARKS:
|
||||||
if (stmt) {
|
|
||||||
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
if (stmt) stmt->options.use_bookmarks = vParam;
|
||||||
stmt->errormsg = "Driver does not support (SET) using bookmarks.";
|
if (conn) conn->stmtOptions.use_bookmarks = vParam;
|
||||||
SC_log_error(func, "", stmt);
|
break;
|
||||||
}
|
|
||||||
if (conn) {
|
|
||||||
conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
|
||||||
conn->errormsg = "Driver does not support (SET) using bookmarks.";
|
|
||||||
CC_log_error(func, "", conn);
|
|
||||||
}
|
|
||||||
return SQL_ERROR;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -507,6 +500,7 @@ RETCODE SQL_API SQLGetStmtOption(
|
|||||||
{
|
{
|
||||||
static char *func="SQLGetStmtOption";
|
static char *func="SQLGetStmtOption";
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
|
QResultClass *res;
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
@ -520,15 +514,39 @@ StatementClass *stmt = (StatementClass *) hstmt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch(fOption) {
|
switch(fOption) {
|
||||||
case SQL_GET_BOOKMARK:/* NOT SUPPORTED */
|
case SQL_GET_BOOKMARK:
|
||||||
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
case SQL_ROW_NUMBER:
|
||||||
stmt->errormsg = "Driver does not support getting bookmarks.";
|
|
||||||
|
res = stmt->result;
|
||||||
|
|
||||||
|
if ( stmt->manual_result || ! globals.use_declarefetch) {
|
||||||
|
// make sure we're positioned on a valid row
|
||||||
|
if((stmt->currTuple < 0) ||
|
||||||
|
(stmt->currTuple >= QR_get_num_tuples(res))) {
|
||||||
|
stmt->errormsg = "Not positioned on a valid row.";
|
||||||
|
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
|
||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (stmt->currTuple == -1 || ! res || ! res->tupleField) {
|
||||||
|
stmt->errormsg = "Not positioned on a valid row.";
|
||||||
|
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF) {
|
||||||
|
stmt->errormsg = "Operation invalid because use bookmarks not enabled.";
|
||||||
|
stmt->errornumber = STMT_OPERATION_INVALID;
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*((UDWORD *) pvParam) = SC_get_bookmark(stmt);
|
||||||
|
|
||||||
case SQL_ROW_NUMBER:
|
|
||||||
*((SDWORD *) pvParam) = stmt->currTuple + 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_ASYNC_ENABLE: /* NOT SUPPORTED */
|
case SQL_ASYNC_ENABLE: /* NOT SUPPORTED */
|
||||||
@ -583,8 +601,8 @@ StatementClass *stmt = (StatementClass *) hstmt;
|
|||||||
*((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE;
|
*((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_USE_BOOKMARKS:/* NOT SUPPORTED */
|
case SQL_USE_BOOKMARKS:
|
||||||
*((SDWORD *) pvParam) = SQL_UB_OFF;
|
*((SDWORD *) pvParam) = stmt->options.use_bookmarks;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -39,8 +39,8 @@ typedef UInt4 Oid;
|
|||||||
|
|
||||||
#define DRIVERNAME "PostgreSQL ODBC"
|
#define DRIVERNAME "PostgreSQL ODBC"
|
||||||
#define DBMS_NAME "PostgreSQL"
|
#define DBMS_NAME "PostgreSQL"
|
||||||
#define DBMS_VERSION "06.40.0003 PostgreSQL 6.4"
|
#define DBMS_VERSION "06.40.0004 PostgreSQL 6.4"
|
||||||
#define POSTGRESDRIVERVERSION "06.40.0003"
|
#define POSTGRESDRIVERVERSION "06.40.0004"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
|
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
|
||||||
@ -137,6 +137,7 @@ typedef struct StatementOptions_ {
|
|||||||
int scroll_concurrency;
|
int scroll_concurrency;
|
||||||
int retrieve_data;
|
int retrieve_data;
|
||||||
int bind_size; /* size of each structure if using Row Binding */
|
int bind_size; /* size of each structure if using Row Binding */
|
||||||
|
int use_bookmarks;
|
||||||
} StatementOptions;
|
} StatementOptions;
|
||||||
|
|
||||||
/* Used to pass extra query info to send_query */
|
/* Used to pass extra query info to send_query */
|
||||||
|
@ -204,8 +204,8 @@ END
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 6,40,0,3
|
FILEVERSION 6,40,0,4
|
||||||
PRODUCTVERSION 6,40,0,3
|
PRODUCTVERSION 6,40,0,4
|
||||||
FILEFLAGSMASK 0x3L
|
FILEFLAGSMASK 0x3L
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -223,12 +223,12 @@ BEGIN
|
|||||||
VALUE "Comments", "PostgreSQL ODBC driver for Windows 95\0"
|
VALUE "Comments", "PostgreSQL ODBC driver for Windows 95\0"
|
||||||
VALUE "CompanyName", "Insight Distribution Systems\0"
|
VALUE "CompanyName", "Insight Distribution Systems\0"
|
||||||
VALUE "FileDescription", "PostgreSQL Driver\0"
|
VALUE "FileDescription", "PostgreSQL Driver\0"
|
||||||
VALUE "FileVersion", " 6.40.0003\0"
|
VALUE "FileVersion", " 6.40.0004\0"
|
||||||
VALUE "InternalName", "psqlodbc\0"
|
VALUE "InternalName", "psqlodbc\0"
|
||||||
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft<66> is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
|
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft<66> is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
|
||||||
VALUE "OriginalFilename", "psqlodbc.dll\0"
|
VALUE "OriginalFilename", "psqlodbc.dll\0"
|
||||||
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
|
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
|
||||||
VALUE "ProductVersion", " 6.40.0003\0"
|
VALUE "ProductVersion", " 6.40.0004\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -610,7 +610,7 @@ int num_cols, num_rows;
|
|||||||
Int4 field_type;
|
Int4 field_type;
|
||||||
void *value;
|
void *value;
|
||||||
int result;
|
int result;
|
||||||
|
char get_bookmark = FALSE;
|
||||||
|
|
||||||
mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
||||||
|
|
||||||
@ -635,12 +635,28 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (icol == 0) {
|
if (icol == 0) {
|
||||||
stmt->errormsg = "Bookmarks are not currently supported.";
|
|
||||||
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
if (stmt->options.use_bookmarks == SQL_UB_OFF) {
|
||||||
|
stmt->errornumber = STMT_COLNUM_ERROR;
|
||||||
|
stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
|
||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure it is the bookmark data type */
|
||||||
|
if (fCType != SQL_C_BOOKMARK) {
|
||||||
|
stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
|
||||||
|
stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_bookmark = TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
|
||||||
// use zero-based column numbers
|
// use zero-based column numbers
|
||||||
icol--;
|
icol--;
|
||||||
|
|
||||||
@ -652,6 +668,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
|||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( stmt->manual_result || ! globals.use_declarefetch) {
|
if ( stmt->manual_result || ! globals.use_declarefetch) {
|
||||||
// make sure we're positioned on a valid row
|
// make sure we're positioned on a valid row
|
||||||
@ -664,6 +681,8 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
mylog(" num_rows = %d\n", num_rows);
|
mylog(" num_rows = %d\n", num_rows);
|
||||||
|
|
||||||
|
if ( ! get_bookmark) {
|
||||||
if ( stmt->manual_result) {
|
if ( stmt->manual_result) {
|
||||||
value = QR_get_value_manual(res, stmt->currTuple, icol);
|
value = QR_get_value_manual(res, stmt->currTuple, icol);
|
||||||
}
|
}
|
||||||
@ -672,6 +691,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
|||||||
}
|
}
|
||||||
mylog(" value = '%s'\n", value);
|
mylog(" value = '%s'\n", value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else { /* its a SOCKET result (backend data) */
|
else { /* its a SOCKET result (backend data) */
|
||||||
if (stmt->currTuple == -1 || ! res || ! res->tupleField) {
|
if (stmt->currTuple == -1 || ! res || ! res->tupleField) {
|
||||||
stmt->errormsg = "Not positioned on a valid row for GetData.";
|
stmt->errormsg = "Not positioned on a valid row for GetData.";
|
||||||
@ -680,11 +700,21 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! get_bookmark)
|
||||||
value = QR_get_value_backend(res, icol);
|
value = QR_get_value_backend(res, icol);
|
||||||
|
|
||||||
mylog(" socket: value = '%s'\n", value);
|
mylog(" socket: value = '%s'\n", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( get_bookmark) {
|
||||||
|
*((UDWORD *) rgbValue) = SC_get_bookmark(stmt);
|
||||||
|
|
||||||
|
if (pcbValue)
|
||||||
|
*pcbValue = 4;
|
||||||
|
|
||||||
|
return SQL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
field_type = QR_get_field_type(res, icol);
|
field_type = QR_get_field_type(res, icol);
|
||||||
|
|
||||||
mylog("**** SQLGetData: icol = %d, fCType = %d, field_type = %d, value = '%s'\n", icol, fCType, field_type, value);
|
mylog("**** SQLGetData: icol = %d, fCType = %d, field_type = %d, value = '%s'\n", icol, fCType, field_type, value);
|
||||||
@ -761,6 +791,14 @@ mylog("SQLFetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result);
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Not allowed to bind a bookmark column when using SQLFetch. */
|
||||||
|
if ( stmt->bookmark.buffer) {
|
||||||
|
stmt->errornumber = STMT_COLNUM_ERROR;
|
||||||
|
stmt->errormsg = "Not allowed to bind a bookmark column when using SQLFetch";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (stmt->status == STMT_EXECUTING) {
|
if (stmt->status == STMT_EXECUTING) {
|
||||||
stmt->errormsg = "Can't fetch while statement is still executing.";
|
stmt->errormsg = "Can't fetch while statement is still executing.";
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
@ -831,6 +869,14 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If a bookmark colunmn is bound but bookmark usage is off, then error */
|
||||||
|
if (stmt->bookmark.buffer && stmt->options.use_bookmarks == SQL_UB_OFF) {
|
||||||
|
stmt->errornumber = STMT_COLNUM_ERROR;
|
||||||
|
stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (stmt->status == STMT_EXECUTING) {
|
if (stmt->status == STMT_EXECUTING) {
|
||||||
stmt->errormsg = "Can't fetch while statement is still executing.";
|
stmt->errormsg = "Can't fetch while statement is still executing.";
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
@ -950,6 +996,11 @@ mylog("SQLExtendedFetch: stmt=%u\n", stmt);
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SQL_FETCH_BOOKMARK:
|
||||||
|
|
||||||
|
stmt->rowset_start = irow - 1;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
|
SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
|
@ -185,6 +185,7 @@ InitializeStatementOptions(StatementOptions *opt)
|
|||||||
opt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
|
opt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
|
||||||
opt->bind_size = 0; /* default is to bind by column */
|
opt->bind_size = 0; /* default is to bind by column */
|
||||||
opt->retrieve_data = SQL_RD_ON;
|
opt->retrieve_data = SQL_RD_ON;
|
||||||
|
opt->use_bookmarks = SQL_UB_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
StatementClass *
|
StatementClass *
|
||||||
@ -213,6 +214,9 @@ StatementClass *rv;
|
|||||||
rv->bindings = NULL;
|
rv->bindings = NULL;
|
||||||
rv->bindings_allocated = 0;
|
rv->bindings_allocated = 0;
|
||||||
|
|
||||||
|
rv->bookmark.buffer = NULL;
|
||||||
|
rv->bookmark.used = NULL;
|
||||||
|
|
||||||
rv->parameters_allocated = 0;
|
rv->parameters_allocated = 0;
|
||||||
rv->parameters = 0;
|
rv->parameters = 0;
|
||||||
|
|
||||||
@ -496,6 +500,9 @@ Int2 lf;
|
|||||||
self->bindings[lf].returntype = SQL_C_CHAR;
|
self->bindings[lf].returntype = SQL_C_CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->bookmark.buffer = NULL;
|
||||||
|
self->bookmark.used = NULL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,6 +573,15 @@ char rv;
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Currently, the driver offers very simple bookmark support -- it is
|
||||||
|
just the current row number. But it could be more sophisticated
|
||||||
|
someday, such as mapping a key to a 32 bit value
|
||||||
|
*/
|
||||||
|
unsigned long
|
||||||
|
SC_get_bookmark(StatementClass *self)
|
||||||
|
{
|
||||||
|
return (self->currTuple + 1);
|
||||||
|
}
|
||||||
|
|
||||||
RETCODE
|
RETCODE
|
||||||
SC_fetch(StatementClass *self)
|
SC_fetch(StatementClass *self)
|
||||||
@ -624,6 +640,19 @@ ColumnInfoClass *ci;
|
|||||||
result = SQL_SUCCESS;
|
result = SQL_SUCCESS;
|
||||||
self->last_fetch_count = 1;
|
self->last_fetch_count = 1;
|
||||||
|
|
||||||
|
/* If the bookmark column was bound then return a bookmark.
|
||||||
|
Since this is used with SQLExtendedFetch, and the rowset size
|
||||||
|
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) {
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
sprintf(buf, "%ld", SC_get_bookmark(self));
|
||||||
|
result = copy_and_convert_field(self, 0, buf,
|
||||||
|
SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used);
|
||||||
|
}
|
||||||
|
|
||||||
for (lf=0; lf < num_cols; lf++) {
|
for (lf=0; lf < num_cols; lf++) {
|
||||||
|
|
||||||
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
|
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
#include "bind.h"
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include "iodbc.h"
|
#include "iodbc.h"
|
||||||
@ -71,6 +72,8 @@ typedef enum {
|
|||||||
#define STMT_OPERATION_CANCELLED 22
|
#define STMT_OPERATION_CANCELLED 22
|
||||||
#define STMT_INVALID_CURSOR_POSITION 23
|
#define STMT_INVALID_CURSOR_POSITION 23
|
||||||
#define STMT_VALUE_OUT_OF_RANGE 24
|
#define STMT_VALUE_OUT_OF_RANGE 24
|
||||||
|
#define STMT_OPERATION_INVALID 25
|
||||||
|
#define STMT_PROGRAM_TYPE_OUT_OF_RANGE 26
|
||||||
|
|
||||||
/* statement types */
|
/* statement types */
|
||||||
enum {
|
enum {
|
||||||
@ -142,6 +145,7 @@ struct StatementClass_ {
|
|||||||
|
|
||||||
/* information on bindings */
|
/* information on bindings */
|
||||||
BindInfoClass *bindings; /* array to store the binding information */
|
BindInfoClass *bindings; /* array to store the binding information */
|
||||||
|
BindInfoClass bookmark;
|
||||||
int bindings_allocated;
|
int bindings_allocated;
|
||||||
|
|
||||||
/* information on statement parameters */
|
/* information on statement parameters */
|
||||||
@ -207,6 +211,7 @@ RETCODE SC_execute(StatementClass *self);
|
|||||||
RETCODE SC_fetch(StatementClass *self);
|
RETCODE SC_fetch(StatementClass *self);
|
||||||
void SC_free_params(StatementClass *self, char option);
|
void SC_free_params(StatementClass *self, char option);
|
||||||
void SC_log_error(char *func, char *desc, StatementClass *self);
|
void SC_log_error(char *func, char *desc, StatementClass *self);
|
||||||
|
unsigned long SC_get_bookmark(StatementClass *self);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user