diff options
author | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-03-28 08:08:07 +0000 |
---|---|---|
committer | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-03-28 08:08:07 +0000 |
commit | 6852741c1879fd2bd5ab5b367c7fc5a130dfd4da (patch) | |
tree | a0f27a6fb623307b0772f2964f31707fd302972e /src/interfaces/odbc/pgapi30.c | |
parent | e6774dc3553d814e6aa500cabe5739b2e6f94df4 (diff) | |
download | postgresql-6852741c1879fd2bd5ab5b367c7fc5a130dfd4da.tar.gz postgresql-6852741c1879fd2bd5ab5b367c7fc5a130dfd4da.zip |
[2002-03-28]
1) Prepare to separate 4 kinds of Descriptor handles.
2) Detect the transaction status more naturally.
3) Improve Parse Statement functionality for the use
of updatable cursors.
4) Improve updatable cursors.
5) Implement SQLGetDescField() and improve SQLColAttribute().
6) etc.
Diffstat (limited to 'src/interfaces/odbc/pgapi30.c')
-rw-r--r-- | src/interfaces/odbc/pgapi30.c | 905 |
1 files changed, 837 insertions, 68 deletions
diff --git a/src/interfaces/odbc/pgapi30.c b/src/interfaces/odbc/pgapi30.c index 6e4c575e31e..a67cc434fab 100644 --- a/src/interfaces/odbc/pgapi30.c +++ b/src/interfaces/odbc/pgapi30.c @@ -24,8 +24,10 @@ #include "environ.h" #include "connection.h" #include "statement.h" +#include "descriptor.h" #include "pgapifunc.h" +static HSTMT statementHandleFromDescHandle(HSTMT, SQLINTEGER *descType); /* SQLError -> SQLDiagRec */ RETCODE SQL_API PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, @@ -54,6 +56,12 @@ PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, 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; } @@ -131,21 +139,37 @@ 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: + *((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); } - return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value); + if (StringLength) + *StringLength = len; + return ret; } static HSTMT @@ -168,113 +192,263 @@ static HSTMT statementHandleFromDescHandle(HSTMT DescHandle, SQLINTEGER *descType) { SQLUINTEGER res = (SQLUINTEGER) DescHandle % 4; - switch (res) + if (descType) { - 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; + 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); } +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: - stmt->options.rowset_size = (SQLUINTEGER) Value; + opts->rowset_size = (SQLUINTEGER) Value; break; case SQL_DESC_ARRAY_STATUS_PTR: - stmt->options.row_operation_ptr = Value; + opts->row_operation_ptr = Value; break; case SQL_DESC_BIND_OFFSET_PTR: - stmt->options.row_offset_ptr = Value; + opts->row_offset_ptr = Value; break; case SQL_DESC_BIND_TYPE: - stmt->options.bind_size = (SQLUINTEGER) Value; + 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) - stmt->bookmark.buffer = Value; + opts->bookmark->buffer = Value; else - stmt->bindings[RecNumber - 1].buffer = Value; + { + column_bindings_set(opts, RecNumber, TRUE); + opts->bindings[RecNumber - 1].buffer = Value; + } break; case SQL_DESC_INDICATOR_PTR: if (!RecNumber) - tptr = stmt->bookmark.used; + tptr = opts->bookmark->used; else - tptr = stmt->bindings[RecNumber - 1].used; + { + column_bindings_set(opts, RecNumber, TRUE); + tptr = opts->bindings[RecNumber - 1].used; + } if (Value != tptr) { ret = SQL_ERROR; - stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; } break; case SQL_DESC_OCTET_LENGTH_PTR: if (!RecNumber) - stmt->bookmark.used = Value; + opts->bookmark->used = Value; else - stmt->bindings[RecNumber - 1].used = Value; + { + 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_OPTION_IDENTIFIER; - stmt->errormsg = "not implemedted yet"; + 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: - stmt->options.paramset_size = (SQLUINTEGER) Value; + opts->paramset_size = (SQLUINTEGER) Value; break; case SQL_DESC_ARRAY_STATUS_PTR: - stmt->options.param_operation_ptr = Value; + opts->param_operation_ptr = Value; break; case SQL_DESC_BIND_OFFSET_PTR: - stmt->options.param_offset_ptr = Value; + opts->param_offset_ptr = Value; break; case SQL_DESC_BIND_TYPE: - stmt->options.param_bind_type = (SQLUINTEGER) Value; + 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: - if (stmt->parameters_allocated < RecNumber) - PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0); - stmt->parameters[RecNumber - 1].buffer = Value; + parameter_bindings_set(opts, RecNumber, TRUE); + opts->parameters[RecNumber - 1].buffer = Value; break; case SQL_DESC_INDICATOR_PTR: - if (stmt->parameters_allocated < RecNumber || - Value != stmt->parameters[RecNumber - 1].used) + if (opts->allocated < RecNumber || + Value != opts->parameters[RecNumber - 1].used) { ret = SQL_ERROR; - stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; + 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: - if (stmt->parameters_allocated < RecNumber) - PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0); - stmt->parameters[RecNumber - 1].used = Value; + 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_OPTION_IDENTIFIER; + stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; } return ret; } @@ -284,16 +458,51 @@ 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: - stmt->options.rowStatusArray = (SQLUSMALLINT *) Value; + opts->rowStatusArray = (SQLUSMALLINT *) Value; break; case SQL_DESC_ROWS_PROCESSED_PTR: - stmt->options.rowsFetched = (SQLUINTEGER *) Value; + 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_OPTION_IDENTIFIER; + stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; } return ret; } @@ -303,17 +512,526 @@ 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].scale = (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; + 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: + ptr = opts->row_operation_ptr; + break; + case SQL_DESC_BIND_OFFSET_PTR: + 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: + if (!RecNumber) + ptr = opts->bookmark->buffer; + else + { + ptr = opts->bindings[RecNumber - 1].buffer; + } + break; + case SQL_DESC_INDICATOR_PTR: + if (!RecNumber) + ptr = opts->bookmark->used; + else + { + ptr = opts->bindings[RecNumber - 1].used; + } + break; + case SQL_DESC_OCTET_LENGTH_PTR: + 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 (BufferLength) + { + case 0: + case SQL_IS_INTEGER: + len = 4; + *((SQLINTEGER *) Value) = ival; + break; + case SQL_IS_UINTEGER: + len = 4; + *((UInt4 *) Value) = ival; + break; + case SQL_IS_SMALLINT: + len = 2; + *((SQLSMALLINT *) Value) = (SQLSMALLINT) ival; + break; + case SQL_IS_USMALLINT: + len = 2; + *((SQLUSMALLINT *) Value) = (SQLUSMALLINT) 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; + PTR ptr = NULL; + const APDFields *opts = SC_get_APD(stmt); + + len = 4; + switch (FieldIdentifier) + { + case SQL_DESC_ARRAY_SIZE: + ival = opts->paramset_size; + break; + case SQL_DESC_ARRAY_STATUS_PTR: + ptr = opts->param_operation_ptr; + break; + case SQL_DESC_BIND_OFFSET_PTR: + 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: + ptr = opts->parameters[RecNumber - 1].buffer; + break; + case SQL_DESC_INDICATOR_PTR: + 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: + 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_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 (BufferLength) + { + 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_SMALLINT: + len = 2; + *((SQLSMALLINT *) Value) = (SQLSMALLINT) ival; + break; + case SQL_IS_USMALLINT: + len = 2; + *((SQLUSMALLINT *) Value) = (SQLUSMALLINT) 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; + PTR ptr = NULL; + const IRDFields *opts = SC_get_IRD(stmt); + + switch (FieldIdentifier) + { + case SQL_DESC_ARRAY_STATUS_PTR: + ptr = opts->rowStatusArray; + break; + case SQL_DESC_ROWS_PROCESSED_PTR: + ptr = opts->rowsFetched; + 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; + } + switch (BufferLength) + { + 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_SMALLINT: + len = 2; + *((SQLSMALLINT *) Value) = (SQLSMALLINT) ival; + break; + case SQL_IS_USMALLINT: + len = 2; + *((SQLUSMALLINT *) Value) = (SQLUSMALLINT) 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; + 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: - stmt->options.param_status_ptr = (SQLUSMALLINT *) Value; + ptr = ipdopts->param_status_ptr; break; case SQL_DESC_ROWS_PROCESSED_PTR: - stmt->options.param_processed_ptr = (SQLUINTEGER *) Value; + 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_SCALE: + ival = apdopts->parameters[RecNumber - 1].scale ; 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: + 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_OPTION_IDENTIFIER; + stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; + } + switch (BufferLength) + { + 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_SMALLINT: + len = 2; + *((SQLSMALLINT *) Value) = (SQLSMALLINT) ival; + break; + case SQL_IS_USMALLINT: + len = 2; + *((SQLUSMALLINT *) Value) = (SQLUSMALLINT) ival; + break; + case SQL_IS_POINTER: + len = 4; + *((void **)Value) = ptr; + break; } + + if (StringLength) + *StringLength = len; return ret; } @@ -332,51 +1050,51 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle, switch (Attribute) { case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */ - Value = stmt->options.bookmark_ptr; + *((void **) Value) = stmt->options.bookmark_ptr; len = 4; break; case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */ - Value = stmt->options.param_offset_ptr; + *((SQLUINTEGER **) Value) = SC_get_APD(stmt)->param_offset_ptr; len = 4; break; case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ - *((SQLUINTEGER *) Value) = stmt->options.param_bind_type; + *((SQLUINTEGER *) Value) = SC_get_APD(stmt)->param_bind_type; len = 4; break; case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */ - Value = stmt->options.param_operation_ptr; + *((SQLUSMALLINT **) Value) = SC_get_APD(stmt)->param_operation_ptr; len = 4; break; case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */ - Value = stmt->options.param_status_ptr; + *((SQLUSMALLINT **) Value) = SC_get_IPD(stmt)->param_status_ptr; len = 4; break; case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ - Value = stmt->options.param_processed_ptr; + *((SQLUINTEGER **) Value) = SC_get_IPD(stmt)->param_processed_ptr; len = 4; break; case SQL_ATTR_PARAMSET_SIZE: /* 22 */ - *((SQLUINTEGER *) Value) = stmt->options.paramset_size; + *((SQLUINTEGER *) Value) = SC_get_APD(stmt)->paramset_size; len = 4; break; case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */ - Value = stmt->options.row_offset_ptr; + *((SQLUINTEGER **) Value) = SC_get_ARD(stmt)->row_offset_ptr; len = 4; break; case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */ - Value = stmt->options.row_operation_ptr; + *((SQLUSMALLINT **) Value) = SC_get_ARD(stmt)->row_operation_ptr; len = 4; break; case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ - Value = stmt->options.rowStatusArray; + *((SQLUSMALLINT **) Value) = SC_get_IRD(stmt)->rowStatusArray; len = 4; break; case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ - Value = stmt->options.rowsFetched; + *((SQLUINTEGER **) Value) = SC_get_IRD(stmt)->rowsFetched; len = 4; break; case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ - *((SQLUINTEGER *) Value) = stmt->options.rowset_size; + *((SQLUINTEGER *) Value) = SC_get_ARD(stmt)->rowset_size; len = 4; break; case SQL_ATTR_APP_ROW_DESC: /* 10010 */ @@ -418,6 +1136,7 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle, SQLINTEGER StringLength) { ConnectionClass *conn = (ConnectionClass *) ConnectionHandle; + RETCODE ret = SQL_SUCCESS; mylog("PGAPI_SetConnectAttr %d\n", Attribute); switch (Attribute) @@ -430,8 +1149,54 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle, 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 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 */ @@ -446,7 +1211,7 @@ PGAPI_SetDescField(SQLHDESC DescriptorHandle, StatementClass *stmt; static const char *func = "PGAPI_SetDescField"; - mylog("%s h=%u rec=%d field=%d val=%x\n", func, DescriptorHandle, RecNumber, FieldIdentifier, Value); + 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; @@ -469,7 +1234,11 @@ PGAPI_SetDescField(SQLHDESC DescriptorHandle, 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; } @@ -511,37 +1280,37 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle, stmt->options.bookmark_ptr = Value; break; case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */ - stmt->options.param_offset_ptr = (SQLUINTEGER *) Value; + SC_get_APD(stmt)->param_offset_ptr = (SQLUINTEGER *) Value; break; case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ - stmt->options.param_bind_type = (SQLUINTEGER) Value; + SC_get_APD(stmt)->param_bind_type = (SQLUINTEGER) Value; break; case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */ - stmt->options.param_operation_ptr = Value; + SC_get_APD(stmt)->param_operation_ptr = Value; break; case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */ - stmt->options.param_status_ptr = (SQLUSMALLINT *) Value; + SC_get_IPD(stmt)->param_status_ptr = (SQLUSMALLINT *) Value; break; case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ - stmt->options.param_processed_ptr = (SQLUINTEGER *) Value; + SC_get_IPD(stmt)->param_processed_ptr = (SQLUINTEGER *) Value; break; case SQL_ATTR_PARAMSET_SIZE: /* 22 */ - stmt->options.paramset_size = (SQLUINTEGER) Value; + SC_get_APD(stmt)->paramset_size = (SQLUINTEGER) Value; break; case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */ - stmt->options.row_offset_ptr = (SQLUINTEGER *) Value; + SC_get_ARD(stmt)->row_offset_ptr = (SQLUINTEGER *) Value; break; case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */ - stmt->options.row_operation_ptr = Value; + SC_get_ARD(stmt)->row_operation_ptr = Value; break; case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ - stmt->options.rowStatusArray = (SQLUSMALLINT *) Value; + SC_get_IRD(stmt)->rowStatusArray = (SQLUSMALLINT *) Value; break; case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ - stmt->options.rowsFetched = (SQLUINTEGER *) Value; + SC_get_IRD(stmt)->rowsFetched = (SQLUINTEGER *) Value; break; case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ - stmt->options.rowset_size = (SQLUINTEGER) Value; + SC_get_ARD(stmt)->rowset_size = (SQLUINTEGER) Value; break; default: return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value); |