Establish a new ODBC connection for a DATE_LOG_HANDLE at a given level
ConnectDateLogHandleToOdbcDatabase establishes an ODBC connection, via
ConnectOdbcDatabase(), for the connection slot previously reserved by
InitializeDateLogHandleOdbc at the specified OdbcLevel, on the given DATE_LOG_HANDLE.
The connection-string parameters are taken from the supplied ODBC_CONNECT_PARAMS instance.
DATE_LOG_MAX_ODBC_CONNECTIONS = 4)SQL_ATTR_CONNECTION_DEAD) before reconnecting
HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) ConnectDateLogHandleToOdbcDatabase(
_In_ DATE_LOG_HANDLE hDateLogHandle,
_In_ PODBC_CONNECT_PARAMS pParams,
_In_ DATE_LOG_ODBC_LEVEL OdbcLevel
);
[In] DATE_LOG_HANDLE
A valid DATE_LOG_HANDLE, DATE_RANGE_HANDLE, or HOLIDAYS_HANDLE for which the connection slot at OdbcLevel has already been reserved.
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))[In] PODBC_CONNECT_PARAMS
Connection parameters obtained via InitializeOdbcConnectParams and populated through the structure’s AddParam member and tri-state fields (see ODBC_CONNECT_PARAMS).
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))[In] DATE_LOG_ODBC_LEVEL
Which of the (up to four) connection slots to connect. Valid values are DATE_LOG_ODBC_1 through DATE_LOG_ODBC_4.
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)Connection established successfully.
pParams/hDateLogHandle NULL, OdbcLevel out of range, or no connection internals/connection reserved yet.
Maximum ODBC connections (4) already reached for this handle.
Connection context could not be resolved for OdbcLevel.
Failure disconnecting/freeing a stale dead connection prior to reconnect.
Propagated from ConnectOdbcDatabase().
Always test the result with FAILED()/SUCCEEDED(); the function is marked _Must_inspect_result_.
The handle is validated and locked for the duration of the call. If a connection already exists at OdbcLevel and is reported dead (SQL_ATTR_CONNECTION_DEAD), it is disconnected and freed before the new connection is made; a failure at that step is reported as HRESULT_FROM_WIN32(ERROR_DATABASE_FAILURE).
The handle is validated and locked for the duration of the call, so concurrent calls on the same handle are serialized. Duplicate handles (see DuplicateDateLogHandle) share the same connections.
CloseDateLogHandle().Reserve slots with InitializeDateLogHandleOdbc in strictly increasing order (1, 2, 3, 4) before connecting a level. Connect before calling SetDateLogOdbcConnectAttr, GetDateLogOdbcConnectAttr, FetchDateLogHandleToOdbcDatabase, or EndDateLogOdbcTransaction, which all require an established connection at the level.
The parameters are consumed during the call but pParams is not retained. Free it with FreeOdbcConnectParams exactly once after you are finished; never use free(), and never allocate the structure on the stack or with malloc().
The ODBC_CONNECT_PARAMS page documents AddParam as HRESULT (*)(pParams, LPCSTR pszKey, LPCSTR pszValue), whereas AddOdbcParamter is documented with a handle-based eight-argument signature. The sample uses the structure’s AddParam member as documented on the structure page.
The example creates a date log, reserves ODBC slot 1, builds the connection parameters, connects, and then frees the parameters and closes every handle. Replace the driver, server, and database values with your own. Holiday data must be loaded into the holidays handle by your application as noted in the code.
#include <stdio.h>
#include "datelog.h"
static HRESULT BuildSampleDateLog(HOLIDAYS_HANDLE hHolidays, DATE_LOG_HANDLE *phDateLog)
{
DATE_LOG_HANDLE hDateLog = NULL;
DATE_ITEM_HANDLE hStart = NULL;
DATE_ITEM_HANDLE hEnd = NULL;
SYSTEMTIME stStart = { 0 };
SYSTEMTIME stEnd = { 0 };
FILETIME ftStart = { 0 };
FILETIME ftEnd = { 0 };
HRESULT hr = E_FAIL;
*phDateLog = NULL;
/* Tuesday 2 January 2024 through Wednesday 31 January 2024 (both market days). */
stStart.wYear = 2024; stStart.wMonth = 1; stStart.wDay = 2;
stEnd.wYear = 2024; stEnd.wMonth = 1; stEnd.wDay = 31;
if (!SystemTimeToFileTime(&stStart, &ftStart) || !SystemTimeToFileTime(&stEnd, &ftEnd)) {
return HRESULT_FROM_WIN32(GetLastError());
}
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
if (FAILED(hr)) {
return hr;
}
hr = InitializeDateItem(hDateLog, &ftStart, NULL, &hStart);
if (SUCCEEDED(hr)) {
hr = InitializeDateItem(hDateLog, &ftEnd, NULL, &hEnd);
}
if (SUCCEEDED(hr)) {
/* No file context: generate the contiguous range between hStart and hEnd. */
hr = LoadDateLogHandle(NULL, hStart, hEnd, hDateLog, NULL, 0);
}
FreeDateItem(hEnd);
FreeDateItem(hStart);
if (FAILED(hr)) {
CloseDateLogHandle(hDateLog);
return hr;
}
*phDateLog = hDateLog;
return S_OK;
}
int main(void)
{
HOLIDAYS_HANDLE hHolidays = NULL;
DATE_LOG_HANDLE hDateLog = NULL;
PODBC_CONNECT_PARAMS pParams = NULL;
HRESULT hr = E_FAIL;
int rc = 1;
/* Holidays handle. Populate it with your market holiday data (see
LoadDateLogHandle) before building date logs; that step is application specific. */
hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
if (FAILED(hr)) {
printf("InitializeDateLogHandle failed for holidays: 0x%08lX\n", (unsigned long)hr);
return 1;
}
hr = BuildSampleDateLog(hHolidays, &hDateLog);
if (FAILED(hr)) {
printf("BuildSampleDateLog failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Step 1: reserve connection slot 1 (levels must be reserved in order: 1, 2, 3, 4). */
hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("InitializeDateLogHandleOdbc failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
/* Step 2: build the connection parameters. */
hr = InitializeOdbcConnectParams(&pParams);
if (FAILED(hr)) {
printf("InitializeOdbcConnectParams 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", "MyDatabase");
}
if (FAILED(hr)) {
printf("AddParam failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
pParams->Trusted_Connection = ODBC_TRUE;
/* Step 3: connect slot 1. The connection is owned by hDateLog. */
hr = ConnectDateLogHandleToOdbcDatabase(hDateLog, pParams, DATE_LOG_ODBC_1);
if (FAILED(hr)) {
printf("ConnectDateLogHandleToOdbcDatabase failed: 0x%08lX\n", (unsigned long)hr);
goto cleanup;
}
printf("hDateLog is connected to the ODBC data source at level 1.\n");
/* ... use the connection, for example with FetchDateLogHandleToOdbcDatabase ... */
rc = 0;
cleanup:
/* pParams is not retained by the library; free it regardless of the outcome. */
if (pParams != NULL && FAILED(FreeOdbcConnectParams(pParams))) {
rc = 1;
}
/* Closing the handle also closes its ODBC connection(s). */
if (hDateLog != NULL && FAILED(CloseDateLogHandle(hDateLog))) {
rc = 1;
}
if (FAILED(CloseDateLogHandle(hHolidays))) {
rc = 1;
}
return rc;
}