Retrieve an ODBC connection attribute for a DATE_LOG_HANDLE's connection
GetDateLogOdbcConnectAttr retrieves the value of an ODBC connection attribute (via SQLGetConnectAttr) for the connection identified by OdbcLevel on the given handle. It resolves the connection context for that level and delegates to OdbcGetConnectAttrImpl() in odbc.c.
Lets callers inspect the state of a connection that is owned by a date log handle, for example the autocommit mode set with SetDateLogOdbcConnectAttr before grouping statements into a transaction ended with EndDateLogOdbcTransaction, or SQL_ATTR_CONNECTION_DEAD, which ConnectDateLogHandleToOdbcDatabase uses to detect a dead connection.
DATE_LOG_ODBC_1 through DATE_LOG_ODBC_4).SQLGetConnectAttr conventions for ValuePtr, BufferLength and StringLengthPtr.
HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) GetDateLogOdbcConnectAttr(
_In_ DATE_LOG_HANDLE hDateLogHandle,
_In_ DATE_LOG_ODBC_LEVEL OdbcLevel,
_In_ SQLINTEGER Attribute,
_Out_writes_bytes_opt_(BufferLength) SQLPOINTER ValuePtr,
_In_ SQLINTEGER BufferLength,
_Out_opt_ SQLINTEGER * StringLengthPtr
);
[In] DATE_LOG_HANDLE
A valid DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE that owns the ODBC connection. The connection slot must have been reserved with InitializeDateLogHandleOdbc and connected with ConnectDateLogHandleToOdbcDatabase.
Must not be NULL. The handle is not closed or otherwise modified.
[In] DATE_LOG_ODBC_LEVEL
Selects which of up to 4 ODBC connections on this handle to query: DATE_LOG_ODBC_1 .. DATE_LOG_ODBC_4.
[In] SQLINTEGER
The SQL_ATTR_* connection attribute identifier to read. SQL_ATTR_TRACEFILE and SQL_ATTR_CONNECTION_POOLING are unsupported.
[Out, Optional] SQLPOINTER
Caller-allocated buffer of at least BufferLength bytes that receives the attribute value. The buffer is owned by the caller; the library does not retain the pointer.
The meaning of NULL follows SQLGetConnectAttr behavior (annotated _Out_writes_bytes_opt_).
[In] SQLINTEGER
Size in bytes of the buffer pointed to by ValuePtr. Pass sizeof of the buffer for string and binary attributes; follow ODBC rules for integer attributes.
[Out, Optional] SQLINTEGER *
May be NULL. When supplied, receives the actual length of the returned value.
| Value | Meaning |
|---|---|
S_OK | The attribute was retrieved successfully. |
HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE_STATE) | No connection has been established yet at the requested OdbcLevel. |
HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED) | Attribute is SQL_ATTR_TRACEFILE or SQL_ATTR_CONNECTION_POOLING. |
Other failure HRESULT | Returned for invalid parameters or an underlying ODBC driver failure. |
FAILED/SUCCEEDED (the function is _Must_inspect_result_); do not read ValuePtr when it fails.The call operates on a connection owned by the handle. Other ODBC operations on the same connection (for example a bulk fetch with FetchDateLogHandleToOdbcDatabase) should not run concurrently on the same OdbcLevel. Date log handles can be duplicated with DuplicateDateLogHandle; duplicates share the same context and therefore the same ODBC connections.
The ODBC connection is owned exclusively by the date log context and is released when the last handle referencing that context is closed with CloseDateLogHandle. The caller owns only the buffers it passes in.
Calling the function before a connection exists at OdbcLevel yields HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE_STATE).
#include <stdio.h>
#include <Windows.h>
#include <sqlext.h>
#include "datelog.h"
int main(void)
{
HRESULT hr = E_FAIL;
HOLIDAYS_HANDLE hHolidays = NULL;
DATE_LOG_HANDLE hDateLog = NULL;
PODBC_CONNECT_PARAMS pParams = NULL;
int exitCode = 1;
SQLUINTEGER autocommit = 0;
SQLUINTEGER dead = 0;
SQLINTEGER length = 0;
char traceFile[260] = { 0 };
/* A holidays handle is created with HandleIsForHolidays; hHolidays must be NULL for that type. */
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
if (FAILED(hr)) {
printf("Holidays handle creation failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* The date log duplicates hHolidays internally; the caller still owns hHolidays. */
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
if (FAILED(hr)) {
printf("Date log creation failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Reserve and connect the first ODBC connection of the date log. */
hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("Reserving the ODBC connection failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = InitializeOdbcConnectParams(&pParams);
if (FAILED(hr)) {
printf("Creating ODBC parameters failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
hr = pParams->AddParam(pParams, "Driver", "{ODBC Driver 17 for SQL Server}");
if (SUCCEEDED(hr)) {
hr = pParams->AddParam(pParams, "Server", "localhost\\SQLEXPRESS");
}
if (SUCCEEDED(hr)) {
hr = pParams->AddParam(pParams, "Database", "MarketDates");
}
if (FAILED(hr)) {
printf("Adding an ODBC parameter failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
pParams->Trusted_Connection = ODBC_TRUE;
pParams->Encrypt = ODBC_TRUE;
hr = ConnectDateLogHandleToOdbcDatabase(hDateLog, pParams, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("Connecting failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* The parameters are no longer needed once the connection exists. */
FreeOdbcConnectParams(pParams);
pParams = NULL;
hr = GetDateLogOdbcConnectAttr(hDateLog, DATE_LOG_ODBC_1, SQL_ATTR_AUTOCOMMIT,
&autocommit, (SQLINTEGER)sizeof(autocommit), &length);
if (FAILED(hr)) {
printf("Reading SQL_ATTR_AUTOCOMMIT failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
printf("Autocommit is %s.\n", autocommit == SQL_AUTOCOMMIT_ON ? "on" : "off");
hr = GetDateLogOdbcConnectAttr(hDateLog, DATE_LOG_ODBC_1, SQL_ATTR_CONNECTION_DEAD,
&dead, (SQLINTEGER)sizeof(dead), NULL);
if (SUCCEEDED(hr)) {
printf("Connection is %s.\n", dead == SQL_CD_TRUE ? "dead" : "alive");
}
/* SQL_ATTR_TRACEFILE is not supported by this function. */
hr = GetDateLogOdbcConnectAttr(hDateLog, DATE_LOG_ODBC_1, SQL_ATTR_TRACEFILE,
traceFile, (SQLINTEGER)sizeof(traceFile), &length);
if (hr == HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED)) {
printf("SQL_ATTR_TRACEFILE is not supported.\n");
}
exitCode = 0;
cleanup:
if (pParams != NULL) {
FreeOdbcConnectParams(pParams);
}
/* Closing the date log also releases the ODBC connections it owns. */
if (hDateLog != NULL) {
CloseDateLogHandle(hDateLog);
}
if (hHolidays != NULL) {
CloseDateLogHandle(hHolidays);
}
return exitCode;
}