2121 lines
59 KiB
C
2121 lines
59 KiB
C
/*-------
|
|
* Module: pgapi30.c
|
|
*
|
|
* Description: This module contains routines related to ODBC 3.0
|
|
* most of their implementations are temporary
|
|
* and must be rewritten properly.
|
|
* 2001/07/23 inoue
|
|
*
|
|
* Classes: n/a
|
|
*
|
|
* API functions: PGAPI_ColAttribute, PGAPI_GetDiagRec,
|
|
PGAPI_GetConnectAttr, PGAPI_GetStmtAttr,
|
|
PGAPI_SetConnectAttr, PGAPI_SetStmtAttr
|
|
*-------
|
|
*/
|
|
|
|
#include "psqlodbc.h"
|
|
#include "misc.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
#include "environ.h"
|
|
#include "connection.h"
|
|
#include "statement.h"
|
|
#include "descriptor.h"
|
|
#include "qresult.h"
|
|
#include "pgapifunc.h"
|
|
#include "loadlib.h"
|
|
#include "dlg_specific.h"
|
|
|
|
|
|
/* SQLError -> SQLDiagRec */
|
|
RETCODE SQL_API
|
|
PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|
SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
|
|
SQLINTEGER *NativeError, SQLCHAR *MessageText,
|
|
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
|
|
{
|
|
RETCODE ret;
|
|
|
|
MYLOG(0, "entering type=%d rec=%d\n", HandleType, RecNumber);
|
|
switch (HandleType)
|
|
{
|
|
case SQL_HANDLE_ENV:
|
|
ret = PGAPI_EnvError(Handle, RecNumber, Sqlstate,
|
|
NativeError, MessageText,
|
|
BufferLength, TextLength, 0);
|
|
break;
|
|
case SQL_HANDLE_DBC:
|
|
ret = PGAPI_ConnectError(Handle, RecNumber, Sqlstate,
|
|
NativeError, MessageText, BufferLength,
|
|
TextLength, 0);
|
|
break;
|
|
case SQL_HANDLE_STMT:
|
|
ret = PGAPI_StmtError(Handle, RecNumber, Sqlstate,
|
|
NativeError, MessageText, BufferLength,
|
|
TextLength, 0);
|
|
break;
|
|
case SQL_HANDLE_DESC:
|
|
ret = PGAPI_DescError(Handle, RecNumber, Sqlstate,
|
|
NativeError,
|
|
MessageText, BufferLength,
|
|
TextLength, 0);
|
|
break;
|
|
default:
|
|
ret = SQL_ERROR;
|
|
}
|
|
MYLOG(0, "leaving %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Minimal implementation.
|
|
*
|
|
*/
|
|
RETCODE SQL_API
|
|
PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|
SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
|
|
PTR DiagInfoPtr, SQLSMALLINT BufferLength,
|
|
SQLSMALLINT *StringLengthPtr)
|
|
{
|
|
RETCODE ret = SQL_ERROR, rtn;
|
|
ConnectionClass *conn;
|
|
StatementClass *stmt;
|
|
SQLLEN rc;
|
|
SQLSMALLINT pcbErrm;
|
|
ssize_t rtnlen = -1;
|
|
int rtnctype = SQL_C_CHAR;
|
|
|
|
MYLOG(0, "entering rec=%d\n", RecNumber);
|
|
switch (HandleType)
|
|
{
|
|
case SQL_HANDLE_ENV:
|
|
switch (DiagIdentifier)
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
case SQL_DIAG_SERVER_NAME:
|
|
rtnlen = 0;
|
|
if (DiagInfoPtr && BufferLength > rtnlen)
|
|
{
|
|
ret = SQL_SUCCESS;
|
|
*((char *) DiagInfoPtr) = '\0';
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
ret = PGAPI_EnvError(Handle, RecNumber,
|
|
NULL, NULL, DiagInfoPtr,
|
|
BufferLength, StringLengthPtr, 0);
|
|
break;
|
|
case SQL_DIAG_NATIVE:
|
|
rtnctype = SQL_C_LONG;
|
|
ret = PGAPI_EnvError(Handle, RecNumber,
|
|
NULL, (SQLINTEGER *) DiagInfoPtr, NULL,
|
|
0, NULL, 0);
|
|
break;
|
|
case SQL_DIAG_NUMBER:
|
|
rtnctype = SQL_C_LONG;
|
|
ret = PGAPI_EnvError(Handle, RecNumber,
|
|
NULL, NULL, NULL,
|
|
0, NULL, 0);
|
|
if (SQL_SUCCEEDED(ret))
|
|
{
|
|
*((SQLINTEGER *) DiagInfoPtr) = 1;
|
|
}
|
|
break;
|
|
case SQL_DIAG_SQLSTATE:
|
|
rtnlen = 5;
|
|
ret = PGAPI_EnvError(Handle, RecNumber,
|
|
DiagInfoPtr, NULL, NULL,
|
|
0, NULL, 0);
|
|
if (SQL_SUCCESS_WITH_INFO == ret)
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_RETURNCODE: /* driver manager returns */
|
|
break;
|
|
case SQL_DIAG_CURSOR_ROW_COUNT:
|
|
case SQL_DIAG_ROW_COUNT:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
|
|
/* options for statement type only */
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_HANDLE_DBC:
|
|
conn = (ConnectionClass *) Handle;
|
|
switch (DiagIdentifier)
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
rtnlen = 0;
|
|
if (DiagInfoPtr && BufferLength > rtnlen)
|
|
{
|
|
ret = SQL_SUCCESS;
|
|
*((char *) DiagInfoPtr) = '\0';
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_SERVER_NAME:
|
|
rtnlen = strlen(CC_get_DSN(conn));
|
|
if (DiagInfoPtr)
|
|
{
|
|
strncpy_null(DiagInfoPtr, CC_get_DSN(conn), BufferLength);
|
|
ret = (BufferLength > rtnlen ? SQL_SUCCESS : SQL_SUCCESS_WITH_INFO);
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
ret = PGAPI_ConnectError(Handle, RecNumber,
|
|
NULL, NULL, DiagInfoPtr,
|
|
BufferLength, StringLengthPtr, 0);
|
|
break;
|
|
case SQL_DIAG_NATIVE:
|
|
rtnctype = SQL_C_LONG;
|
|
ret = PGAPI_ConnectError(Handle, RecNumber,
|
|
NULL, (SQLINTEGER *) DiagInfoPtr, NULL,
|
|
0, NULL, 0);
|
|
break;
|
|
case SQL_DIAG_NUMBER:
|
|
rtnctype = SQL_C_LONG;
|
|
ret = PGAPI_ConnectError(Handle, RecNumber,
|
|
NULL, NULL, NULL,
|
|
0, NULL, 0);
|
|
if (SQL_SUCCEEDED(ret))
|
|
{
|
|
*((SQLINTEGER *) DiagInfoPtr) = 1;
|
|
}
|
|
break;
|
|
case SQL_DIAG_SQLSTATE:
|
|
rtnlen = 5;
|
|
ret = PGAPI_ConnectError(Handle, RecNumber,
|
|
DiagInfoPtr, NULL, NULL,
|
|
0, NULL, 0);
|
|
if (SQL_SUCCESS_WITH_INFO == ret)
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_RETURNCODE: /* driver manager returns */
|
|
break;
|
|
case SQL_DIAG_CURSOR_ROW_COUNT:
|
|
case SQL_DIAG_ROW_COUNT:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
|
|
/* options for statement type only */
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_HANDLE_STMT:
|
|
conn = (ConnectionClass *) SC_get_conn(((StatementClass *) Handle));
|
|
switch (DiagIdentifier)
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
rtnlen = 0;
|
|
if (DiagInfoPtr && BufferLength > rtnlen)
|
|
{
|
|
ret = SQL_SUCCESS;
|
|
*((char *) DiagInfoPtr) = '\0';
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_SERVER_NAME:
|
|
rtnlen = strlen(CC_get_DSN(conn));
|
|
if (DiagInfoPtr)
|
|
{
|
|
strncpy_null(DiagInfoPtr, CC_get_DSN(conn), BufferLength);
|
|
ret = (BufferLength > rtnlen ? SQL_SUCCESS : SQL_SUCCESS_WITH_INFO);
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
ret = PGAPI_StmtError(Handle, RecNumber,
|
|
NULL, NULL, DiagInfoPtr,
|
|
BufferLength, StringLengthPtr, 0);
|
|
break;
|
|
case SQL_DIAG_NATIVE:
|
|
rtnctype = SQL_C_LONG;
|
|
ret = PGAPI_StmtError(Handle, RecNumber,
|
|
NULL, (SQLINTEGER *) DiagInfoPtr, NULL,
|
|
0, NULL, 0);
|
|
break;
|
|
case SQL_DIAG_NUMBER:
|
|
rtnctype = SQL_C_LONG;
|
|
*((SQLINTEGER *) DiagInfoPtr) = 0;
|
|
ret = SQL_NO_DATA_FOUND;
|
|
stmt = (StatementClass *) Handle;
|
|
rtn = PGAPI_StmtError(Handle, -1, NULL,
|
|
NULL, NULL, 0, &pcbErrm, 0);
|
|
switch (rtn)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
ret = SQL_SUCCESS;
|
|
if (pcbErrm > 0 && stmt->pgerror)
|
|
|
|
*((SQLINTEGER *) DiagInfoPtr) = (pcbErrm - 1)/ stmt->pgerror->recsize + 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DIAG_SQLSTATE:
|
|
rtnlen = 5;
|
|
ret = PGAPI_StmtError(Handle, RecNumber,
|
|
DiagInfoPtr, NULL, NULL,
|
|
0, NULL, 0);
|
|
if (SQL_SUCCESS_WITH_INFO == ret)
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_CURSOR_ROW_COUNT:
|
|
rtnctype = SQL_C_LONG;
|
|
stmt = (StatementClass *) Handle;
|
|
rc = -1;
|
|
if (stmt->status == STMT_FINISHED)
|
|
{
|
|
QResultClass *res = SC_get_Curres(stmt);
|
|
|
|
if (stmt->proc_return > 0)
|
|
rc = 0;
|
|
else if (res && QR_NumResultCols(res) > 0 && !SC_is_fetchcursor(stmt))
|
|
rc = QR_get_num_total_tuples(res) - res->dl_count;
|
|
}
|
|
*((SQLLEN *) DiagInfoPtr) = rc;
|
|
MYLOG(DETAIL_LOG_LEVEL, "rc=" FORMAT_LEN "\n", rc);
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_ROW_COUNT:
|
|
rtnctype = SQL_C_LONG;
|
|
stmt = (StatementClass *) Handle;
|
|
*((SQLLEN *) DiagInfoPtr) = stmt->diag_row_count;
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_ROW_NUMBER:
|
|
rtnctype = SQL_C_LONG;
|
|
*((SQLLEN *) DiagInfoPtr) = SQL_ROW_NUMBER_UNKNOWN;
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_COLUMN_NUMBER:
|
|
rtnctype = SQL_C_LONG;
|
|
*((SQLINTEGER *) DiagInfoPtr) = SQL_COLUMN_NUMBER_UNKNOWN;
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_RETURNCODE: /* driver manager returns */
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_HANDLE_DESC:
|
|
conn = DC_get_conn(((DescriptorClass *) Handle));
|
|
switch (DiagIdentifier)
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
rtnlen = 0;
|
|
if (DiagInfoPtr && BufferLength > rtnlen)
|
|
{
|
|
ret = SQL_SUCCESS;
|
|
*((char *) DiagInfoPtr) = '\0';
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_SERVER_NAME:
|
|
rtnlen = strlen(CC_get_DSN(conn));
|
|
if (DiagInfoPtr)
|
|
{
|
|
strncpy_null(DiagInfoPtr, CC_get_DSN(conn), BufferLength);
|
|
ret = (BufferLength > rtnlen ? SQL_SUCCESS : SQL_SUCCESS_WITH_INFO);
|
|
}
|
|
else
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
break;
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
case SQL_DIAG_NATIVE:
|
|
case SQL_DIAG_NUMBER:
|
|
break;
|
|
case SQL_DIAG_SQLSTATE:
|
|
rtnlen = 5;
|
|
ret = PGAPI_DescError(Handle, RecNumber,
|
|
DiagInfoPtr, NULL, NULL,
|
|
0, NULL, 0);
|
|
if (SQL_SUCCESS_WITH_INFO == ret)
|
|
ret = SQL_SUCCESS;
|
|
break;
|
|
case SQL_DIAG_RETURNCODE: /* driver manager returns */
|
|
break;
|
|
case SQL_DIAG_CURSOR_ROW_COUNT:
|
|
case SQL_DIAG_ROW_COUNT:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION:
|
|
case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
|
|
rtnctype = SQL_C_LONG;
|
|
/* options for statement type only */
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
ret = SQL_ERROR;
|
|
}
|
|
if (SQL_C_LONG == rtnctype)
|
|
{
|
|
if (SQL_SUCCESS_WITH_INFO == ret)
|
|
ret = SQL_SUCCESS;
|
|
if (StringLengthPtr)
|
|
*StringLengthPtr = sizeof(SQLINTEGER);
|
|
}
|
|
else if (rtnlen >= 0)
|
|
{
|
|
if (rtnlen >= BufferLength)
|
|
{
|
|
if (SQL_SUCCESS == ret)
|
|
ret = SQL_SUCCESS_WITH_INFO;
|
|
if (BufferLength > 0)
|
|
((char *) DiagInfoPtr) [BufferLength - 1] = '\0';
|
|
}
|
|
if (StringLengthPtr)
|
|
*StringLengthPtr = (SQLSMALLINT) rtnlen;
|
|
}
|
|
MYLOG(0, "leaving %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
/* SQLGetConnectOption -> SQLGetconnectAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_GetConnectAttr(HDBC ConnectionHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER BufferLength, SQLINTEGER *StringLength)
|
|
{
|
|
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER len = 4;
|
|
|
|
MYLOG(0, "entering %d\n", Attribute);
|
|
switch (Attribute)
|
|
{
|
|
case SQL_ATTR_ASYNC_ENABLE:
|
|
*((SQLINTEGER *) Value) = SQL_ASYNC_ENABLE_OFF;
|
|
break;
|
|
case SQL_ATTR_AUTO_IPD:
|
|
*((SQLINTEGER *) Value) = SQL_FALSE;
|
|
break;
|
|
case SQL_ATTR_CONNECTION_DEAD:
|
|
*((SQLUINTEGER *) Value) = CC_not_connected(conn);
|
|
break;
|
|
case SQL_ATTR_CONNECTION_TIMEOUT:
|
|
*((SQLUINTEGER *) Value) = 0;
|
|
break;
|
|
case SQL_ATTR_METADATA_ID:
|
|
*((SQLUINTEGER *) Value) = conn->stmtOptions.metadata_id;
|
|
break;
|
|
case SQL_ATTR_PGOPT_DEBUG:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.debug;
|
|
break;
|
|
case SQL_ATTR_PGOPT_COMMLOG:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.commlog;
|
|
break;
|
|
case SQL_ATTR_PGOPT_PARSE:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.parse;
|
|
break;
|
|
case SQL_ATTR_PGOPT_USE_DECLAREFETCH:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.use_declarefetch;
|
|
break;
|
|
case SQL_ATTR_PGOPT_SERVER_SIDE_PREPARE:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.use_server_side_prepare;
|
|
break;
|
|
case SQL_ATTR_PGOPT_FETCH:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.fetch_max;
|
|
break;
|
|
case SQL_ATTR_PGOPT_UNKNOWNSIZES:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.unknown_sizes;
|
|
break;
|
|
case SQL_ATTR_PGOPT_TEXTASLONGVARCHAR:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.text_as_longvarchar;
|
|
break;
|
|
case SQL_ATTR_PGOPT_UNKNOWNSASLONGVARCHAR:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.unknowns_as_longvarchar;
|
|
break;
|
|
case SQL_ATTR_PGOPT_BOOLSASCHAR:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.bools_as_char;
|
|
break;
|
|
case SQL_ATTR_PGOPT_MAXVARCHARSIZE:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.max_varchar_size;
|
|
break;
|
|
case SQL_ATTR_PGOPT_MAXLONGVARCHARSIZE:
|
|
*((SQLINTEGER *) Value) = conn->connInfo.drivers.max_longvarchar_size;
|
|
break;
|
|
case SQL_ATTR_PGOPT_MSJET:
|
|
*((SQLINTEGER *) Value) = conn->ms_jet;
|
|
break;
|
|
default:
|
|
ret = PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value, &len, BufferLength);
|
|
}
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static SQLHDESC
|
|
descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
|
|
{
|
|
StatementClass *stmt = (StatementClass *) StatementHandle;
|
|
|
|
switch (descType)
|
|
{
|
|
case SQL_ATTR_APP_ROW_DESC: /* 10010 */
|
|
return (HSTMT) stmt->ard;
|
|
case SQL_ATTR_APP_PARAM_DESC: /* 10011 */
|
|
return (HSTMT) stmt->apd;
|
|
case SQL_ATTR_IMP_ROW_DESC: /* 10012 */
|
|
return (HSTMT) stmt->ird;
|
|
case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */
|
|
return (HSTMT) stmt->ipd;
|
|
}
|
|
return (HSTMT) 0;
|
|
}
|
|
|
|
static void column_bindings_set(ARDFields *opts, int cols, BOOL maxset)
|
|
{
|
|
int i;
|
|
|
|
if (cols == opts->allocated)
|
|
return;
|
|
if (cols > opts->allocated)
|
|
{
|
|
extend_column_bindings(opts, cols);
|
|
return;
|
|
}
|
|
if (maxset) return;
|
|
|
|
for (i = opts->allocated; i > cols; i--)
|
|
reset_a_column_binding(opts, i);
|
|
opts->allocated = cols;
|
|
if (0 == cols)
|
|
{
|
|
free(opts->bindings);
|
|
opts->bindings = NULL;
|
|
}
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
ARDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
ARDFields *opts = &(desc->ardf);
|
|
SQLSMALLINT row_idx;
|
|
BOOL unbind = TRUE;
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
opts->size_of_rowset = CAST_UPTR(SQLULEN, Value);
|
|
return ret;
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
opts->row_operation_ptr = Value;
|
|
return ret;
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
opts->row_offset_ptr = Value;
|
|
return ret;
|
|
case SQL_DESC_BIND_TYPE:
|
|
opts->bind_size = CAST_UPTR(SQLUINTEGER, Value);
|
|
return ret;
|
|
case SQL_DESC_COUNT:
|
|
column_bindings_set(opts, CAST_PTR(SQLSMALLINT, Value), FALSE);
|
|
return ret;
|
|
|
|
case SQL_DESC_TYPE:
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
break;
|
|
}
|
|
if (RecNumber < 0 || RecNumber > opts->allocated)
|
|
{
|
|
DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR, "invalid column number");
|
|
return SQL_ERROR;
|
|
}
|
|
if (0 == RecNumber) /* bookmark column */
|
|
{
|
|
BindInfoClass *bookmark = ARD_AllocBookmark(opts);
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_DATA_PTR:
|
|
bookmark->buffer = Value;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
bookmark->indicator = Value;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
bookmark->used = Value;
|
|
break;
|
|
default:
|
|
DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR, "invalid column number");
|
|
ret = SQL_ERROR;
|
|
}
|
|
return ret;
|
|
}
|
|
row_idx = RecNumber - 1;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_TYPE:
|
|
opts->bindings[row_idx].returntype = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
switch (opts->bindings[row_idx].returntype)
|
|
{
|
|
case SQL_DATETIME:
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
switch ((LONG_PTR) Value)
|
|
{
|
|
case SQL_CODE_DATE:
|
|
opts->bindings[row_idx].returntype = SQL_C_TYPE_DATE;
|
|
break;
|
|
case SQL_CODE_TIME:
|
|
opts->bindings[row_idx].returntype = SQL_C_TYPE_TIME;
|
|
break;
|
|
case SQL_CODE_TIMESTAMP:
|
|
opts->bindings[row_idx].returntype = SQL_C_TYPE_TIMESTAMP;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
opts->bindings[row_idx].returntype = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
unbind = FALSE;
|
|
opts->bindings[row_idx].buffer = Value;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
unbind = FALSE;
|
|
opts->bindings[row_idx].indicator = Value;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
unbind = FALSE;
|
|
opts->bindings[row_idx].used = Value;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
opts->bindings[row_idx].buflen = CAST_PTR(SQLLEN, Value);
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
opts->bindings[row_idx].precision = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
opts->bindings[row_idx].scale = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
if (unbind)
|
|
opts->bindings[row_idx].buffer = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static void parameter_bindings_set(APDFields *opts, int params, BOOL maxset)
|
|
{
|
|
int i;
|
|
|
|
if (params == opts->allocated)
|
|
return;
|
|
if (params > opts->allocated)
|
|
{
|
|
extend_parameter_bindings(opts, params);
|
|
return;
|
|
}
|
|
if (maxset) return;
|
|
|
|
for (i = opts->allocated; i > params; i--)
|
|
reset_a_parameter_binding(opts, i);
|
|
opts->allocated = params;
|
|
if (0 == params)
|
|
{
|
|
free(opts->parameters);
|
|
opts->parameters = NULL;
|
|
}
|
|
}
|
|
|
|
static void parameter_ibindings_set(IPDFields *opts, int params, BOOL maxset)
|
|
{
|
|
int i;
|
|
|
|
if (params == opts->allocated)
|
|
return;
|
|
if (params > opts->allocated)
|
|
{
|
|
extend_iparameter_bindings(opts, params);
|
|
return;
|
|
}
|
|
if (maxset) return;
|
|
|
|
for (i = opts->allocated; i > params; i--)
|
|
reset_a_iparameter_binding(opts, i);
|
|
opts->allocated = params;
|
|
if (0 == params)
|
|
{
|
|
free(opts->parameters);
|
|
opts->parameters = NULL;
|
|
}
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
APDFields *opts = &(desc->apdf);
|
|
SQLSMALLINT para_idx;
|
|
BOOL unbind = TRUE;
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
opts->paramset_size = CAST_UPTR(SQLUINTEGER, Value);
|
|
return ret;
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
opts->param_operation_ptr = Value;
|
|
return ret;
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
opts->param_offset_ptr = Value;
|
|
return ret;
|
|
case SQL_DESC_BIND_TYPE:
|
|
opts->param_bind_type = CAST_UPTR(SQLUINTEGER, Value);
|
|
return ret;
|
|
case SQL_DESC_COUNT:
|
|
parameter_bindings_set(opts, CAST_PTR(SQLSMALLINT, Value), FALSE);
|
|
return ret;
|
|
|
|
case SQL_DESC_TYPE:
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
break;
|
|
}
|
|
if (RecNumber <=0)
|
|
{
|
|
MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
|
|
DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
|
|
"bad parameter number");
|
|
return SQL_ERROR;
|
|
}
|
|
if (RecNumber > opts->allocated)
|
|
{
|
|
MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
}
|
|
para_idx = RecNumber - 1;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_TYPE:
|
|
opts->parameters[para_idx].CType = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
switch (opts->parameters[para_idx].CType)
|
|
{
|
|
case SQL_DATETIME:
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
switch ((LONG_PTR) Value)
|
|
{
|
|
case SQL_CODE_DATE:
|
|
opts->parameters[para_idx].CType = SQL_C_TYPE_DATE;
|
|
break;
|
|
case SQL_CODE_TIME:
|
|
opts->parameters[para_idx].CType = SQL_C_TYPE_TIME;
|
|
break;
|
|
case SQL_CODE_TIMESTAMP:
|
|
opts->parameters[para_idx].CType = SQL_C_TYPE_TIMESTAMP;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
opts->parameters[para_idx].CType = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
unbind = FALSE;
|
|
opts->parameters[para_idx].buffer = Value;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
unbind = FALSE;
|
|
opts->parameters[para_idx].indicator = Value;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
opts->parameters[para_idx].buflen = CAST_PTR(Int4, Value);
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
unbind = FALSE;
|
|
opts->parameters[para_idx].used = Value;
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
opts->parameters[para_idx].precision = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
opts->parameters[para_idx].scale = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invaid descriptor identifier");
|
|
}
|
|
if (unbind)
|
|
opts->parameters[para_idx].buffer = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IRDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
IRDFields *opts = &(desc->irdf);
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
opts->rowStatusArray = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
opts->rowsFetched = (SQLULEN *) Value;
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
case SQL_DESC_COUNT: /* read-only */
|
|
case SQL_DESC_AUTO_UNIQUE_VALUE: /* read-only */
|
|
case SQL_DESC_BASE_COLUMN_NAME: /* read-only */
|
|
case SQL_DESC_BASE_TABLE_NAME: /* read-only */
|
|
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
|
case SQL_DESC_CATALOG_NAME: /* read-only */
|
|
case SQL_DESC_CONCISE_TYPE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
|
|
case SQL_DESC_DISPLAY_SIZE: /* read-only */
|
|
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
|
|
case SQL_DESC_LABEL: /* read-only */
|
|
case SQL_DESC_LENGTH: /* read-only */
|
|
case SQL_DESC_LITERAL_PREFIX: /* read-only */
|
|
case SQL_DESC_LITERAL_SUFFIX: /* read-only */
|
|
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_NAME: /* read-only */
|
|
case SQL_DESC_NULLABLE: /* read-only */
|
|
case SQL_DESC_NUM_PREC_RADIX: /* read-only */
|
|
case SQL_DESC_OCTET_LENGTH: /* read-only */
|
|
case SQL_DESC_PRECISION: /* read-only */
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
case SQL_DESC_SCALE: /* read-only */
|
|
case SQL_DESC_SCHEMA_NAME: /* read-only */
|
|
case SQL_DESC_SEARCHABLE: /* read-only */
|
|
case SQL_DESC_TABLE_NAME: /* read-only */
|
|
case SQL_DESC_TYPE: /* read-only */
|
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_UNNAMED: /* read-only */
|
|
case SQL_DESC_UNSIGNED: /* read-only */
|
|
case SQL_DESC_UPDATABLE: /* read-only */
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IPDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
IPDFields *ipdopts = &(desc->ipdf);
|
|
SQLSMALLINT para_idx;
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
ipdopts->param_status_ptr = (SQLUSMALLINT *) Value;
|
|
return ret;
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
ipdopts->param_processed_ptr = (SQLULEN *) Value;
|
|
return ret;
|
|
case SQL_DESC_COUNT:
|
|
parameter_ibindings_set(ipdopts, CAST_PTR(SQLSMALLINT, Value), FALSE);
|
|
return ret;
|
|
case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
|
|
if (SQL_UNNAMED != CAST_PTR(SQLSMALLINT, Value))
|
|
{
|
|
ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
return ret;
|
|
}
|
|
case SQL_DESC_NAME:
|
|
case SQL_DESC_TYPE:
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
parameter_ibindings_set(ipdopts, RecNumber, TRUE);
|
|
break;
|
|
}
|
|
if (RecNumber <= 0 || RecNumber > ipdopts->allocated)
|
|
{
|
|
MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, ipdopts->allocated);
|
|
DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
|
|
"bad parameter number");
|
|
return SQL_ERROR;
|
|
}
|
|
para_idx = RecNumber - 1;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_TYPE:
|
|
if (ipdopts->parameters[para_idx].SQLType != CAST_PTR(SQLSMALLINT, Value))
|
|
{
|
|
reset_a_iparameter_binding(ipdopts, RecNumber);
|
|
ipdopts->parameters[para_idx].SQLType = CAST_PTR(SQLSMALLINT, Value);
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
switch (ipdopts->parameters[para_idx].SQLType)
|
|
{
|
|
case SQL_DATETIME:
|
|
case SQL_TYPE_DATE:
|
|
case SQL_TYPE_TIME:
|
|
case SQL_TYPE_TIMESTAMP:
|
|
switch ((LONG_PTR) Value)
|
|
{
|
|
case SQL_CODE_DATE:
|
|
ipdopts->parameters[para_idx].SQLType = SQL_TYPE_DATE;
|
|
break;
|
|
case SQL_CODE_TIME:
|
|
ipdopts->parameters[para_idx].SQLType = SQL_TYPE_TIME;
|
|
break;
|
|
case SQL_CODE_TIMESTAMP:
|
|
ipdopts->parameters[para_idx].SQLType = SQL_TYPE_TIMESTAMP;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
ipdopts->parameters[para_idx].SQLType = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_NAME:
|
|
if (Value)
|
|
STR_TO_NAME(ipdopts->parameters[para_idx].paramName, Value);
|
|
else
|
|
NULL_THE_NAME(ipdopts->parameters[para_idx].paramName);
|
|
break;
|
|
case SQL_DESC_PARAMETER_TYPE:
|
|
ipdopts->parameters[para_idx].paramType = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
ipdopts->parameters[para_idx].decimal_digits = CAST_PTR(SQLSMALLINT, Value);
|
|
break;
|
|
case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
|
|
if (SQL_UNNAMED != CAST_PTR(SQLSMALLINT, Value))
|
|
{
|
|
ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
else
|
|
NULL_THE_NAME(ipdopts->parameters[para_idx].paramName);
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_NULLABLE: /* read-only */
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
case SQL_DESC_PRECISION:
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_UNSIGNED: /* read-only */
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
static RETCODE SQL_API
|
|
ARDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLLEN ival = 0;
|
|
SQLINTEGER len, rettype = 0;
|
|
PTR ptr = NULL;
|
|
const ARDFields *opts = &(desc->ardf);
|
|
SQLSMALLINT row_idx;
|
|
|
|
len = sizeof(SQLINTEGER);
|
|
if (0 == RecNumber) /* bookmark */
|
|
{
|
|
BindInfoClass *bookmark = opts->bookmark;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_DATA_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = bookmark ? bookmark->buffer : NULL;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = bookmark ? bookmark->indicator : NULL;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = bookmark ? bookmark->used : NULL;
|
|
break;
|
|
}
|
|
if (ptr)
|
|
{
|
|
*((void **) Value) = ptr;
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
}
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
case SQL_DESC_BIND_TYPE:
|
|
case SQL_DESC_COUNT:
|
|
break;
|
|
default:
|
|
if (RecNumber <= 0 || RecNumber > opts->allocated)
|
|
{
|
|
DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR,
|
|
"invalid column number");
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
row_idx = RecNumber - 1;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
ival = opts->size_of_rowset;
|
|
break;
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->row_operation_ptr;
|
|
break;
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->row_offset_ptr;
|
|
break;
|
|
case SQL_DESC_BIND_TYPE:
|
|
ival = opts->bind_size;
|
|
break;
|
|
case SQL_DESC_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (opts->bindings[row_idx].returntype)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
ival = SQL_DATETIME;
|
|
break;
|
|
default:
|
|
ival = opts->bindings[row_idx].returntype;
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (opts->bindings[row_idx].returntype)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
ival = SQL_CODE_DATE;
|
|
break;
|
|
case SQL_C_TYPE_TIME:
|
|
ival = SQL_CODE_TIME;
|
|
break;
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
ival = SQL_CODE_TIMESTAMP;
|
|
break;
|
|
default:
|
|
ival = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->bindings[row_idx].returntype;
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->bindings[row_idx].buffer;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->bindings[row_idx].indicator;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->bindings[row_idx].used;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->allocated;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
ival = opts->bindings[row_idx].buflen;
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
rettype = SQL_IS_SMALLINT;
|
|
if (DC_get_embedded(desc))
|
|
ival = SQL_DESC_ALLOC_AUTO;
|
|
else
|
|
ival = SQL_DESC_ALLOC_USER;
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->bindings[row_idx].precision;
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->bindings[row_idx].scale;
|
|
break;
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
ival = 10;
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
default:
|
|
ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = sizeof(SQLINTEGER);
|
|
*((SQLINTEGER *) Value) = (SQLINTEGER) ival;
|
|
break;
|
|
case SQL_IS_SMALLINT:
|
|
len = sizeof(SQLSMALLINT);
|
|
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = sizeof(SQLPOINTER);
|
|
*((void **) Value) = ptr;
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLLEN ival = 0;
|
|
SQLINTEGER len, rettype = 0;
|
|
PTR ptr = NULL;
|
|
const APDFields *opts = (const APDFields *) &(desc->apdf);
|
|
SQLSMALLINT para_idx;
|
|
|
|
len = sizeof(SQLINTEGER);
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
case SQL_DESC_BIND_TYPE:
|
|
case SQL_DESC_COUNT:
|
|
break;
|
|
default:if (RecNumber <= 0 || RecNumber > opts->allocated)
|
|
{
|
|
MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
|
|
DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
|
|
"bad parameter number");
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
para_idx = RecNumber - 1;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
rettype = SQL_IS_LEN;
|
|
ival = opts->paramset_size;
|
|
break;
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->param_operation_ptr;
|
|
break;
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->param_offset_ptr;
|
|
break;
|
|
case SQL_DESC_BIND_TYPE:
|
|
ival = opts->param_bind_type;
|
|
break;
|
|
|
|
case SQL_DESC_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (opts->parameters[para_idx].CType)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
ival = SQL_DATETIME;
|
|
break;
|
|
default:
|
|
ival = opts->parameters[para_idx].CType;
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (opts->parameters[para_idx].CType)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
ival = SQL_CODE_DATE;
|
|
break;
|
|
case SQL_C_TYPE_TIME:
|
|
ival = SQL_CODE_TIME;
|
|
break;
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
ival = SQL_CODE_TIMESTAMP;
|
|
break;
|
|
default:
|
|
ival = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->parameters[para_idx].CType;
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->parameters[para_idx].buffer;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->parameters[para_idx].indicator;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
ival = opts->parameters[para_idx].buflen;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->parameters[para_idx].used;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
ret = SQL_IS_SMALLINT;
|
|
ival = opts->allocated;
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
rettype = SQL_IS_SMALLINT;
|
|
if (DC_get_embedded(desc))
|
|
ival = SQL_DESC_ALLOC_AUTO;
|
|
else
|
|
ival = SQL_DESC_ALLOC_USER;
|
|
break;
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
ival = 10;
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->parameters[para_idx].precision;
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = opts->parameters[para_idx].scale;
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifer");
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case SQL_IS_LEN:
|
|
len = sizeof(SQLLEN);
|
|
*((SQLLEN *) Value) = ival;
|
|
break;
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = sizeof(SQLINTEGER);
|
|
*((SQLINTEGER *) Value) = (SQLINTEGER) ival;
|
|
break;
|
|
case SQL_IS_SMALLINT:
|
|
len = sizeof(SQLSMALLINT);
|
|
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = sizeof(SQLPOINTER);
|
|
*((void **) Value) = ptr;
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IRDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLLEN ival = 0;
|
|
SQLINTEGER len = 0, rettype = 0;
|
|
PTR ptr = NULL;
|
|
BOOL bCallColAtt = FALSE;
|
|
const IRDFields *opts = &(desc->irdf);
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->rowStatusArray;
|
|
break;
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->rowsFetched;
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = SQL_DESC_ALLOC_AUTO;
|
|
break;
|
|
case SQL_DESC_COUNT: /* read-only */
|
|
case SQL_DESC_AUTO_UNIQUE_VALUE: /* read-only */
|
|
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
|
case SQL_DESC_CONCISE_TYPE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
|
|
case SQL_DESC_DISPLAY_SIZE: /* read-only */
|
|
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
|
|
case SQL_DESC_LENGTH: /* read-only */
|
|
case SQL_DESC_NULLABLE: /* read-only */
|
|
case SQL_DESC_NUM_PREC_RADIX: /* read-only */
|
|
case SQL_DESC_OCTET_LENGTH: /* read-only */
|
|
case SQL_DESC_PRECISION: /* read-only */
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
case SQL_DESC_SCALE: /* read-only */
|
|
case SQL_DESC_SEARCHABLE: /* read-only */
|
|
case SQL_DESC_TYPE: /* read-only */
|
|
case SQL_DESC_UNNAMED: /* read-only */
|
|
case SQL_DESC_UNSIGNED: /* read-only */
|
|
case SQL_DESC_UPDATABLE: /* read-only */
|
|
bCallColAtt = TRUE;
|
|
break;
|
|
case SQL_DESC_BASE_COLUMN_NAME: /* read-only */
|
|
case SQL_DESC_BASE_TABLE_NAME: /* read-only */
|
|
case SQL_DESC_CATALOG_NAME: /* read-only */
|
|
case SQL_DESC_LABEL: /* read-only */
|
|
case SQL_DESC_LITERAL_PREFIX: /* read-only */
|
|
case SQL_DESC_LITERAL_SUFFIX: /* read-only */
|
|
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_NAME: /* read-only */
|
|
case SQL_DESC_SCHEMA_NAME: /* read-only */
|
|
case SQL_DESC_TABLE_NAME: /* read-only */
|
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
rettype = SQL_NTS;
|
|
bCallColAtt = TRUE;
|
|
break;
|
|
default:
|
|
ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
if (bCallColAtt)
|
|
{
|
|
SQLSMALLINT pcbL;
|
|
StatementClass *stmt;
|
|
|
|
stmt = opts->stmt;
|
|
ret = PGAPI_ColAttributes(stmt, RecNumber,
|
|
FieldIdentifier, Value, (SQLSMALLINT) BufferLength,
|
|
&pcbL, &ival);
|
|
len = pcbL;
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = sizeof(SQLINTEGER);
|
|
*((SQLINTEGER *) Value) = (SQLINTEGER) ival;
|
|
break;
|
|
case SQL_IS_UINTEGER:
|
|
len = sizeof(SQLUINTEGER);
|
|
*((SQLUINTEGER *) Value) = (SQLUINTEGER) ival;
|
|
break;
|
|
case SQL_IS_SMALLINT:
|
|
len = sizeof(SQLSMALLINT);
|
|
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = sizeof(SQLPOINTER);
|
|
*((void **) Value) = ptr;
|
|
break;
|
|
case SQL_NTS:
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER ival = 0, len = 0, rettype = 0;
|
|
PTR ptr = NULL;
|
|
const IPDFields *ipdopts = (const IPDFields *) &(desc->ipdf);
|
|
SQLSMALLINT para_idx;
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
case SQL_DESC_COUNT:
|
|
break;
|
|
default:if (RecNumber <= 0 || RecNumber > ipdopts->allocated)
|
|
{
|
|
MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, ipdopts->allocated);
|
|
DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
|
|
"bad parameter number");
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
para_idx = RecNumber - 1;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = ipdopts->param_status_ptr;
|
|
break;
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = ipdopts->param_processed_ptr;
|
|
break;
|
|
case SQL_DESC_UNNAMED:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = NAME_IS_NULL(ipdopts->parameters[para_idx].paramName) ? SQL_UNNAMED : SQL_NAMED;
|
|
break;
|
|
case SQL_DESC_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (ipdopts->parameters[para_idx].SQLType)
|
|
{
|
|
case SQL_TYPE_DATE:
|
|
case SQL_TYPE_TIME:
|
|
case SQL_TYPE_TIMESTAMP:
|
|
ival = SQL_DATETIME;
|
|
break;
|
|
default:
|
|
ival = ipdopts->parameters[para_idx].SQLType;
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (ipdopts->parameters[para_idx].SQLType)
|
|
{
|
|
case SQL_TYPE_DATE:
|
|
ival = SQL_CODE_DATE;
|
|
break;
|
|
case SQL_TYPE_TIME:
|
|
ival = SQL_CODE_TIME;
|
|
break;
|
|
case SQL_TYPE_TIMESTAMP:
|
|
ival = SQL_CODE_TIMESTAMP;
|
|
break;
|
|
default:
|
|
ival = 0;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = ipdopts->parameters[para_idx].SQLType;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = ipdopts->allocated;
|
|
break;
|
|
case SQL_DESC_PARAMETER_TYPE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = ipdopts->parameters[para_idx].paramType;
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (ipdopts->parameters[para_idx].SQLType)
|
|
{
|
|
case SQL_TYPE_DATE:
|
|
case SQL_TYPE_TIME:
|
|
case SQL_TYPE_TIMESTAMP:
|
|
case SQL_DATETIME:
|
|
ival = ipdopts->parameters[para_idx].decimal_digits;
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
rettype = SQL_IS_SMALLINT;
|
|
switch (ipdopts->parameters[para_idx].SQLType)
|
|
{
|
|
case SQL_NUMERIC:
|
|
ival = ipdopts->parameters[para_idx].decimal_digits;
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
rettype = SQL_IS_SMALLINT;
|
|
ival = SQL_DESC_ALLOC_AUTO;
|
|
break;
|
|
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_NAME:
|
|
case SQL_DESC_NULLABLE: /* read-only */
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_UNSIGNED: /* read-only */
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER,
|
|
"invalid descriptor identifier");
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = sizeof(SQLINTEGER);
|
|
*((SQLINTEGER *) Value) = ival;
|
|
break;
|
|
case SQL_IS_SMALLINT:
|
|
len = sizeof(SQLSMALLINT);
|
|
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = sizeof(SQLPOINTER);
|
|
*((void **)Value) = ptr;
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
/* SQLGetStmtOption -> SQLGetStmtAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_GetStmtAttr(HSTMT StatementHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER BufferLength, SQLINTEGER *StringLength)
|
|
{
|
|
CSTR func = "PGAPI_GetStmtAttr";
|
|
StatementClass *stmt = (StatementClass *) StatementHandle;
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER len = 0;
|
|
|
|
MYLOG(0, "entering Handle=%p %d\n", StatementHandle, Attribute);
|
|
switch (Attribute)
|
|
{
|
|
case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */
|
|
*((void **) Value) = stmt->options.bookmark_ptr;
|
|
len = sizeof(SQLPOINTER);
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
|
|
*((SQLULEN **) Value) = SC_get_APDF(stmt)->param_offset_ptr;
|
|
len = sizeof(SQLPOINTER);
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
|
|
*((SQLUINTEGER *) Value) = SC_get_APDF(stmt)->param_bind_type;
|
|
len = sizeof(SQLUINTEGER);
|
|
break;
|
|
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_APDF(stmt)->param_operation_ptr;
|
|
len = sizeof(SQLPOINTER);
|
|
break;
|
|
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_IPDF(stmt)->param_status_ptr;
|
|
len = sizeof(SQLPOINTER);
|
|
break;
|
|
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
|
|
*((SQLULEN **) Value) = SC_get_IPDF(stmt)->param_processed_ptr;
|
|
len = sizeof(SQLPOINTER);
|
|
break;
|
|
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
|
|
*((SQLULEN *) Value) = SC_get_APDF(stmt)->paramset_size;
|
|
len = sizeof(SQLUINTEGER);
|
|
break;
|
|
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
|
|
*((SQLULEN **) Value) = SC_get_ARDF(stmt)->row_offset_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_ARDF(stmt)->row_operation_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_IRDF(stmt)->rowStatusArray;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
|
|
*((SQLULEN **) Value) = SC_get_IRDF(stmt)->rowsFetched;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
|
|
*((SQLULEN *) Value) = SC_get_ARDF(stmt)->size_of_rowset;
|
|
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_CURSOR_SCROLLABLE: /* -1 */
|
|
len = 4;
|
|
if (SQL_CURSOR_FORWARD_ONLY == stmt->options.cursor_type)
|
|
*((SQLUINTEGER *) Value) = SQL_NONSCROLLABLE;
|
|
else
|
|
*((SQLUINTEGER *) Value) = SQL_SCROLLABLE;
|
|
break;
|
|
case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */
|
|
len = 4;
|
|
if (SQL_CONCUR_READ_ONLY == stmt->options.scroll_concurrency)
|
|
*((SQLUINTEGER *) Value) = SQL_INSENSITIVE;
|
|
else
|
|
*((SQLUINTEGER *) Value) = SQL_UNSPECIFIED;
|
|
break;
|
|
case SQL_ATTR_METADATA_ID: /* 10014 */
|
|
*((SQLUINTEGER *) Value) = stmt->options.metadata_id;
|
|
break;
|
|
case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */
|
|
*((SQLUINTEGER *) Value) = SQL_FALSE;
|
|
break;
|
|
case SQL_ATTR_AUTO_IPD: /* 10001 */
|
|
/* case SQL_ATTR_ROW_BIND_TYPE: ** == SQL_BIND_TYPE(ODBC2.0) */
|
|
SC_set_error(stmt, DESC_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Get)", func);
|
|
return SQL_ERROR;
|
|
default:
|
|
ret = PGAPI_GetStmtOption(StatementHandle, (SQLSMALLINT) Attribute, Value, &len, BufferLength);
|
|
}
|
|
if (ret == SQL_SUCCESS && StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
/* SQLSetConnectOption -> SQLSetConnectAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_SetConnectAttr(HDBC ConnectionHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER StringLength)
|
|
{
|
|
CSTR func = "PGAPI_SetConnectAttr";
|
|
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
|
|
RETCODE ret = SQL_SUCCESS;
|
|
BOOL unsupported = FALSE;
|
|
int newValue;
|
|
|
|
MYLOG(0, "entering for %p: %d %p\n", ConnectionHandle, Attribute, Value);
|
|
switch (Attribute)
|
|
{
|
|
case SQL_ATTR_METADATA_ID:
|
|
conn->stmtOptions.metadata_id = CAST_UPTR(SQLUINTEGER, Value);
|
|
break;
|
|
case SQL_ATTR_ANSI_APP:
|
|
if (SQL_AA_FALSE != CAST_PTR(SQLINTEGER, Value))
|
|
{
|
|
MYLOG(0, "the application is ansi\n");
|
|
if (CC_is_in_unicode_driver(conn)) /* the driver is unicode */
|
|
CC_set_in_ansi_app(conn); /* but the app is ansi */
|
|
}
|
|
else
|
|
{
|
|
MYLOG(0, "the application is unicode\n");
|
|
}
|
|
return SQL_SUCCESS;
|
|
case SQL_ATTR_ENLIST_IN_DTC:
|
|
#ifdef WIN32
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
MYLOG(0, "SQL_ATTR_ENLIST_IN_DTC %p request received\n", Value);
|
|
if (conn->connInfo.xa_opt != 0)
|
|
{
|
|
/*
|
|
* When a new global transaction is about
|
|
* to begin, isolate the existent global
|
|
* transaction.
|
|
*/
|
|
if (NULL != Value && CC_is_in_global_trans(conn))
|
|
CALL_IsolateDtcConn(conn, TRUE);
|
|
return CALL_EnlistInDtc(conn, Value, conn->connInfo.xa_opt);
|
|
}
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
#endif /* WIN32 */
|
|
unsupported = TRUE;
|
|
break;
|
|
case SQL_ATTR_AUTO_IPD:
|
|
if (SQL_FALSE != Value)
|
|
unsupported = TRUE;
|
|
break;
|
|
case SQL_ATTR_ASYNC_ENABLE:
|
|
case SQL_ATTR_CONNECTION_DEAD:
|
|
case SQL_ATTR_CONNECTION_TIMEOUT:
|
|
unsupported = TRUE;
|
|
break;
|
|
case SQL_ATTR_PGOPT_DEBUG:
|
|
newValue = CAST_UPTR(SQLCHAR, Value);
|
|
if (newValue > 0)
|
|
{
|
|
logs_on_off(-1, conn->connInfo.drivers.debug, 0);
|
|
conn->connInfo.drivers.debug = newValue;
|
|
logs_on_off(1, conn->connInfo.drivers.debug, 0);
|
|
MYLOG(0, "debug => %d\n", conn->connInfo.drivers.debug);
|
|
}
|
|
else if (newValue == 0 && conn->connInfo.drivers.debug > 0)
|
|
{
|
|
MYLOG(0, "debug => %d\n", newValue);
|
|
logs_on_off(-1, conn->connInfo.drivers.debug, 0);
|
|
conn->connInfo.drivers.debug = newValue;
|
|
logs_on_off(1, 0, 0);
|
|
}
|
|
break;
|
|
case SQL_ATTR_PGOPT_COMMLOG:
|
|
newValue = CAST_UPTR(SQLCHAR, Value);
|
|
if (newValue > 0)
|
|
{
|
|
logs_on_off(-1, 0, conn->connInfo.drivers.commlog);
|
|
conn->connInfo.drivers.commlog = newValue;
|
|
logs_on_off(1, 0, conn->connInfo.drivers.commlog);
|
|
MYLOG(0, "commlog => %d\n", conn->connInfo.drivers.commlog);
|
|
}
|
|
else if (newValue == 0 && conn->connInfo.drivers.commlog > 0)
|
|
{
|
|
MYLOG(0, "commlog => %d\n", newValue);
|
|
logs_on_off(-1, 0, conn->connInfo.drivers.commlog);
|
|
conn->connInfo.drivers.debug = newValue;
|
|
logs_on_off(1, 0, 0);
|
|
}
|
|
break;
|
|
case SQL_ATTR_PGOPT_PARSE:
|
|
conn->connInfo.drivers.parse = CAST_UPTR(SQLCHAR, Value);
|
|
MYLOG(0, "parse => %d\n", conn->connInfo.drivers.parse);
|
|
break;
|
|
case SQL_ATTR_PGOPT_USE_DECLAREFETCH:
|
|
conn->connInfo.drivers.use_declarefetch = CAST_UPTR(SQLCHAR, Value);
|
|
ci_updatable_cursors_set(&conn->connInfo);
|
|
MYLOG(0, "declarefetch => %d\n", conn->connInfo.drivers.use_declarefetch);
|
|
break;
|
|
case SQL_ATTR_PGOPT_SERVER_SIDE_PREPARE:
|
|
conn->connInfo.use_server_side_prepare = CAST_UPTR(SQLCHAR, Value);
|
|
MYLOG(0, "server_side_prepare => %d\n", conn->connInfo.use_server_side_prepare);
|
|
break;
|
|
case SQL_ATTR_PGOPT_FETCH:
|
|
conn->connInfo.drivers.fetch_max = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "fetch => %d\n", conn->connInfo.drivers.fetch_max);
|
|
break;
|
|
case SQL_ATTR_PGOPT_UNKNOWNSIZES:
|
|
conn->connInfo.drivers.unknown_sizes = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "unknown_sizes => %d\n", conn->connInfo.drivers.unknown_sizes);
|
|
break;
|
|
case SQL_ATTR_PGOPT_TEXTASLONGVARCHAR:
|
|
conn->connInfo.drivers.text_as_longvarchar = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "text_as_longvarchar => %d\n", conn->connInfo.drivers.text_as_longvarchar);
|
|
break;
|
|
case SQL_ATTR_PGOPT_UNKNOWNSASLONGVARCHAR:
|
|
conn->connInfo.drivers.unknowns_as_longvarchar = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "unknowns_as_long_varchar => %d\n", conn->connInfo.drivers.unknowns_as_longvarchar);
|
|
break;
|
|
case SQL_ATTR_PGOPT_BOOLSASCHAR:
|
|
conn->connInfo.drivers.bools_as_char = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "bools_as_char => %d\n", conn->connInfo.drivers.bools_as_char);
|
|
break;
|
|
case SQL_ATTR_PGOPT_MAXVARCHARSIZE:
|
|
conn->connInfo.drivers.max_varchar_size = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "max_varchar_size => %d\n", conn->connInfo.drivers.max_varchar_size);
|
|
break;
|
|
case SQL_ATTR_PGOPT_MAXLONGVARCHARSIZE:
|
|
conn->connInfo.drivers.max_longvarchar_size = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "max_longvarchar_size => %d\n", conn->connInfo.drivers.max_longvarchar_size);
|
|
break;
|
|
case SQL_ATTR_PGOPT_WCSDEBUG:
|
|
conn->connInfo.wcs_debug = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "wcs_debug => %d\n", conn->connInfo.wcs_debug);
|
|
break;
|
|
case SQL_ATTR_PGOPT_MSJET:
|
|
conn->ms_jet = CAST_PTR(SQLINTEGER, Value);
|
|
MYLOG(0, "ms_jet => %d\n", conn->ms_jet);
|
|
break;
|
|
default:
|
|
if (Attribute < 65536)
|
|
ret = PGAPI_SetConnectOption(ConnectionHandle, (SQLUSMALLINT) Attribute, (SQLLEN) Value);
|
|
else
|
|
unsupported = TRUE;
|
|
}
|
|
if (unsupported)
|
|
{
|
|
char msg[64];
|
|
SPRINTF_FIXED(msg, "Couldn't set unsupported connect attribute " FORMAT_INTEGER, Attribute);
|
|
CC_set_error(conn, CONN_OPTION_NOT_FOR_THE_DRIVER, msg, func);
|
|
return SQL_ERROR;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* new function */
|
|
RETCODE SQL_API
|
|
PGAPI_GetDescField(SQLHDESC DescriptorHandle,
|
|
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
|
|
PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
CSTR func = "PGAPI_GetDescField";
|
|
RETCODE ret = SQL_SUCCESS;
|
|
DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
|
|
|
|
MYLOG(0, "entering h=%p rec=%d field=%d blen=%d\n", DescriptorHandle, RecNumber, FieldIdentifier, BufferLength);
|
|
switch (DC_get_desc_type(desc))
|
|
{
|
|
case SQL_ATTR_APP_ROW_DESC:
|
|
ret = ARDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
case SQL_ATTR_APP_PARAM_DESC:
|
|
ret = APDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
case SQL_ATTR_IMP_ROW_DESC:
|
|
ret = IRDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
case SQL_ATTR_IMP_PARAM_DESC:
|
|
ret = IPDGetField(desc, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INTERNAL_ERROR, "Error not implemented");
|
|
}
|
|
if (ret == SQL_ERROR)
|
|
{
|
|
if (!DC_get_errormsg(desc))
|
|
{
|
|
switch (DC_get_errornumber(desc))
|
|
{
|
|
case DESC_INVALID_DESCRIPTOR_IDENTIFIER:
|
|
DC_set_errormsg(desc, "can't SQLGetDescField for this descriptor identifier");
|
|
break;
|
|
case DESC_INVALID_COLUMN_NUMBER_ERROR:
|
|
DC_set_errormsg(desc, "can't SQLGetDescField for this column number");
|
|
break;
|
|
case DESC_BAD_PARAMETER_NUMBER_ERROR:
|
|
DC_set_errormsg(desc, "can't SQLGetDescField for this parameter number");
|
|
break;
|
|
}
|
|
}
|
|
DC_log_error(func, "", desc);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* new function */
|
|
RETCODE SQL_API
|
|
PGAPI_SetDescField(SQLHDESC DescriptorHandle,
|
|
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
|
|
PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
CSTR func = "PGAPI_SetDescField";
|
|
RETCODE ret = SQL_SUCCESS;
|
|
DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
|
|
|
|
MYLOG(0, "entering h=%p(%d) rec=%d field=%d val=%p,%d\n", DescriptorHandle, DC_get_desc_type(desc), RecNumber, FieldIdentifier, Value, BufferLength);
|
|
switch (DC_get_desc_type(desc))
|
|
{
|
|
case SQL_ATTR_APP_ROW_DESC:
|
|
ret = ARDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
case SQL_ATTR_APP_PARAM_DESC:
|
|
ret = APDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
case SQL_ATTR_IMP_ROW_DESC:
|
|
ret = IRDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
case SQL_ATTR_IMP_PARAM_DESC:
|
|
ret = IPDSetField(desc, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
default:ret = SQL_ERROR;
|
|
DC_set_error(desc, DESC_INTERNAL_ERROR, "Error not implemented");
|
|
}
|
|
if (ret == SQL_ERROR)
|
|
{
|
|
if (!DC_get_errormsg(desc))
|
|
{
|
|
switch (DC_get_errornumber(desc))
|
|
{
|
|
case DESC_INVALID_DESCRIPTOR_IDENTIFIER:
|
|
DC_set_errormsg(desc, "can't SQLSetDescField for this descriptor identifier");
|
|
break;
|
|
case DESC_INVALID_COLUMN_NUMBER_ERROR:
|
|
DC_set_errormsg(desc, "can't SQLSetDescField for this column number");
|
|
break;
|
|
case DESC_BAD_PARAMETER_NUMBER_ERROR:
|
|
DC_set_errormsg(desc, "can't SQLSetDescField for this parameter number");
|
|
break;
|
|
}
|
|
}
|
|
DC_log_error(func, "", desc);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_SetStmtAttr(HSTMT StatementHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
CSTR func = "PGAPI_SetStmtAttr";
|
|
StatementClass *stmt = (StatementClass *) StatementHandle;
|
|
|
|
MYLOG(0, "entering Handle=%p %d," FORMAT_ULEN "(%p)\n", StatementHandle, Attribute, (SQLULEN) Value, Value);
|
|
switch (Attribute)
|
|
{
|
|
case SQL_ATTR_ENABLE_AUTO_IPD: /* 15 */
|
|
if (SQL_FALSE == Value)
|
|
break;
|
|
case SQL_ATTR_CURSOR_SCROLLABLE: /* -1 */
|
|
case SQL_ATTR_CURSOR_SENSITIVITY: /* -2 */
|
|
case SQL_ATTR_AUTO_IPD: /* 10001 */
|
|
SC_set_error(stmt, DESC_OPTION_NOT_FOR_THE_DRIVER, "Unsupported statement option (Set)", func);
|
|
return SQL_ERROR;
|
|
/* 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_PREDICATE_PTR: case
|
|
* SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
|
|
*/
|
|
SC_set_error(stmt, DESC_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Set)", func);
|
|
return SQL_ERROR;
|
|
|
|
case SQL_ATTR_METADATA_ID: /* 10014 */
|
|
stmt->options.metadata_id = CAST_UPTR(SQLUINTEGER, Value);
|
|
break;
|
|
case SQL_ATTR_APP_ROW_DESC: /* 10010 */
|
|
if (SQL_NULL_HDESC == Value)
|
|
{
|
|
stmt->ard = &(stmt->ardi);
|
|
}
|
|
else
|
|
{
|
|
stmt->ard = (DescriptorClass *) Value;
|
|
MYLOG(DETAIL_LOG_LEVEL, "set ard=%p\n", stmt->ard);
|
|
}
|
|
break;
|
|
case SQL_ATTR_APP_PARAM_DESC: /* 10011 */
|
|
if (SQL_NULL_HDESC == Value)
|
|
{
|
|
stmt->apd = &(stmt->apdi);
|
|
}
|
|
else
|
|
{
|
|
stmt->apd = (DescriptorClass *) Value;
|
|
}
|
|
break;
|
|
case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */
|
|
stmt->options.bookmark_ptr = Value;
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
|
|
SC_get_APDF(stmt)->param_offset_ptr = (SQLULEN *) Value;
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
|
|
SC_get_APDF(stmt)->param_bind_type = CAST_UPTR(SQLUINTEGER, Value);
|
|
break;
|
|
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
|
|
SC_get_APDF(stmt)->param_operation_ptr = Value;
|
|
break;
|
|
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
|
|
SC_get_IPDF(stmt)->param_status_ptr = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
|
|
SC_get_IPDF(stmt)->param_processed_ptr = (SQLULEN *) Value;
|
|
break;
|
|
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
|
|
SC_get_APDF(stmt)->paramset_size = CAST_UPTR(SQLULEN, Value);
|
|
break;
|
|
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
|
|
SC_get_ARDF(stmt)->row_offset_ptr = (SQLULEN *) Value;
|
|
break;
|
|
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
|
|
SC_get_ARDF(stmt)->row_operation_ptr = Value;
|
|
break;
|
|
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
|
|
SC_get_IRDF(stmt)->rowStatusArray = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
|
|
SC_get_IRDF(stmt)->rowsFetched = (SQLULEN *) Value;
|
|
break;
|
|
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
|
|
SC_get_ARDF(stmt)->size_of_rowset = CAST_UPTR(SQLULEN, Value);
|
|
break;
|
|
default:
|
|
return PGAPI_SetStmtOption(StatementHandle, (SQLUSMALLINT) Attribute, (SQLULEN) Value);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* SQL_NEED_DATA callback for PGAPI_BulkOperations */
|
|
typedef struct
|
|
{
|
|
StatementClass *stmt;
|
|
SQLSMALLINT operation;
|
|
char need_data_callback;
|
|
char auto_commit_needed;
|
|
ARDFields *opts;
|
|
int idx, processed;
|
|
} bop_cdata;
|
|
|
|
static
|
|
RETCODE bulk_ope_callback(RETCODE retcode, void *para)
|
|
{
|
|
CSTR func = "bulk_ope_callback";
|
|
RETCODE ret = retcode;
|
|
bop_cdata *s = (bop_cdata *) para;
|
|
SQLULEN global_idx;
|
|
ConnectionClass *conn;
|
|
QResultClass *res;
|
|
IRDFields *irdflds;
|
|
PG_BM pg_bm;
|
|
|
|
if (s->need_data_callback)
|
|
{
|
|
MYLOG(0, "entering in\n");
|
|
s->processed++;
|
|
s->idx++;
|
|
}
|
|
else
|
|
{
|
|
s->idx = s->processed = 0;
|
|
}
|
|
s->need_data_callback = FALSE;
|
|
res = SC_get_Curres(s->stmt);
|
|
for (; SQL_ERROR != ret && s->idx < s->opts->size_of_rowset; s->idx++)
|
|
{
|
|
if (SQL_ADD != s->operation)
|
|
{
|
|
pg_bm = SC_Resolve_bookmark(s->opts, s->idx);
|
|
QR_get_last_bookmark(res, s->idx, &pg_bm.keys);
|
|
global_idx = pg_bm.index;
|
|
}
|
|
/* Note opts->row_operation_ptr is ignored */
|
|
switch (s->operation)
|
|
{
|
|
case SQL_ADD:
|
|
ret = SC_pos_add(s->stmt, (UWORD) s->idx);
|
|
break;
|
|
case SQL_UPDATE_BY_BOOKMARK:
|
|
ret = SC_pos_update(s->stmt, (UWORD) s->idx, global_idx, &(pg_bm.keys));
|
|
break;
|
|
case SQL_DELETE_BY_BOOKMARK:
|
|
ret = SC_pos_delete(s->stmt, (UWORD) s->idx, global_idx, &(pg_bm.keys));
|
|
break;
|
|
}
|
|
if (SQL_NEED_DATA == ret)
|
|
{
|
|
bop_cdata *cbdata = (bop_cdata *) malloc(sizeof(bop_cdata));
|
|
if (!cbdata)
|
|
{
|
|
SC_set_error(s->stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for cbdata.", func);
|
|
return SQL_ERROR;
|
|
}
|
|
memcpy(cbdata, s, sizeof(bop_cdata));
|
|
cbdata->need_data_callback = TRUE;
|
|
if (0 == enqueueNeedDataCallback(s->stmt, bulk_ope_callback, cbdata))
|
|
ret = SQL_ERROR;
|
|
return ret;
|
|
}
|
|
s->processed++;
|
|
}
|
|
conn = SC_get_conn(s->stmt);
|
|
if (s->auto_commit_needed)
|
|
CC_set_autocommit(conn, TRUE);
|
|
irdflds = SC_get_IRDF(s->stmt);
|
|
if (irdflds->rowsFetched)
|
|
*(irdflds->rowsFetched) = s->processed;
|
|
|
|
if (res)
|
|
res->recent_processed_row_count = s->stmt->diag_row_count = s->processed;
|
|
return ret;
|
|
}
|
|
|
|
RETCODE SQL_API
|
|
PGAPI_BulkOperations(HSTMT hstmt, SQLSMALLINT operationX)
|
|
{
|
|
CSTR func = "PGAPI_BulkOperations";
|
|
bop_cdata s;
|
|
RETCODE ret;
|
|
ConnectionClass *conn;
|
|
BindInfoClass *bookmark;
|
|
|
|
MYLOG(0, "entering operation = %d\n", operationX);
|
|
s.stmt = (StatementClass *) hstmt;
|
|
s.operation = operationX;
|
|
SC_clear_error(s.stmt);
|
|
s.opts = SC_get_ARDF(s.stmt);
|
|
|
|
s.auto_commit_needed = FALSE;
|
|
if (SQL_FETCH_BY_BOOKMARK != s.operation)
|
|
{
|
|
conn = SC_get_conn(s.stmt);
|
|
if (s.auto_commit_needed = (char) CC_does_autocommit(conn), s.auto_commit_needed)
|
|
CC_set_autocommit(conn, FALSE);
|
|
}
|
|
if (SQL_ADD != s.operation)
|
|
{
|
|
if (!(bookmark = s.opts->bookmark) || !(bookmark->buffer))
|
|
{
|
|
SC_set_error(s.stmt, DESC_INVALID_OPTION_IDENTIFIER, "bookmark isn't specified", func);
|
|
return SQL_ERROR;
|
|
}
|
|
}
|
|
|
|
if (SQL_FETCH_BY_BOOKMARK == operationX)
|
|
ret = SC_fetch_by_bookmark(s.stmt);
|
|
else
|
|
{
|
|
s.need_data_callback = FALSE;
|
|
ret = bulk_ope_callback(SQL_SUCCESS, &s);
|
|
}
|
|
return ret;
|
|
}
|