driver/odbc.c (1,135 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ #include "log.h" #include "tracing.h" #include "handles.h" #include "info.h" #include "connect.h" #include "queries.h" #include "convert.h" #include "catalogue.h" #include "tinycbor.h" #define RET_NOT_IMPLEMENTED(hnd) \ do { \ ERR("not implemented."); \ RET_HDIAGS(hnd, SQL_STATE_HYC00); \ } while (0) #ifdef WITH_OAPI_TIMING volatile LONG64 api_ticks = 0; clock_t thread_local in_ticks = 0; #endif /* WITH_API_TIMING */ static BOOL driver_init() { int cnt; wchar_t exe_path[MAX_PATH + 1]; if (! log_init()) { return FALSE; } #ifndef NDEBUG if (_gf_log) { ERR("leak reporting: on."); /* force create the log handle */ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _gf_log->handle); _CrtSetReportFile(_CRT_ERROR, _gf_log->handle); _CrtSetReportFile(_CRT_ASSERT, _gf_log->handle); } #endif /* !NDEBUG */ cnt = GetModuleFileName(/*handle*/NULL, exe_path, sizeof(exe_path)/sizeof(exe_path[0])); if (cnt <= 0) { ERRN("failed to read current process name."); } else { INFO("calling application: " LWPDL, cnt, exe_path); } INFO("initializing driver."); if (! queries_init()) { return FALSE; } convert_init(); if (! connect_init()) { return FALSE; } return TRUE; } static void driver_cleanup() { connect_cleanup(); tinycbor_cleanup(); # ifdef WITH_EXTENDED_BUFF_LOG cstr_hex_dump(NULL); /* util.[ch] */ # endif /* WITH_EXTENDED_BUFF_LOG */ } BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to DLL module DWORD fdwReason, // reason for calling function LPVOID lpReserved) // reserved { SQLWCHAR path[MAX_PATH]; // Perform actions based on the reason for calling. switch (fdwReason) { // Initialize once for each new process. // Return FALSE to fail DLL load. case DLL_PROCESS_ATTACH: if (! driver_init()) { return FALSE; } INFO("process %u attached.", GetCurrentProcessId()); if (GetModuleFileNameW(NULL, path, sizeof(path)/sizeof(*path)) > 0) { INFO("process path: `" PFWP_DESC "`.", path); } break; // Do thread-specific initialization. case DLL_THREAD_ATTACH: DBG("thread %u attached.", GetCurrentThreadId()); break; // Do thread-specific cleanup. case DLL_THREAD_DETACH: DBG("thread %u dettached.", GetCurrentThreadId()); break; // Perform any necessary cleanup. case DLL_PROCESS_DETACH: driver_cleanup(); #ifndef NDEBUG if (_gf_log) { ERR("dumping tracked leaks (log.c leak is safe to ignore):"); /* _CrtDumpMemoryLeaks() will always report at least one leak, * that of the allocated logger itself that the function uses * to log into. This is freed below, in log_cleanup(). */ ERR("leaks dumped: %d.", _CrtDumpMemoryLeaks()); } #endif /* !NDEBUG */ #ifdef WITH_OAPI_TIMING INFO("total in-driver time (secs): %.3f.", (float)api_ticks / CLOCKS_PER_SEC); #endif /* WITH_OAPI_TIMING */ INFO("process %u detaching.", GetCurrentProcessId()); log_cleanup(); break; } return TRUE; } /* * Connecting to a data source */ SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, _Out_ SQLHANDLE *OutputHandle) { SQLRETURN ret; TRACE3(_IN, InputHandle, "dpp", HandleType, InputHandle, OutputHandle); /* no synchronization required */ ret = EsSQLAllocHandle(HandleType, InputHandle, OutputHandle); TRACE4(_OUT, InputHandle, "dhpp", ret, HandleType, InputHandle, *OutputHandle); return ret; } /* * https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/unicode-drivers : * """ * A Unicode driver must export SQLConnectW to be recognized as a Unicode * driver by the Driver Manager. * """ */ SQLRETURN SQL_API SQLConnectW ( SQLHDBC hdbc, _In_reads_(cchDSN) SQLWCHAR *szDSN, SQLSMALLINT cchDSN, _In_reads_(cchUID) SQLWCHAR *szUID, SQLSMALLINT cchUID, _In_reads_(cchAuthStr) SQLWCHAR *szAuthStr, SQLSMALLINT cchAuthStr ) { #ifndef NDEBUG /* don't print the PWD */ const char *fmt_in = "pWhWhWh"; const char *fmt_out = "dpWhWhWh"; #else /* NDEBUG */ const char *fmt_in = "pWhWhph"; const char *fmt_out = "dpWhWhph"; #endif /* NDEBUG */ SQLRETURN ret; TRACE7(_IN, hdbc, fmt_in, hdbc, szDSN, cchDSN, szUID, cchUID, szAuthStr, cchAuthStr); HND_LOCK(hdbc); ret = EsSQLConnectW(hdbc, szDSN, cchDSN, szUID, cchUID, szAuthStr, cchAuthStr); HND_UNLOCK(hdbc); TRACE8(_OUT, hdbc, fmt_out, ret, hdbc, szDSN, cchDSN, szUID, cchUID, szAuthStr, cchAuthStr); return ret; } SQLRETURN SQL_API SQLDriverConnectW ( SQLHDBC hdbc, SQLHWND hwnd, _In_reads_(cchConnStrIn) SQLWCHAR *szConnStrIn, SQLSMALLINT cchConnStrIn, _Out_writes_opt_(cchConnStrOutMax) SQLWCHAR *szConnStrOut, SQLSMALLINT cchConnStrOutMax, _Out_opt_ SQLSMALLINT *pcchConnStrOut, SQLUSMALLINT fDriverCompletion ) { #ifndef NDEBUG /* don't print the PWD */ const char *fmt_in = "ppWhphpH"; const char *fmt_out = "dppWhWhtH"; #else /* NDEBUG */ const char *fmt_in = "ppphphpH"; const char *fmt_out = "dppphWhtH"; #endif /* NDEBUG */ SQLRETURN ret; TRACE8(_IN, hdbc, fmt_in, hdbc, hwnd, szConnStrIn, cchConnStrIn, szConnStrOut, cchConnStrOutMax, pcchConnStrOut, fDriverCompletion); HND_LOCK(hdbc); ret = EsSQLDriverConnectW(hdbc, hwnd, szConnStrIn, cchConnStrIn, szConnStrOut, cchConnStrOutMax, pcchConnStrOut, fDriverCompletion); HND_UNLOCK(hdbc); TRACE9(_OUT, hdbc, fmt_out, ret, hdbc, hwnd, szConnStrIn, cchConnStrIn, szConnStrOut, cchConnStrOutMax, pcchConnStrOut, fDriverCompletion); return ret; } SQLRETURN SQL_API SQLBrowseConnectW ( SQLHDBC hdbc, _In_reads_(cchConnStrIn) SQLWCHAR *szConnStrIn, SQLSMALLINT cchConnStrIn, _Out_writes_opt_(cchConnStrOutMax) SQLWCHAR *szConnStrOut, SQLSMALLINT cchConnStrOutMax, _Out_opt_ SQLSMALLINT *pcchConnStrOut ) { RET_NOT_IMPLEMENTED(hdbc); } SQLRETURN SQL_API SQLGetInfoW(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, _Out_writes_bytes_opt_(BufferLength) SQLPOINTER InfoValue, SQLSMALLINT BufferLength, _Out_opt_ SQLSMALLINT *StringLengthPtr) { SQLRETURN ret; TRACE5(_IN, ConnectionHandle, "pHphp", ConnectionHandle, InfoType, InfoValue, BufferLength, StringLengthPtr); /* Note_sync: no synchronization really required for setting/getting of * integer attributes (atomic) or string ones (= reading static string * locations), but error handling involves posting an SQL state & string, * which needs serialization. */ HND_LOCK(ConnectionHandle); ret = EsSQLGetInfoW(ConnectionHandle, InfoType, InfoValue, BufferLength, StringLengthPtr); HND_UNLOCK(ConnectionHandle); TRACE6(_OUT, ConnectionHandle, "dpHpht", ret, ConnectionHandle, InfoType, InfoValue, BufferLength, StringLengthPtr); return ret; } SQLRETURN SQL_API SQLGetFunctions(SQLHDBC ConnectionHandle, SQLUSMALLINT FunctionId, _Out_writes_opt_ (_Inexpressible_("Buffer length pfExists points to depends on fFunction value.")) SQLUSMALLINT *Supported) { SQLRETURN ret; TRACE3(_IN, ConnectionHandle, "pHp", ConnectionHandle, FunctionId, Supported); /* no synchronization required */ ret = EsSQLGetFunctions(ConnectionHandle, FunctionId, Supported); TRACE4(_IN, ConnectionHandle, "dpHT", ret, ConnectionHandle, FunctionId, Supported); return ret; } SQLRETURN SQL_API SQLGetTypeInfoW( SQLHSTMT StatementHandle, SQLSMALLINT DataType) { SQLRETURN ret; TRACE2(_IN, StatementHandle, "ph", StatementHandle, DataType); HND_LOCK(StatementHandle); ret = EsSQLGetTypeInfoW(StatementHandle, DataType); HND_UNLOCK(StatementHandle); TRACE3(_OUT, StatementHandle, "dph", ret, StatementHandle, DataType); return ret; } /* * * Setting and retrieving driver attributes * */ SQLRETURN SQL_API SQLSetConnectAttrW( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, _In_reads_bytes_opt_(StringLength) SQLPOINTER Value, SQLINTEGER StringLength) { SQLRETURN ret; TRACE4(_IN, ConnectionHandle, "plpl", ConnectionHandle, Attribute, Value, StringLength); HND_LOCK(ConnectionHandle); /* see Note_sync above */ ret = EsSQLSetConnectAttrW(ConnectionHandle, Attribute, Value, StringLength); HND_UNLOCK(ConnectionHandle); TRACE5(_OUT, ConnectionHandle, "dplpl", ret, ConnectionHandle, Attribute, Value, StringLength); return ret; } SQLRETURN SQL_API SQLGetConnectAttrW( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, _Out_writes_opt_(_Inexpressible_(cbValueMax)) SQLPOINTER ValuePtr, SQLINTEGER BufferLength, _Out_opt_ SQLINTEGER *StringLengthPtr) { SQLRETURN ret; TRACE5(_IN, ConnectionHandle, "plplp", ConnectionHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr); HND_LOCK(ConnectionHandle); ret = EsSQLGetConnectAttrW(ConnectionHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr); HND_UNLOCK(ConnectionHandle); TRACE6(_OUT, ConnectionHandle, "dplplg", ret, ConnectionHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr); return ret; } SQLRETURN SQL_API SQLSetEnvAttr( SQLHENV EnvironmentHandle, SQLINTEGER Attribute, _In_reads_bytes_opt_(StringLength) SQLPOINTER Value, SQLINTEGER StringLength) { SQLRETURN ret; TRACE4(_IN, EnvironmentHandle, "plpl", EnvironmentHandle, Attribute, Value, StringLength); HND_LOCK(EnvironmentHandle); /* see Note_sync above */ ret = EsSQLSetEnvAttr(EnvironmentHandle, Attribute, Value, StringLength); HND_UNLOCK(EnvironmentHandle); TRACE5(_OUT, EnvironmentHandle, "dplpl", ret, EnvironmentHandle, Attribute, Value, StringLength); return ret; } SQLRETURN SQL_API SQLGetEnvAttr( SQLHENV EnvironmentHandle, SQLINTEGER Attribute, _Out_writes_(_Inexpressible_(BufferLength)) SQLPOINTER Value, SQLINTEGER BufferLength, _Out_opt_ SQLINTEGER *StringLength) { SQLRETURN ret; TRACE5(_IN, EnvironmentHandle, "plplp", EnvironmentHandle, Attribute, Value, BufferLength, StringLength); HND_LOCK(EnvironmentHandle); /* see Note_sync above */ ret = EsSQLGetEnvAttr(EnvironmentHandle, Attribute, Value, BufferLength, StringLength); HND_UNLOCK(EnvironmentHandle); TRACE6(_OUT, EnvironmentHandle, "dplplg", ret, EnvironmentHandle, Attribute, Value, BufferLength, StringLength); return ret; } SQLRETURN SQL_API SQLSetStmtAttrW( SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength) { SQLRETURN ret; TRACE4(_IN, StatementHandle, "plpl", StatementHandle, Attribute, ValuePtr, BufferLength); HND_LOCK(StatementHandle); ret = EsSQLSetStmtAttrW(StatementHandle, Attribute, ValuePtr, BufferLength); HND_UNLOCK(StatementHandle); TRACE5(_OUT, StatementHandle, "dplpl", ret, StatementHandle, Attribute, ValuePtr, BufferLength); return ret; } SQLRETURN SQL_API SQLGetStmtAttrW( SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr) { SQLRETURN ret; TRACE5(_IN, StatementHandle, "plplp", StatementHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr); HND_LOCK(StatementHandle); ret = EsSQLGetStmtAttrW(StatementHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr); HND_UNLOCK(StatementHandle); TRACE6(_OUT, StatementHandle, "dplplg", ret, StatementHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr); return ret; } /* * * Setting and retrieving descriptor fields * */ SQLRETURN SQL_API SQLGetDescFieldW( SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, _Out_writes_opt_(_Inexpressible_(BufferLength)) SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr) { SQLRETURN ret; TRACE6(_IN, DescriptorHandle, "phhplp", DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, StringLengthPtr); /* Note_stmt_sync: API descriptor access is serialized by statement's * mutex, not descriptor's, since statement functions working on * descriptors won't lock these, but will lock the statement instead * (which keeps the code simpler; besides, no "high-speed" concurrent * thread access on descriptors is necessary anyway). */ HND_LOCK(DSCH(DescriptorHandle)->hdr.stmt); ret = EsSQLGetDescFieldW(DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, StringLengthPtr); HND_UNLOCK(DSCH(DescriptorHandle)->hdr.stmt); TRACE7(_OUT, DescriptorHandle, "dphhplg", ret, DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, StringLengthPtr); return ret; } SQLRETURN SQL_API SQLSetDescFieldW ( SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, SQLPOINTER Value, SQLINTEGER BufferLength ) { SQLRETURN ret; TRACE5(_IN, DescriptorHandle, "phhpl", DescriptorHandle, RecNumber, FieldIdentifier, Value, BufferLength); HND_LOCK(DSCH(DescriptorHandle)->hdr.stmt); /* see Note_stmt_sync */ ret = EsSQLSetDescFieldW(DescriptorHandle, RecNumber, FieldIdentifier, Value, BufferLength); HND_UNLOCK(DSCH(DescriptorHandle)->hdr.stmt); TRACE6(_OUT, DescriptorHandle, "dphhpl", ret, DescriptorHandle, RecNumber, FieldIdentifier, Value, BufferLength); return ret; } SQLRETURN SQL_API SQLGetDescRecW( SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, _Out_writes_opt_(BufferLength) SQLWCHAR *Name, _Out_opt_ SQLSMALLINT BufferLength, _Out_opt_ SQLSMALLINT *StringLengthPtr, _Out_opt_ SQLSMALLINT *TypePtr, _Out_opt_ SQLSMALLINT *SubTypePtr, _Out_opt_ SQLLEN *LengthPtr, _Out_opt_ SQLSMALLINT *PrecisionPtr, _Out_opt_ SQLSMALLINT *ScalePtr, _Out_opt_ SQLSMALLINT *NullablePtr) { RET_NOT_IMPLEMENTED(DescriptorHandle); } /* * "When the application sets the SQL_DESC_TYPE field, the driver checks that * other fields that specify the type are valid and consistent." AND: * * "A consistency check is performed by the driver automatically whenever an * application sets the SQL_DESC_DATA_PTR field of the APD, ARD, or IPD. * Whenever this field is set, the driver checks that the value of the * SQL_DESC_TYPE field and the values applicable to the SQL_DESC_TYPE field in * the same record are valid and consistent. * * "The SQL_DESC_DATA_PTR field of an IPD is not normally set; however, an * application can do so to force a consistency check of IPD fields. The value * that the SQL_DESC_DATA_PTR field of the IPD is set to is not actually * stored and cannot be retrieved by a call to SQLGetDescField or * SQLGetDescRec; the setting is made only to force the consistency check. A * consistency check cannot be performed on an IRD." * * "A call to SQLSetDescRec sets the interval leading precision to the default * but sets the interval seconds precision (in the SQL_DESC_PRECISION field) * to the value of its Precision argument" */ SQLRETURN SQL_API SQLSetDescRec( SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT Type, SQLSMALLINT SubType, SQLLEN Length, SQLSMALLINT Precision, SQLSMALLINT Scale, _Inout_updates_bytes_opt_(Length) SQLPOINTER Data, _Inout_opt_ SQLLEN *StringLength, _Inout_opt_ SQLLEN *Indicator) { /* * https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/column-wise-binding : * "When using column-wise binding, an application binds one or two, or in * some cases three, arrays to each column for which data is to be * returned. The first array holds the data values, and the second array * holds length/indicator buffers. Indicators and length values can be * stored in separate buffers by setting the SQL_DESC_INDICATOR_PTR and * SQL_DESC_OCTET_LENGTH_PTR descriptor fields to different values; if * this is done, a third array is bound. Each array contains as many * elements as there are rows in the rowset." */ /* needs to trigger consistency_check */ RET_NOT_IMPLEMENTED(DescriptorHandle); } /* * "SQLCopyDesc function is called to copy the fields of one descriptor to * another descriptor. Fields can be copied only to an application descriptor * or an IPD, but not to an IRD. Fields can be copied from any type of * descriptor. Only those fields that are defined for both the source and * target descriptors are copied." (with the exception of SQL_DESC_ALLOC_TYPE * field, which can't be changed) * * "An ARD on one statement handle can serve as the APD on another statement * handle." (= copying data between tables w/o extra copy in App; only if * SQL_MAX_CONCURRENT_ACTIVITIES > 1) */ SQLRETURN SQL_API SQLCopyDesc(SQLHDESC SourceDescHandle, SQLHDESC TargetDescHandle) { RET_NOT_IMPLEMENTED(SourceDescHandle); } /* * "The prepared statement associated with the statement handle can be * re-executed by calling SQLExecute until the application frees the statement * with a call to SQLFreeStmt with the SQL_DROP option or until the statement * handle is used in a call to SQLPrepare, SQLExecDirect, or one of the * catalog functions (SQLColumns, SQLTables, and so on)." */ SQLRETURN SQL_API SQLPrepareW ( SQLHSTMT hstmt, _In_reads_(cchSqlStr) SQLWCHAR *szSqlStr, SQLINTEGER cchSqlStr ) { SQLRETURN ret; TRACE3(_IN, hstmt, "pWl", hstmt, szSqlStr, cchSqlStr); HND_LOCK(hstmt); ret = EsSQLPrepareW(hstmt, szSqlStr, cchSqlStr); HND_UNLOCK(hstmt); TRACE4(_OUT, hstmt, "dpWl", ret, hstmt, szSqlStr, cchSqlStr); return ret; } /* * https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/sending-long-data */ SQLRETURN SQL_API SQLBindParameter( SQLHSTMT hstmt, SQLUSMALLINT ipar, SQLSMALLINT fParamType, SQLSMALLINT fCType, SQLSMALLINT fSqlType, SQLULEN cbColDef, SQLSMALLINT ibScale, SQLPOINTER rgbValue, SQLLEN cbValueMax, SQLLEN *pcbValue) { SQLRETURN ret; TRACE10(_IN, hstmt, "pHhhhZhpzp", hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, cbValueMax, pcbValue); HND_LOCK(hstmt); ret = EsSQLBindParameter(hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, cbValueMax, pcbValue); HND_UNLOCK(hstmt); TRACE11(_OUT, hstmt, "dpHhhhZhpzn", ret, hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, cbValueMax, pcbValue); return ret; } SQLRETURN SQL_API SQLGetCursorNameW ( SQLHSTMT hstmt, _Out_writes_opt_(cchCursorMax) SQLWCHAR *szCursor, SQLSMALLINT cchCursorMax, _Out_opt_ SQLSMALLINT *pcchCursor ) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLSetCursorNameW ( SQLHSTMT hstmt, _In_reads_(cchCursor) SQLWCHAR *szCursor, SQLSMALLINT cchCursor ) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLSetScrollOptions( /* Use SQLSetStmtOptions */ SQLHSTMT hstmt, SQLUSMALLINT fConcurrency, SQLLEN crowKeyset, SQLUSMALLINT crowRowset) { RET_NOT_IMPLEMENTED(hstmt); } /* * * Submitting requests * */ /* * "In the IPD, this header field points to a parameter status array * containing status information for each set of parameter values after a call * to SQLExecute or SQLExecDirect." = .array_status_ptr * * "In the APD, this header field points to a parameter operation array of * values that can be set by the application to indicate whether this set of * parameters is to be ignored when SQLExecute or SQLExecDirect is called." * = .array_status_ptr * "If no elements of the array are set, all sets of parameters in the array * are used in the SQLExecute or SQLExecDirect calls." */ SQLRETURN SQL_API SQLExecute(SQLHSTMT hstmt) { SQLRETURN ret; TRACE1(_IN, hstmt, "p", hstmt); HND_LOCK(hstmt); ret = EsSQLExecute(hstmt); HND_UNLOCK(hstmt); TRACE2(_OUT, hstmt, "dp", ret, hstmt); return ret; } /* * "In the IPD, this header field points to a parameter status array * containing status information for each set of parameter values after a call * to SQLExecute or SQLExecDirect." = .array_status_ptr * * "In the APD, this header field points to a parameter operation array of * values that can be set by the application to indicate whether this set of * parameters is to be ignored when SQLExecute or SQLExecDirect is called." * = .array_status_ptr * "If no elements of the array are set, all sets of parameters in the array * are used in the SQLExecute or SQLExecDirect calls." */ SQLRETURN SQL_API SQLExecDirectW ( SQLHSTMT hstmt, _In_reads_opt_(TextLength) SQLWCHAR *szSqlStr, SQLINTEGER cchSqlStr ) { SQLRETURN ret; TRACE3(_IN, hstmt, "pWl", hstmt, szSqlStr, cchSqlStr); HND_LOCK(hstmt); ret = EsSQLExecDirectW(hstmt, szSqlStr, cchSqlStr); HND_UNLOCK(hstmt); TRACE4(_OUT, hstmt, "dpWl", ret, hstmt, szSqlStr, cchSqlStr); return ret; } SQLRETURN SQL_API SQLNativeSqlW ( SQLHDBC hdbc, _In_reads_(cchSqlStrIn) SQLWCHAR *szSqlStrIn, SQLINTEGER cchSqlStrIn, _Out_writes_opt_(cchSqlStrMax) SQLWCHAR *szSqlStr, SQLINTEGER cchSqlStrMax, SQLINTEGER *pcchSqlStr ) { SQLRETURN ret; TRACE6(_IN, hdbc, "pplplp", hdbc, szSqlStrIn, cchSqlStrIn, szSqlStr, cchSqlStrMax, pcchSqlStr); HND_LOCK(hdbc); ret = EsSQLNativeSqlW(hdbc, szSqlStrIn, cchSqlStrIn, szSqlStr, cchSqlStrMax, pcchSqlStr); HND_UNLOCK(hdbc); TRACE7(_OUT, hdbc, "dpplplg", ret, hdbc, szSqlStrIn, cchSqlStrIn, szSqlStr, cchSqlStrMax, pcchSqlStr); return ret; } /* * "drivers are capable of setting the fields of the IPD after a parameterized * query has been prepared. The descriptor fields are automatically populated * with information about the parameter, including the data type, precision, * scale, and other characteristics. This is equivalent to supporting * SQLDescribeParam." * Note: see EsSQLDescribeColW() for size & dec digits impl. */ SQLRETURN SQL_API SQLDescribeParam( SQLHSTMT hstmt, SQLUSMALLINT ipar, _Out_opt_ SQLSMALLINT *pfSqlType, _Out_opt_ SQLULEN *pcbParamDef, _Out_opt_ SQLSMALLINT *pibScale, _Out_opt_ SQLSMALLINT *pfNullable) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLNumParams( SQLHSTMT hstmt, _Out_opt_ SQLSMALLINT *pcpar) { SQLRETURN ret; TRACE2(_IN, hstmt, "pp", hstmt, pcpar); HND_LOCK(hstmt); ret = EsSQLNumParams(hstmt, pcpar); HND_UNLOCK(hstmt); TRACE3(_OUT, hstmt, "dpt", ret, hstmt, pcpar); return ret; } SQLRETURN SQL_API SQLParamData(SQLHSTMT StatementHandle, _Out_opt_ SQLPOINTER *Value) { RET_NOT_IMPLEMENTED(StatementHandle); } SQLRETURN SQL_API SQLPutData(SQLHSTMT StatementHandle, _In_reads_(_Inexpressible_(StrLen_or_Ind)) SQLPOINTER Data, SQLLEN StrLen_or_Ind) { RET_NOT_IMPLEMENTED(StatementHandle); } /* * * Retrieving results and information about results * */ SQLRETURN SQL_API SQLRowCount(_In_ SQLHSTMT StatementHandle, _Out_ SQLLEN *RowCount) { SQLRETURN ret; TRACE2(_IN, StatementHandle, "pp", StatementHandle, RowCount); HND_LOCK(StatementHandle); /* see Note_sync */ ret = EsSQLRowCount(StatementHandle, RowCount); HND_UNLOCK(StatementHandle); TRACE3(_OUT, StatementHandle, "dpn", ret, StatementHandle, RowCount); return ret; } SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle, _Out_ SQLSMALLINT *ColumnCount) { SQLRETURN ret; TRACE2(_IN, StatementHandle, "pp", StatementHandle, ColumnCount); HND_LOCK(StatementHandle); /* see Note_sync */ ret = EsSQLNumResultCols(StatementHandle, ColumnCount); HND_UNLOCK(StatementHandle); TRACE3(_OUT, StatementHandle, "dpt", ret, StatementHandle, ColumnCount); return ret; } SQLRETURN SQL_API SQLDescribeColW ( SQLHSTMT hstmt, SQLUSMALLINT icol, _Out_writes_opt_(cchColNameMax) SQLWCHAR *szColName, SQLSMALLINT cchColNameMax, _Out_opt_ SQLSMALLINT *pcchColName, _Out_opt_ SQLSMALLINT *pfSqlType, _Out_opt_ SQLULEN *pcbColDef, _Out_opt_ SQLSMALLINT *pibScale, _Out_opt_ SQLSMALLINT *pfNullable ) { SQLRETURN ret; TRACE9(_IN, hstmt, "pHphppppp", hstmt, icol, szColName, cchColNameMax, pcchColName, pfSqlType, pcbColDef, pibScale, pfNullable); HND_LOCK(hstmt); ret = EsSQLDescribeColW(hstmt, icol, szColName, cchColNameMax, pcchColName, pfSqlType, pcbColDef, pibScale, pfNullable); HND_UNLOCK(hstmt); TRACE10(_OUT, hstmt, "dpHphttNtt", ret, hstmt, icol, szColName, cchColNameMax, pcchColName, pfSqlType, pcbColDef, pibScale, pfNullable); return ret; } SQLRETURN SQL_API SQLColAttributeW ( SQLHSTMT hstmt, SQLUSMALLINT iCol, SQLUSMALLINT iField, _Out_writes_bytes_opt_(cbDescMax) SQLPOINTER pCharAttr, SQLSMALLINT cbDescMax, _Out_opt_ SQLSMALLINT *pcbCharAttr, _Out_opt_ #ifdef _WIN64 SQLLEN *pNumAttr #else /* _WIN64 */ SQLPOINTER pNumAttr #endif /* _WIN64 */ ) { SQLRETURN ret; TRACE7(_IN, hstmt, "pHHphpp", hstmt, iCol, iField, pCharAttr, cbDescMax, pcbCharAttr, pNumAttr); HND_LOCK(hstmt); ret = EsSQLColAttributeW(hstmt, iCol, iField, pCharAttr, cbDescMax, pcbCharAttr, pNumAttr); HND_UNLOCK(hstmt); TRACE8(_OUT, hstmt, "dpHHphtn", ret, hstmt, iCol, iField, pCharAttr, cbDescMax, pcbCharAttr, pNumAttr); return ret; } SQLRETURN SQL_API SQLBindCol( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, _Inout_updates_opt_(_Inexpressible_(BufferLength)) SQLPOINTER TargetValue, SQLLEN BufferLength, _Inout_opt_ SQLLEN *StrLen_or_Ind) { SQLRETURN ret; TRACE6(_IN, StatementHandle, "pHhpzp", StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_Ind); HND_LOCK(StatementHandle); ret = EsSQLBindCol(StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_Ind); HND_UNLOCK(StatementHandle); TRACE7(_OUT, StatementHandle, "dpHhpzn", ret, StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_Ind); return ret; } SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) { SQLRETURN ret; TRACE1(_IN, StatementHandle, "p", StatementHandle); HND_LOCK(StatementHandle); ret = EsSQLFetch(StatementHandle); HND_UNLOCK(StatementHandle); TRACE2(_OUT, StatementHandle, "dp", ret, StatementHandle); return ret; } /* * "SQLFetch and SQLFetchScroll use the rowset size at the time of the call to * determine how many rows to fetch. However, SQLFetchScroll with a * FetchOrientation of SQL_FETCH_NEXT increments the cursor based on the * rowset of the previous fetch and then fetches a rowset based on the current * rowset size." * * "In the IRD, this header field points to a row status array containing * status values after a call to SQLBulkOperations, SQLFetch, SQLFetchScroll, * or SQLSetPos." = row status array of IRD (.array_status_ptr) * * "In ARDs, this field specifies the binding orientation when SQLFetchScroll * or SQLFetch is called on the associated statement handle." (.bind_type) * * "In an IRD, this SQLULEN * header field points to a buffer containing the * number of rows fetched after a call to SQLFetch or SQLFetchScroll, or the * number of rows affected in a bulk operation performed by a call to * SQLBulkOperations or SQLSetPos, including error rows." * (.rows_processed_ptr) * * "The variable that the StrLen_or_Ind argument refers to is used for both * indicator and length information. If a fetch encounters a null value for * the column, it stores SQL_NULL_DATA in this variable; otherwise, it stores * the data length in this variable. Passing a null pointer as StrLen_or_Ind * keeps the fetch operation from returning the data length but makes the * fetch fail if it encounters a null value and has no way to return * SQL_NULL_DATA." (.indicator_ptr) */ SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT StatementHandle, SQLSMALLINT FetchOrientation, SQLLEN FetchOffset) { SQLRETURN ret; TRACE3(_IN, StatementHandle, "phz", StatementHandle, FetchOrientation, FetchOffset); HND_LOCK(StatementHandle); ret = EsSQLFetchScroll(StatementHandle, FetchOrientation, FetchOffset); HND_UNLOCK(StatementHandle); TRACE4(_OUT, StatementHandle, "dphz", ret, StatementHandle, FetchOrientation, FetchOffset); return ret; } SQLRETURN SQL_API SQLGetData( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, _Out_writes_opt_(_Inexpressible_(BufferLength)) SQLPOINTER TargetValuePtr, SQLLEN BufferLength, _Out_opt_ SQLLEN *StrLen_or_IndPtr) { SQLRETURN ret; TRACE6(_IN, StatementHandle, "pHhplp", StatementHandle, ColumnNumber, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr); HND_LOCK(StatementHandle); ret = EsSQLGetData(StatementHandle, ColumnNumber, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr); HND_UNLOCK(StatementHandle); TRACE7(_OUT, StatementHandle, "dpHhpln", ret, StatementHandle, ColumnNumber, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr); return ret; } SQLRETURN SQL_API SQLSetPos( SQLHSTMT StatementHandle, SQLSETPOSIROW RowNumber, /* SQLULEN / SQLUSMALLINT */ SQLUSMALLINT Operation, SQLUSMALLINT LockType) { SQLRETURN ret; TRACE4(_IN, StatementHandle, "pZHH", StatementHandle, RowNumber, Operation, LockType); HND_LOCK(StatementHandle); ret = EsSQLSetPos(StatementHandle, RowNumber, Operation, LockType); HND_UNLOCK(StatementHandle); TRACE5(_OUT, StatementHandle, "dpZHH", ret,StatementHandle, RowNumber, Operation, LockType); return ret; } SQLRETURN SQL_API SQLBulkOperations( SQLHSTMT StatementHandle, SQLSMALLINT Operation) { SQLRETURN ret; TRACE2(_IN, StatementHandle, "ph", StatementHandle, Operation); HND_LOCK(StatementHandle); ret = EsSQLBulkOperations(StatementHandle, Operation); HND_UNLOCK(StatementHandle); TRACE3(_OUT, StatementHandle, "dph", ret, StatementHandle, Operation); return ret; } SQLRETURN SQL_API SQLMoreResults(SQLHSTMT StatementHandle) { SQLRETURN ret; TRACE1(_IN, StatementHandle, "p", StatementHandle); /* no synchronization required */ ret = EsSQLMoreResults(StatementHandle); TRACE2(_OUT, StatementHandle, "dp", ret, StatementHandle); return ret; } SQLRETURN SQL_API SQLGetDiagFieldW( SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, _Out_writes_opt_(_Inexpressible_(BufferLength)) SQLPOINTER DiagInfoPtr, SQLSMALLINT BufferLength, _Out_opt_ SQLSMALLINT *StringLengthPtr) { SQLRETURN ret; TRACE7(_IN, Handle, "hphhphp", HandleType, Handle, RecNumber, DiagIdentifier, DiagInfoPtr, BufferLength, StringLengthPtr); /* Note_diag: locking here only really makes sense for stmt and dbc, but * uniformly locking env and desc too is harmless and simple */ HND_LOCK(Handle); ret = EsSQLGetDiagFieldW(HandleType, Handle, RecNumber, DiagIdentifier, DiagInfoPtr, BufferLength, StringLengthPtr); HND_UNLOCK(Handle); TRACE8(_OUT, Handle, "dhphhpht", ret, HandleType, Handle, RecNumber, DiagIdentifier, DiagInfoPtr, BufferLength, StringLengthPtr); return ret; } SQLRETURN SQL_API SQLGetDiagRecW ( SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, _Out_writes_opt_(6) SQLWCHAR *Sqlstate, SQLINTEGER *NativeError, _Out_writes_opt_(BufferLength) SQLWCHAR *MessageText, SQLSMALLINT BufferLength, _Out_opt_ SQLSMALLINT *TextLength ) { SQLRETURN ret; TRACE8(_IN, Handle, "hphppphp", HandleType, Handle, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength); HND_LOCK(Handle); /* see Note_diag */ ret = EsSQLGetDiagRecW(HandleType, Handle, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength); HND_UNLOCK(Handle); TRACE9(_OUT, Handle, "dhphwgwht", ret, HandleType, Handle, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength); return ret; } /* * * Obtaining information about the data source's system tables * (catalog functions) * */ SQLRETURN SQL_API SQLColumnPrivilegesW( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName, _In_reads_opt_(cchColumnName) SQLWCHAR *szColumnName, SQLSMALLINT cchColumnName ) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLColumnsW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName, _In_reads_opt_(cchColumnName) SQLWCHAR *szColumnName, SQLSMALLINT cchColumnName ) { SQLRETURN ret; TRACE9(_IN, hstmt, "pWhWhWhWh", hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, szColumnName, cchColumnName); HND_LOCK(hstmt); ret = EsSQLColumnsW(hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, szColumnName, cchColumnName); HND_UNLOCK(hstmt); TRACE10(_OUT, hstmt, "dpWhWhWhWh", ret, hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, szColumnName, cchColumnName); return ret; } SQLRETURN SQL_API SQLForeignKeysW ( SQLHSTMT hstmt, _In_reads_opt_(cchPkCatalogName) SQLWCHAR *szPkCatalogName, SQLSMALLINT cchPkCatalogName, _In_reads_opt_(cchPkSchemaName) SQLWCHAR *szPkSchemaName, SQLSMALLINT cchPkSchemaName, _In_reads_opt_(cchPkTableName) SQLWCHAR *szPkTableName, SQLSMALLINT cchPkTableName, _In_reads_opt_(cchFkCatalogName) SQLWCHAR *szFkCatalogName, SQLSMALLINT cchFkCatalogName, _In_reads_opt_(cchFkSchemaName) SQLWCHAR *szFkSchemaName, SQLSMALLINT cchFkSchemaName, _In_reads_opt_(cchFkTableName) SQLWCHAR *szFkTableName, SQLSMALLINT cchFkTableName ) { SQLRETURN ret; TRACE13(_IN, hstmt, "pWhWhWhWhWhWh", hstmt, szPkCatalogName, cchPkCatalogName, szPkSchemaName, cchPkSchemaName, szPkTableName, cchPkTableName, szFkCatalogName, cchFkCatalogName, szFkSchemaName, cchFkSchemaName, szFkTableName, cchFkTableName); HND_LOCK(hstmt); ret = EsSQLForeignKeysW(hstmt, szPkCatalogName, cchPkCatalogName, szPkSchemaName, cchPkSchemaName, szPkTableName, cchPkTableName, szFkCatalogName, cchFkCatalogName, szFkSchemaName, cchFkSchemaName, szFkTableName, cchFkTableName); HND_UNLOCK(hstmt); TRACE14(_OUT, hstmt, "dpWhWhWhWhWhWh", ret, hstmt, szPkCatalogName, cchPkCatalogName, szPkSchemaName, cchPkSchemaName, szPkTableName, cchPkTableName, szFkCatalogName, cchFkCatalogName, szFkSchemaName, cchFkSchemaName, szFkTableName, cchFkTableName); return ret; } SQLRETURN SQL_API SQLPrimaryKeysW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName ) { SQLRETURN ret; TRACE7(_IN, hstmt, "pWhWhWh", hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName); HND_LOCK(hstmt); ret = EsSQLPrimaryKeysW(hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName); HND_UNLOCK(hstmt); TRACE8(_OUT, hstmt, "dpWhWhWh", ret, hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName); return ret; } SQLRETURN SQL_API SQLProcedureColumnsW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchProcName) SQLWCHAR *szProcName, SQLSMALLINT cchProcName, _In_reads_opt_(cchColumnName) SQLWCHAR *szColumnName, SQLSMALLINT cchColumnName ) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLProceduresW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchProcName) SQLWCHAR *szProcName, SQLSMALLINT cchProcName ) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLSpecialColumnsW ( SQLHSTMT hstmt, SQLUSMALLINT fColType, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName, SQLUSMALLINT fScope, SQLUSMALLINT fNullable ) { SQLRETURN ret; TRACE10(_IN, hstmt, "pHWhWhWhHH", hstmt, fColType, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, fScope, fNullable); HND_LOCK(hstmt); ret = EsSQLSpecialColumnsW(hstmt, fColType, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, fScope, fNullable); HND_UNLOCK(hstmt); TRACE11(_OUT, hstmt, "dpHWhWhWhHH", ret, hstmt, fColType, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, fScope, fNullable); return ret; } SQLRETURN SQL_API SQLStatisticsW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName, SQLUSMALLINT fUnique, SQLUSMALLINT fAccuracy ) { SQLRETURN ret; TRACE9(_IN, hstmt, "pWhWhWhHH", hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, fUnique, fAccuracy); HND_LOCK(hstmt); ret = EsSQLStatisticsW(hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, fUnique, fAccuracy); HND_UNLOCK(hstmt); TRACE10(_OUT, hstmt, "dpWhWhWhHH", ret, hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, fUnique, fAccuracy); return ret; } SQLRETURN SQL_API SQLTablePrivilegesW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName ) { RET_NOT_IMPLEMENTED(hstmt); } SQLRETURN SQL_API SQLTablesW ( SQLHSTMT hstmt, _In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName, SQLSMALLINT cchCatalogName, _In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName, SQLSMALLINT cchSchemaName, _In_reads_opt_(cchTableName) SQLWCHAR *szTableName, SQLSMALLINT cchTableName, _In_reads_opt_(cchTableType) SQLWCHAR *szTableType, SQLSMALLINT cchTableType ) { SQLRETURN ret; TRACE9(_IN, hstmt, "pWhWhWhWh", hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, szTableType, cchTableType); HND_LOCK(hstmt); ret = EsSQLTablesW(hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, szTableType, cchTableType); HND_UNLOCK(hstmt); TRACE10(_OUT, hstmt, "dpWhWhWhWh", ret, hstmt, szCatalogName, cchCatalogName, szSchemaName, cchSchemaName, szTableName, cchTableName, szTableType, cchTableType); return ret; } /* * * Terminating a statement * */ SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) { SQLRETURN ret; TRACE2(_IN, StatementHandle, "pH", StatementHandle, Option); HND_LOCK(StatementHandle); ret = EsSQLFreeStmt(StatementHandle, Option); HND_UNLOCK(StatementHandle); TRACE3(_OUT, StatementHandle, "dpH", ret, StatementHandle, Option); return ret; } SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT StatementHandle) { SQLRETURN ret; TRACE1(_IN, StatementHandle, "p", StatementHandle); HND_LOCK(StatementHandle); ret = EsSQLCloseCursor(StatementHandle); HND_UNLOCK(StatementHandle); TRACE2(_OUT, StatementHandle, "dp", ret, StatementHandle); return ret; } SQLRETURN SQL_API SQLCancel(SQLHSTMT StatementHandle) { SQLRETURN ret; TRACE1(_IN, StatementHandle, "p", StatementHandle); HND_LOCK(StatementHandle); ret = EsSQLCancel(StatementHandle); HND_UNLOCK(StatementHandle); TRACE2(_OUT, StatementHandle, "dp", ret, StatementHandle); return ret; } SQLRETURN SQL_API SQLCancelHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle) { SQLRETURN ret; TRACE2(_IN, InputHandle, "hp", HandleType, InputHandle); HND_LOCK(InputHandle); ret = EsSQLCancelHandle(HandleType, InputHandle); HND_UNLOCK(InputHandle); TRACE3(_IN, InputHandle, "dhp", ret, HandleType, InputHandle); return ret; } SQLRETURN SQL_API SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT CompletionType) { SQLRETURN ret; TRACE3(_IN, Handle, "hph", HandleType, Handle, CompletionType); HND_LOCK(Handle); ret = EsSQLEndTran(HandleType, Handle, CompletionType); HND_UNLOCK(Handle); TRACE4(_IN, Handle, "dhph", ret, HandleType, Handle, CompletionType); return ret; } /* * * Terminating a connection * */ SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle) { SQLRETURN ret; TRACE1(_IN, ConnectionHandle, "p", ConnectionHandle); HND_LOCK(ConnectionHandle); ret = EsSQLDisconnect(ConnectionHandle); HND_UNLOCK(ConnectionHandle); TRACE2(_OUT, ConnectionHandle, "dp", ret, ConnectionHandle); return ret; } SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) { SQLRETURN ret; TRACE2(_IN, Handle, "hp", HandleType, Handle); if (! HND_TRYLOCK(Handle)) { BUGH(Handle, "handle still locked while freeing attempt."); return SQL_ERROR; } ret = EsSQLFreeHandle(HandleType, Handle); TRACE3(_OUT, NULL/*Handle's freed*/, "dhp", ret, HandleType, Handle); return ret; } /* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 tw=78 : */