mirror of
https://github.com/postgres/postgres.git
synced 2026-02-20 08:20:55 -05:00
2) Implement some options for SQLGetDescField(). 3) Handle *Inifinity* timestamp for SQL_C_CHAR type output. 4) Separate Unicode conversions from common implementations. 5) Improve internal parse_statement() function.
1341 lines
36 KiB
C
1341 lines
36 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
|
|
*-------
|
|
*/
|
|
|
|
#ifndef ODBCVER
|
|
#define ODBCVER 0x0300
|
|
#endif
|
|
#include "psqlodbc.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "environ.h"
|
|
#include "connection.h"
|
|
#include "statement.h"
|
|
#include "descriptor.h"
|
|
#include "pgapifunc.h"
|
|
|
|
static HSTMT statementHandleFromDescHandle(SQLHDESC, SQLINTEGER *descType);
|
|
/* 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;
|
|
static const char *func = "PGAPI_GetDiagRec";
|
|
|
|
mylog("%s entering rec=%d", func, 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_StmtError(statementHandleFromDescHandle(Handle, NULL),
|
|
RecNumber, Sqlstate, NativeError,
|
|
MessageText, BufferLength,
|
|
TextLength, 0);
|
|
break;
|
|
default:
|
|
ret = SQL_ERROR;
|
|
}
|
|
mylog("%s exiting %d\n", func, ret);
|
|
return ret;
|
|
}
|
|
|
|
RETCODE SQL_API
|
|
PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|
SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
|
|
PTR DiagInfoPtr, SQLSMALLINT BufferLength,
|
|
SQLSMALLINT *StringLengthPtr)
|
|
{
|
|
RETCODE ret = SQL_ERROR;
|
|
static const char *func = "PGAPI_GetDiagField";
|
|
|
|
mylog("%s entering rec=%d", func, 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_MESSAGE_TEXT:
|
|
case SQL_DIAG_NATIVE:
|
|
case SQL_DIAG_NUMBER:
|
|
case SQL_DIAG_RETURNCODE:
|
|
case SQL_DIAG_SERVER_NAME:
|
|
case SQL_DIAG_SQLSTATE:
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_HANDLE_DBC:
|
|
switch (DiagIdentifier)
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
case SQL_DIAG_NATIVE:
|
|
case SQL_DIAG_NUMBER:
|
|
case SQL_DIAG_RETURNCODE:
|
|
case SQL_DIAG_SERVER_NAME:
|
|
case SQL_DIAG_SQLSTATE:
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_HANDLE_STMT:
|
|
switch (DiagIdentifier)
|
|
{
|
|
case SQL_DIAG_CLASS_ORIGIN:
|
|
case SQL_DIAG_SUBCLASS_ORIGIN:
|
|
case SQL_DIAG_CONNECTION_NAME:
|
|
case SQL_DIAG_MESSAGE_TEXT:
|
|
case SQL_DIAG_NATIVE:
|
|
case SQL_DIAG_NUMBER:
|
|
case SQL_DIAG_RETURNCODE:
|
|
case SQL_DIAG_SERVER_NAME:
|
|
break;
|
|
case SQL_DIAG_SQLSTATE:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
ret = SQL_ERROR;
|
|
}
|
|
mylog("%s exiting %d\n", func, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* SQLGetConnectOption -> SQLGetconnectAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_GetConnectAttr(HDBC ConnectionHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER BufferLength, SQLINTEGER *StringLength)
|
|
{
|
|
static const char *func = "PGAPI_GetConnectAttr";
|
|
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER len = 4;
|
|
|
|
mylog("PGAPI_GetConnectAttr %d\n", Attribute);
|
|
switch (Attribute)
|
|
{
|
|
case SQL_ATTR_ASYNC_ENABLE:
|
|
*((SQLUINTEGER *) Value) = SQL_ASYNC_ENABLE_OFF;
|
|
break;
|
|
case SQL_ATTR_AUTO_IPD:
|
|
*((SQLUINTEGER *) Value) = SQL_FALSE;
|
|
break;
|
|
case SQL_ATTR_CONNECTION_DEAD:
|
|
if (CC_is_in_trans(conn))
|
|
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
|
else if (conn->num_stmts > 0)
|
|
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
|
else
|
|
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
|
break;
|
|
case SQL_ATTR_CONNECTION_TIMEOUT:
|
|
*((SQLUINTEGER *) Value) = 0;
|
|
break;
|
|
case SQL_ATTR_METADATA_ID:
|
|
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
conn->errormsg = "Unsupported connect attribute (Get)";
|
|
CC_log_error(func, "", conn);
|
|
return SQL_ERROR;
|
|
default:
|
|
ret = PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value);
|
|
}
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static SQLHDESC
|
|
descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
|
|
{
|
|
switch (descType)
|
|
{
|
|
case SQL_ATTR_APP_ROW_DESC: /* 10010 */
|
|
return StatementHandle; /* this is bogus */
|
|
case SQL_ATTR_APP_PARAM_DESC: /* 10011 */
|
|
return (HSTMT) ((SQLUINTEGER) StatementHandle + 1) ; /* this is bogus */
|
|
case SQL_ATTR_IMP_ROW_DESC: /* 10012 */
|
|
return (HSTMT) ((SQLUINTEGER) StatementHandle + 2); /* this is bogus */
|
|
case SQL_ATTR_IMP_PARAM_DESC: /* 10013 */
|
|
return (HSTMT) ((SQLUINTEGER) StatementHandle + 3); /* this is bogus */
|
|
}
|
|
return (HSTMT) 0;
|
|
}
|
|
static HSTMT
|
|
statementHandleFromDescHandle(SQLHDESC DescHandle, SQLINTEGER *descType)
|
|
{
|
|
SQLUINTEGER res = (SQLUINTEGER) DescHandle % 4;
|
|
if (descType)
|
|
{
|
|
switch (res)
|
|
{
|
|
case 0: *descType = SQL_ATTR_APP_ROW_DESC; /* 10010 */
|
|
break;
|
|
case 1: *descType = SQL_ATTR_APP_PARAM_DESC; /* 10011 */
|
|
break;
|
|
case 2: *descType = SQL_ATTR_IMP_ROW_DESC; /* 10012 */
|
|
break;
|
|
case 3: *descType = SQL_ATTR_IMP_PARAM_DESC; /* 10013 */
|
|
break;
|
|
}
|
|
}
|
|
return (HSTMT) ((SQLUINTEGER) DescHandle - res);
|
|
}
|
|
|
|
void Desc_set_error(SQLHDESC hdesc, int errornumber, const char *errormsg)
|
|
{
|
|
SQLINTEGER descType;
|
|
HSTMT hstmt = statementHandleFromDescHandle(hdesc, &descType);
|
|
StatementClass *stmt;
|
|
|
|
if (!hstmt)
|
|
return;
|
|
stmt = (StatementClass *) hstmt;
|
|
stmt->errornumber = errornumber;
|
|
stmt->errormsg = errormsg; /* should be static */
|
|
}
|
|
|
|
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(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
PTR tptr;
|
|
ARDFields *opts = SC_get_ARD(stmt);
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
opts->rowset_size = (SQLUINTEGER) Value;
|
|
break;
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
opts->row_operation_ptr = Value;
|
|
break;
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
opts->row_offset_ptr = Value;
|
|
break;
|
|
case SQL_DESC_BIND_TYPE:
|
|
opts->bind_size = (SQLUINTEGER) Value;
|
|
break;
|
|
|
|
case SQL_DESC_TYPE:
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
reset_a_column_binding(opts, RecNumber);
|
|
opts->bindings[RecNumber - 1].returntype = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
switch (opts->bindings[RecNumber - 1].returntype)
|
|
{
|
|
case SQL_DATETIME:
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
switch ((Int4) Value)
|
|
{
|
|
case SQL_CODE_DATE:
|
|
opts->bindings[RecNumber - 1].returntype = SQL_C_TYPE_DATE;
|
|
break;
|
|
case SQL_CODE_TIME:
|
|
opts->bindings[RecNumber - 1].returntype = SQL_C_TYPE_TIME;
|
|
break;
|
|
case SQL_CODE_TIMESTAMP:
|
|
opts->bindings[RecNumber - 1].returntype = SQL_C_TYPE_TIMESTAMP;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
opts->bindings[RecNumber - 1].returntype = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
if (!RecNumber)
|
|
opts->bookmark->buffer = Value;
|
|
else
|
|
{
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
opts->bindings[RecNumber - 1].buffer = Value;
|
|
}
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
if (!RecNumber)
|
|
tptr = opts->bookmark->used;
|
|
else
|
|
{
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
tptr = opts->bindings[RecNumber - 1].used;
|
|
}
|
|
if (Value != tptr)
|
|
{
|
|
ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR";
|
|
}
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
if (!RecNumber)
|
|
opts->bookmark->used = Value;
|
|
else
|
|
{
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
opts->bindings[RecNumber - 1].used = Value;
|
|
}
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
column_bindings_set(opts, (SQLUINTEGER) Value, FALSE);
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
if (RecNumber)
|
|
{
|
|
column_bindings_set(opts, RecNumber, TRUE);
|
|
opts->bindings[RecNumber - 1].buflen = (Int4) 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:
|
|
case SQL_DESC_PRECISION:
|
|
case SQL_DESC_SCALE:
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
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 RETCODE SQL_API
|
|
APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
APDFields *opts = SC_get_APD(stmt);
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
opts->paramset_size = (SQLUINTEGER) Value;
|
|
break;
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
opts->param_operation_ptr = Value;
|
|
break;
|
|
case SQL_DESC_BIND_OFFSET_PTR:
|
|
opts->param_offset_ptr = Value;
|
|
break;
|
|
case SQL_DESC_BIND_TYPE:
|
|
opts->param_bind_type = (SQLUINTEGER) Value;
|
|
break;
|
|
|
|
case SQL_DESC_TYPE:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
reset_a_parameter_binding(opts, RecNumber);
|
|
opts->parameters[RecNumber - 1].CType = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
switch (opts->parameters[RecNumber - 1].CType)
|
|
{
|
|
case SQL_DATETIME:
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
switch ((Int4) Value)
|
|
{
|
|
case SQL_CODE_DATE:
|
|
opts->parameters[RecNumber - 1].CType = SQL_C_TYPE_DATE;
|
|
break;
|
|
case SQL_CODE_TIME:
|
|
opts->parameters[RecNumber - 1].CType = SQL_C_TYPE_TIME;
|
|
break;
|
|
case SQL_CODE_TIMESTAMP:
|
|
opts->parameters[RecNumber - 1].CType = SQL_C_TYPE_TIMESTAMP;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
opts->parameters[RecNumber - 1].CType = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
opts->parameters[RecNumber - 1].buffer = Value;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
if (opts->allocated < RecNumber ||
|
|
Value != opts->parameters[RecNumber - 1].used)
|
|
{
|
|
ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR";
|
|
}
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
opts->parameters[RecNumber - 1].buflen = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
parameter_bindings_set(opts, RecNumber, TRUE);
|
|
opts->parameters[RecNumber - 1].used = Value;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
parameter_bindings_set(opts, (SQLUINTEGER) Value, FALSE);
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
case SQL_DESC_PRECISION:
|
|
case SQL_DESC_SCALE:
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IRDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
IRDFields *opts = SC_get_IRD(stmt);
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
opts->rowStatusArray = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
opts->rowsFetched = (SQLUINTEGER *) 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 */
|
|
#if (ODBCVER >= 0x0350)
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
#endif /* ODBCVER */
|
|
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;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
IPDFields *ipdopts = SC_get_IPD(stmt);
|
|
APDFields *apdopts = SC_get_APD(stmt);
|
|
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
ipdopts->param_status_ptr = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
ipdopts->param_processed_ptr = (SQLUINTEGER *) Value;
|
|
break;
|
|
case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
|
|
if (SQL_UNNAMED != (SQLUINTEGER) Value)
|
|
{
|
|
ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
break;
|
|
case SQL_DESC_TYPE:
|
|
parameter_bindings_set(apdopts, RecNumber, TRUE);
|
|
apdopts->parameters[RecNumber - 1].SQLType = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
parameter_bindings_set(apdopts, RecNumber, TRUE);
|
|
switch (apdopts->parameters[RecNumber - 1].SQLType)
|
|
{
|
|
case SQL_DATETIME:
|
|
case SQL_TYPE_DATE:
|
|
case SQL_TYPE_TIME:
|
|
case SQL_TYPE_TIMESTAMP:
|
|
switch ((Int4) Value)
|
|
{
|
|
case SQL_CODE_DATE:
|
|
apdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_DATE;
|
|
break;
|
|
case SQL_CODE_TIME:
|
|
apdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_TIME;
|
|
break;
|
|
case SQL_CODE_TIMESTAMP:
|
|
apdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_TIMESTAMP;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_CONCISE_TYPE:
|
|
parameter_bindings_set(apdopts, RecNumber, TRUE);
|
|
apdopts->parameters[RecNumber - 1].SQLType = (Int4) Value;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
parameter_bindings_set(apdopts, (SQLUINTEGER) Value, FALSE);
|
|
break;
|
|
case SQL_DESC_PARAMETER_TYPE:
|
|
apdopts->parameters[RecNumber - 1].paramType = (Int2) Value;
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
apdopts->parameters[RecNumber - 1].decimal_digits = (Int2) Value;
|
|
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_NAME:
|
|
case SQL_DESC_NULLABLE: /* read-only */
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
case SQL_DESC_PRECISION:
|
|
#if (ODBCVER >= 0x0350)
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
#endif /* ODBCVER */
|
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_UNSIGNED: /* read-only */
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
static RETCODE SQL_API
|
|
ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER len, ival, rettype = 0;
|
|
PTR ptr = NULL;
|
|
const ARDFields *opts = SC_get_ARD(stmt);
|
|
|
|
len = 4;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
ival = opts->rowset_size;
|
|
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:
|
|
switch (opts->bindings[RecNumber - 1].returntype)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
ival = SQL_DATETIME;
|
|
break;
|
|
default:
|
|
ival = opts->bindings[RecNumber - 1].returntype;
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
switch (opts->bindings[RecNumber - 1].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:
|
|
ival = opts->bindings[RecNumber - 1].returntype;
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
if (!RecNumber)
|
|
ptr = opts->bookmark->buffer;
|
|
else
|
|
{
|
|
ptr = opts->bindings[RecNumber - 1].buffer;
|
|
}
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
if (!RecNumber)
|
|
ptr = opts->bookmark->used;
|
|
else
|
|
{
|
|
ptr = opts->bindings[RecNumber - 1].used;
|
|
}
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
if (!RecNumber)
|
|
ptr = opts->bookmark->used;
|
|
else
|
|
{
|
|
ptr = opts->bindings[RecNumber - 1].used;
|
|
}
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
ival = opts->allocated;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
if (RecNumber)
|
|
{
|
|
ival = opts->bindings[RecNumber - 1].buflen;
|
|
}
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
ival = SQL_DESC_ALLOC_AUTO;
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
case SQL_DESC_PRECISION:
|
|
case SQL_DESC_SCALE:
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = 4;
|
|
*((SQLINTEGER *) Value) = ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = 4;
|
|
*((void **) Value) = ptr;
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER ival = 0, len, rettype = 0;
|
|
PTR ptr = NULL;
|
|
const APDFields *opts = SC_get_APD(stmt);
|
|
|
|
len = 4;
|
|
switch (FieldIdentifier)
|
|
{
|
|
case SQL_DESC_ARRAY_SIZE:
|
|
rettype = SQL_IS_POINTER;
|
|
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:
|
|
switch (opts->parameters[RecNumber - 1].CType)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
ival = SQL_DATETIME;
|
|
break;
|
|
default:
|
|
ival = opts->parameters[RecNumber - 1].CType;
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
switch (opts->parameters[RecNumber - 1].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:
|
|
ival = opts->parameters[RecNumber - 1].CType;
|
|
break;
|
|
case SQL_DESC_DATA_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->parameters[RecNumber - 1].buffer;
|
|
break;
|
|
case SQL_DESC_INDICATOR_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->parameters[RecNumber - 1].used;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH:
|
|
ival = opts->parameters[RecNumber - 1].buflen;
|
|
break;
|
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
rettype = SQL_IS_POINTER;
|
|
ptr = opts->parameters[RecNumber - 1].used;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
ival = opts->allocated;
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
ival = SQL_DESC_ALLOC_AUTO;
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
case SQL_DESC_SCALE:
|
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
|
case SQL_DESC_LENGTH:
|
|
case SQL_DESC_NUM_PREC_RADIX:
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = 4;
|
|
*((Int4 *) Value) = ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = 4;
|
|
*((void **) Value) = ptr;
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER ival = 0, len, rettype = 0;
|
|
PTR ptr = NULL;
|
|
BOOL bCallColAtt = FALSE;
|
|
const IRDFields *opts = SC_get_IRD(stmt);
|
|
|
|
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 */
|
|
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 */
|
|
#if (ODBCVER >= 0x0350)
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
#endif /* ODBCVER */
|
|
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;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
if (bCallColAtt)
|
|
{
|
|
SQLSMALLINT pcbL;
|
|
|
|
ret = PGAPI_ColAttributes(stmt, RecNumber,
|
|
FieldIdentifier, Value, (SQLSMALLINT) BufferLength,
|
|
&pcbL, &ival);
|
|
len = pcbL;
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = 4;
|
|
*((Int4 *) Value) = ival;
|
|
break;
|
|
case SQL_IS_UINTEGER:
|
|
len = 4;
|
|
*((UInt4 *) Value) = ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = 4;
|
|
*((void **) Value) = ptr;
|
|
break;
|
|
}
|
|
|
|
if (StringLength)
|
|
*StringLength = len;
|
|
return ret;
|
|
}
|
|
|
|
static RETCODE SQL_API
|
|
IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
SQLINTEGER ival = 0, len, rettype = 0;
|
|
PTR ptr = NULL;
|
|
const IPDFields *ipdopts = SC_get_IPD(stmt);
|
|
const APDFields *apdopts = SC_get_APD(stmt);
|
|
|
|
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: /* only SQL_UNNAMED is allowed */
|
|
ival = SQL_UNNAMED;
|
|
break;
|
|
case SQL_DESC_TYPE:
|
|
switch (apdopts->parameters[RecNumber - 1].SQLType)
|
|
{
|
|
case SQL_TYPE_DATE:
|
|
case SQL_TYPE_TIME:
|
|
case SQL_TYPE_TIMESTAMP:
|
|
ival = SQL_DATETIME;
|
|
break;
|
|
default:
|
|
ival = apdopts->parameters[RecNumber - 1].SQLType;
|
|
}
|
|
break;
|
|
case SQL_DESC_DATETIME_INTERVAL_CODE:
|
|
switch (apdopts->parameters[RecNumber - 1].SQLType)
|
|
{
|
|
case SQL_TYPE_DATE:
|
|
ival = SQL_CODE_DATE;
|
|
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:
|
|
ival = apdopts->parameters[RecNumber - 1].SQLType;
|
|
break;
|
|
case SQL_DESC_COUNT:
|
|
ival = apdopts->allocated;
|
|
break;
|
|
case SQL_DESC_PARAMETER_TYPE:
|
|
ival = apdopts->parameters[RecNumber - 1].paramType;
|
|
break;
|
|
case SQL_DESC_PRECISION:
|
|
switch (apdopts->parameters[RecNumber - 1].CType)
|
|
{
|
|
case SQL_C_TYPE_DATE:
|
|
case SQL_C_TYPE_TIME:
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
case SQL_DATETIME:
|
|
ival = apdopts->parameters[RecNumber - 1].decimal_digits;
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_SCALE:
|
|
switch (apdopts->parameters[RecNumber - 1].CType)
|
|
{
|
|
case SQL_C_NUMERIC:
|
|
ival = apdopts->parameters[RecNumber - 1].decimal_digits;
|
|
break;
|
|
}
|
|
break;
|
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
|
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:
|
|
#if (ODBCVER >= 0x0350)
|
|
case SQL_DESC_ROWVER: /* read-only */
|
|
#endif /* ODBCVER */
|
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
case SQL_DESC_UNSIGNED: /* read-only */
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
|
}
|
|
switch (rettype)
|
|
{
|
|
case 0:
|
|
case SQL_IS_INTEGER:
|
|
len = 4;
|
|
*((Int4 *) Value) = ival;
|
|
break;
|
|
case SQL_IS_POINTER:
|
|
len = 4;
|
|
*((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)
|
|
{
|
|
static char *func = "PGAPI_GetStmtAttr";
|
|
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 */
|
|
*((void **) Value) = stmt->options.bookmark_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
|
|
*((SQLUINTEGER **) Value) = SC_get_APD(stmt)->param_offset_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
|
|
*((SQLUINTEGER *) Value) = SC_get_APD(stmt)->param_bind_type;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_APD(stmt)->param_operation_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_IPD(stmt)->param_status_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
|
|
*((SQLUINTEGER **) Value) = SC_get_IPD(stmt)->param_processed_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
|
|
*((SQLUINTEGER *) Value) = SC_get_APD(stmt)->paramset_size;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
|
|
*((SQLUINTEGER **) Value) = SC_get_ARD(stmt)->row_offset_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_ARD(stmt)->row_operation_ptr;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
|
|
*((SQLUSMALLINT **) Value) = SC_get_IRD(stmt)->rowStatusArray;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
|
|
*((SQLUINTEGER **) Value) = SC_get_IRD(stmt)->rowsFetched;
|
|
len = 4;
|
|
break;
|
|
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
|
|
*((SQLUINTEGER *) Value) = SC_get_ARD(stmt)->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;
|
|
}
|
|
|
|
/* SQLSetConnectOption -> SQLSetConnectAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_SetConnectAttr(HDBC ConnectionHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER StringLength)
|
|
{
|
|
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
|
|
RETCODE ret = SQL_SUCCESS;
|
|
|
|
mylog("PGAPI_SetConnectAttr %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 connect attribute (Set)";
|
|
return SQL_ERROR;
|
|
default:
|
|
ret = PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* new function */
|
|
RETCODE SQL_API
|
|
PGAPI_GetDescField(SQLHDESC DescriptorHandle,
|
|
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
|
|
PTR Value, SQLINTEGER BufferLength,
|
|
SQLINTEGER *StringLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
HSTMT hstmt;
|
|
SQLUINTEGER descType;
|
|
StatementClass *stmt;
|
|
static const char *func = "PGAPI_GetDescField";
|
|
|
|
mylog("%s h=%u rec=%d field=%d blen=%d\n", func, DescriptorHandle, RecNumber, FieldIdentifier, BufferLength);
|
|
hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType);
|
|
mylog("stmt=%x type=%d\n", hstmt, descType);
|
|
stmt = (StatementClass *) hstmt;
|
|
switch (descType)
|
|
{
|
|
case SQL_ATTR_APP_ROW_DESC:
|
|
ret = ARDGetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
case SQL_ATTR_APP_PARAM_DESC:
|
|
ret = APDGetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
case SQL_ATTR_IMP_ROW_DESC:
|
|
ret = IRDGetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
case SQL_ATTR_IMP_PARAM_DESC:
|
|
ret = IPDGetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
|
|
break;
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INTERNAL_ERROR;
|
|
stmt->errormsg = "Error not implemented";
|
|
}
|
|
if (ret == SQL_ERROR)
|
|
{
|
|
if (!stmt->errormsg && stmt->errornumber == STMT_INVALID_DESCRIPTOR_IDENTIFIER)
|
|
stmt->errormsg = "can't SQLGetDescField for this descriptor identifier";
|
|
SC_log_error(func, "", stmt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* new function */
|
|
RETCODE SQL_API
|
|
PGAPI_SetDescField(SQLHDESC DescriptorHandle,
|
|
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
|
|
PTR Value, SQLINTEGER BufferLength)
|
|
{
|
|
RETCODE ret = SQL_SUCCESS;
|
|
HSTMT hstmt;
|
|
SQLUINTEGER descType;
|
|
StatementClass *stmt;
|
|
static const char *func = "PGAPI_SetDescField";
|
|
|
|
mylog("%s h=%u rec=%d field=%d val=%x,%d\n", func, DescriptorHandle, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType);
|
|
mylog("stmt=%x type=%d\n", hstmt, descType);
|
|
stmt = (StatementClass *) hstmt;
|
|
switch (descType)
|
|
{
|
|
case SQL_ATTR_APP_ROW_DESC:
|
|
ret = ARDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
case SQL_ATTR_APP_PARAM_DESC:
|
|
ret = APDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
case SQL_ATTR_IMP_ROW_DESC:
|
|
ret = IRDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
case SQL_ATTR_IMP_PARAM_DESC:
|
|
ret = IPDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
break;
|
|
default:ret = SQL_ERROR;
|
|
stmt->errornumber = STMT_INTERNAL_ERROR;
|
|
stmt->errormsg = "Error not implemented";
|
|
}
|
|
if (ret == SQL_ERROR)
|
|
{
|
|
if (!stmt->errormsg && stmt->errornumber == STMT_INVALID_DESCRIPTOR_IDENTIFIER)
|
|
stmt->errormsg = "can't SQLSetDescField for this descriptor identifier";
|
|
SC_log_error(func, "", stmt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */
|
|
RETCODE SQL_API
|
|
PGAPI_SetStmtAttr(HSTMT StatementHandle,
|
|
SQLINTEGER Attribute, PTR Value,
|
|
SQLINTEGER StringLength)
|
|
{
|
|
static char *func = "PGAPI_SetStmtAttr";
|
|
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 */
|
|
SC_get_APD(stmt)->param_offset_ptr = (SQLUINTEGER *) Value;
|
|
break;
|
|
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
|
|
SC_get_APD(stmt)->param_bind_type = (SQLUINTEGER) Value;
|
|
break;
|
|
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
|
|
SC_get_APD(stmt)->param_operation_ptr = Value;
|
|
break;
|
|
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
|
|
SC_get_IPD(stmt)->param_status_ptr = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
|
|
SC_get_IPD(stmt)->param_processed_ptr = (SQLUINTEGER *) Value;
|
|
break;
|
|
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
|
|
SC_get_APD(stmt)->paramset_size = (SQLUINTEGER) Value;
|
|
break;
|
|
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
|
|
SC_get_ARD(stmt)->row_offset_ptr = (SQLUINTEGER *) Value;
|
|
break;
|
|
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
|
|
SC_get_ARD(stmt)->row_operation_ptr = Value;
|
|
break;
|
|
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
|
|
SC_get_IRD(stmt)->rowStatusArray = (SQLUSMALLINT *) Value;
|
|
break;
|
|
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
|
|
SC_get_IRD(stmt)->rowsFetched = (SQLUINTEGER *) Value;
|
|
break;
|
|
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
|
|
SC_get_ARD(stmt)->rowset_size = (SQLUINTEGER) Value;
|
|
break;
|
|
default:
|
|
return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value);
|
|
}
|
|
return SQL_SUCCESS;
|
|
}
|