InitializeDateLogHandleOdbc

Initialize the ODBC connection internals / reserve a connection slot for a DATE_LOG_HANDLE

Overview

InitializeDateLogHandleOdbc lazily allocates the handle's ODBC connection internals (on the first call, OdbcLevel must be DATE_LOG_ODBC_1), then allocates a new connection node wrapping a freshly initialized connection context for the requested OdbcLevel and pushes it onto the handle's internal connection list. No database connection is opened yet.

Purpose

Reserves one of up to four ODBC connection slots on a date log handle. It must be called once per OdbcLevel, in strictly increasing order (1, then 2, then 3, then 4), before ConnectDateLogHandleToOdbcDatabase can target that level. The slot can then be configured with AddOdbcParamter and SetDateLogOdbcConnectAttr.

Key Features

Function Signature


HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) InitializeDateLogHandleOdbc(
    _In_ DATE_LOG_HANDLE     hDateLogHandle,
    _In_ DATE_LOG_ODBC_LEVEL OdbcLevel
);

Parameters

hDateLogHandle

[In] DATE_LOG_HANDLE

Must be a DATE_LOG_HANDLE (dwMagic == __DATE_LOG_MAGIC__); other handle types are rejected. Create it with InitializeDateLogHandle using HandleIsForDatelog.

Must not be NULL. The handle is not closed by this function; the new connection slot is owned by the handle's shared context.

OdbcLevel

[In] DATE_LOG_ODBC_LEVEL

Must equal the current connection count + 1, i.e. sequential starting at DATE_LOG_ODBC_1. Valid values are DATE_LOG_ODBC_1 through DATE_LOG_ODBC_4 (the per-handle limit is 4 connections).

Return Values

ValueMeaning
S_OKThe connection slot was reserved and initialized successfully.
ERR_BAD_HANDLE_TYPEhDateLogHandle is not a DATE_LOG_MAGIC handle.
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)OdbcLevel is out of range or is not the next sequential slot.
HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY)Allocation of the node or connection context failed.

Notes

On any failure, any partially allocated context/node is freed before returning; the connection count is not incremented.

Remarks

Thread Safety

Slot reservation changes the shared context of the handle. Complete all InitializeDateLogHandleOdbc calls before other threads begin using the ODBC connections of the same context (including through handles created with DuplicateDateLogHandle).

Handle Lifetime and Ownership

ODBC connections belong to the shared context, not to an individual handle. They are released, together with their statements, when the last handle referencing the context is closed with CloseDateLogHandle. There is no separate function to release a reserved slot.

Ordering

InitializeDateLogHandle
→
InitializeDateLogHandleOdbc(level 1..n)
→
ConnectDateLogHandleToOdbcDatabase
→
CloseDateLogHandle

Calling a later level before the earlier ones, or the same level twice, fails with ERROR_INVALID_PARAMETER.

Other ODBC pages state that DATE_RANGE_HANDLE and HOLIDAYS_HANDLE are also accepted by their functions, while this function accepts only DATE_LOG_HANDLE; follow the type rule of each function. The SQL_DATE_BULK sample uses the name DATE_LOG_ODBC_LEVEL_READ_ONLY, which is not among the levels listed on the ODBC pages (DATE_LOG_ODBC_1..DATE_LOG_ODBC_4).

See Also

Sample Code


#include <stdio.h>
#include <Windows.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;

    /* 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 connection slots strictly in order: 1, then 2. */
    hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_1);
    if (FAILED(hr)) {
        printf("Reserving ODBC level 1 failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_2);
    if (FAILED(hr)) {
        printf("Reserving ODBC level 2 failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* Reserving level 2 again is not the next sequential slot and must fail. */
    hr = InitializeDateLogHandleOdbc(hDateLog, DATE_LOG_ODBC_2);
    if (FAILED(hr)) {
        printf("Second reservation of level 2 rejected: 0x%08lX\n", (unsigned long)hr);
    }

    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;

    /* Connect the first slot; level 2 stays reserved but unconnected. */
    hr = ConnectDateLogHandleToOdbcDatabase(hDateLog, pParams, DATE_LOG_ODBC_1);
    if (FAILED(hr)) {
        printf("Connecting level 1 failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }
    printf("ODBC level 1 connected.\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;
}