/*------- * 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 #include #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; if (Value == NULL) { CC_set_error(conn, CONN_VALUE_OUT_OF_RANGE, "Invalid Connection value", "PGAPI_GetConnectOption"); return SQL_ERROR; } 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; }