ODBC ドライバー API サポート

Snowflake ODBC ドライバーは、 ODBC API のバージョン3.52をサポートしています。このトピックでは、Snowflakeに関連する ODBC ルーチンをリストし、それらがサポートされているかどうかを示します。ルーチンは、実行する機能に基づいてカテゴリに分類されます。

完全な API リファレンスについては、 Microsoft ODBC プログラマーズリファレンス をご参照ください。

データソースへの接続

関数名

サポート対象

メモ

SQLAllocHandle

✔

SQLConnect

✔

SQLDriverConnect

✔

SQLAllocEnv

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

SQLAllocConnect

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

SQLBrowseConnect

✔

ドライバーおよびデータソースに関する情報の取得

関数名

サポート対象

メモ

SQLDataSources

✔

SQLDrivers

✔

SQLGetInfo

✔

SQLGetFunctions

✔

SQLGetTypeInfo

✔

ドライバー属性の設定および取得

関数名

サポート対象

メモ

SQLSetConnectAttr

✔

SQL_ATTR_METADATA_ID の設定は、 SQLTables 関数と SQLColumns 関数のみに影響します(他の サポートされているカタログ関数 には影響なし)。

SQLGetConnectAttr

✔

読み取り専用モードはサポートされていません。SQL_MODE_READ_ONLY はドライバーに渡されますが、Snowflakeは引き続きデータベースに書き込みます。. . また、 API バージョン3.52以降でいくつかの属性が導入されました。SQL_ATTR_ASYNC_DBC_EVENT、 SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE、 SQL_ATTR_ASYNC_DBC_PCALLBACK、 SQL_ATTR_ASYNC_DBC_PCONTEXT、 SQL_ATTR_DBC_INFO_TOKEN。

SQLSetConnectOption

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

SQLGetConnectOption

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

SQLSetEnvAttr

✔

SQLGetEnvAttr

✔

SQL_ATTR_CONNECTION_POOLING 属性は、 ODBCAPI バージョン3.52の後に導入されており、サポートされていません。

SQLSetStmtAttr

✔

SQL_ATTR_CURSOR_SCROLLABLE は、SQL_NONSCROLLABLE 値のみをサポートします。. SQL_ATTR_USE_BOOKMARKS は、SQL_UB_OFF 値のみをサポートします。. . サードパーティツールとの互換性のために、ODBC 標準ではデフォルトはfalseであると規定されていますが、SQL_ATTR_ENABLE_AUTO_IPD はデフォルトでtrueに設定されています。デフォルト値をfalseに変更するには、 EnableAutoIpdByDefault パラメーターを false に設定します。. . SQL_ATTR_METADATA_ID の設定は、SQLTables および SQLColumns 関数にのみ影響します(他の サポートされているカタログ関数 には影響しません)。. . サポートされていない属性: SQL_ATTR_SIMULATE_CURSOR、SQL_ATTR_FETCH_BOOKMARK_PTR、SQL_ATTR_KEYSET_SIZE。

SQLGetStmtAttr

✔

標準属性に加えて、Snowflake実装は属性 SQL_SF_STMT_ATTR_LAST_QUERY_ID をサポートします。これにより、ユーザーは指定されたステートメントハンドルに関連付けられた最新のクエリ ID を取得できます。部分的な例は、以下の 例 セクションに記載されています。

SQLSetStmtOption

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。SQLSetStmtAttr に置き換えられました。

SQLGetStmtOption

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。SQLGetStmtAttr に置き換えられました。

SQLParamOptions

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。SQLSetStmtAttr に置き換えられました。

上記の各関数には、ワイド文字(Unicode)を受け入れる対応する関数があります。そのような各Unicode関数には、上記の名前の後に「W」が付いています。例えば、3番目のパラメーターとしてchar配列を受け入れる関数 SQLGetStmtAttr には、3番目のパラメーターとしてwchar配列を受け入れる SQLGetStmtAttrW という名前の対応する関数があります。

Snowflake固有の動作

  • SQLSetConnectAttr

    このメソッドは、次の2つのSnowflake固有の属性をサポートしています。

    属性名

    説明

    SQL_SF_CONN_ATTR_APPLICATION

    これにより、レジストリまたは.iniファイルの APPLICATION 設定で指定された値が上書きされます。

    SQL_SF_CONN_ATTR_PRIV_KEY

    これは、プライベートキーのメモリ内コピーを指す EVP_PKEY*ポインターです。これにより、レジストリまたは.iniファイルの PRIV_KEY_FILE および PRIV_KEY_PWD 設定が上書きされます。Snowflakeは、この属性を使用して秘密キーを設定することをお勧めします。

    Snowflake内 ODBC ドライバーバージョン3.4.0以降では、SQLSetConnectAttr で次の2つの追加属性を使用できます。

    属性名

    説明

    :codenowrap:SQL_SF_CONN_ATTR_PRIV_KEY_CONTENT

    プライベートキーのコンテンツを接続に直接渡すことができます。ヘッダーとフッターを含む完全なキーコンテンツを渡してください。

    :codenowrap:SQL_SF_CONN_ATTR_PRIV_KEY_PASSWORD

    SQL_SF_CONN_ATTR_PRIV_KEY_CONTENT で暗号化されたプライベートキーを渡す場合、この属性を使用するとパスワードを指定できます。

    アプリケーションと ODBC ドライバーが互換性のない OpenSSL のバージョンにリンクされており、キーペア認証の使用時に ODBC ドライバーによるクラッシュが発生する場合は、SQL_SF_CONN_ATTR_PRIV_KEY_CONTENT の使用が必要になることがあります。

    次のC++コードは、以下の実装を示しています。

    std::string fileContent = loadKeyFileContent(keyFilePath);
    SQLSetConnectAttr(dbc, SQL_SF_CONN_ATTR_PRIV_KEY_CONTENT, (SQLPOINTER)fileContent.c_str(), SQL_NTS);
    

記述子フィールドの設定および取得

関数名

サポート対象

メモ

SQLGetDescField

✔

SQLGetDescRec

✔

SQLSetDescField

✔

SQLSetDescRec

✔

SQL リクエストの準備

関数名

サポート対象

メモ

SQLAllocStmt

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

SQLBindParameter

✔

SQLPrepare

✔

SQLGetCursorName

✔

SQLSetCursorName

✔

SQLSetScrollOptions

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API では非推奨です。

SQLSetParam

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン2.xでは非推奨です。SQLBindParameter に置き換えられました。

注釈

リクエストの送信

関数名

サポート対象

メモ

SQLExecute

✔

SQLExecDirect

✔

SQLNativeSql

✔

SQLDescribeParam

✔

パラメーターにバインドされているデータ型に関係なく、Snowflakeはサーバー側の変換を実行し、最大長が134217728の VARCHAR を返します。

SQLNumParams

✔

SQLParamData

✔

この機能のサポートは、 ODBC ドライバーのバージョン2.23.3で追加されました。

SQLPutData

✔

この機能のサポートは、 ODBC ドライバーのバージョン2.23.3で追加されました。

結果および結果に関する情報の取得

関数名

サポート対象

メモ

SQLBindCol

✔

ODBC ドライバーは現在、 VARIANT、 OBJECT、 ARRAY データ型などの半構造化データをサポートしていません。

SQLError

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。SQLGetDiagRec に置き換えられました。

SQLGetData

✔

SQLGetDiagField

✔

SQLGetDiagRec

✔

SQLRowCount

✔

SQLNumResultCols

✔

SQLDescribeCol

✔

SQLColAttribute

✔

GEOGRAPHY 列に対して、 SQL_DESC_TYPE_NAME は GEOGRAPHY を返します。他の記述子(例: SQL_DESC_CONCISE_TYPE)は、列タイプが GEOGRAPHY であることを示してはいません。

SQLColAttributes

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン2.xでは非推奨です。SQLColAttribute に置き換えられました。

SQLFetch

✔

SQLFetchScroll

✔

FetchOrientation 引数は SQL_FETCH_NEXT 値のみをサポートします。他のすべてのタイプのフェッチは失敗します。

SQLExtendedFetch

API バージョン3.xドライバーで、 SQLFetchScroll に置き換えられました。

SQLSetPos

Snowflakeはこの機能をサポートしていません。

SQLBulkOperations

Snowflakeはこの機能をサポートしていません。

データソースのシステムテーブルに関する情報の取得(カタログ関数)

関数名

サポート対象

メモ

SQLColumnPrivileges

空の結果セットを返します。

SQLColumns

✔

SQLForeignKeys

✔

SQLPrimaryKeys

✔

SQLProcedureColumns

✔

SQLProcedures

✔

結果セットの NUM_INPUT_PARAMS 列には、プロシージャの引数の数( SHOW PROCEDURES コマンドの出力max_num_argumentsの列の値)が含まれています。. . Snowflakeのストアドプロシージャは出力パラメータをサポートしていないため、 NUM_OUTPUT_PARAMS 列には NULL 値が含まれています。. . Snowflakeのストアドプロシージャは結果セットを返さないため、 NUM_RESULT_SETS 列には NULL 値も含まれます。. . Snowflakeのストアドプロシージャは常に値を返すため、 PROCEDURE_TYPE 列には常に SQL_PT_FUNCTION が含まれます。

SQLSpecialColumns

空の結果セットを返します。

SQLStatistics

空の結果セットを返します。

SQLTablePrivileges

空の結果セットを返します。

SQLTables

✔

関数に渡されるパラメーターが「TABLE」の場合、関数は一時テーブルや仮テーブルを含むすべてのタイプのテーブルを返します。. . 関数に渡されるパラメーターが「VIEW」の場合、関数はマテリアライズドビューを含むすべてのタイプのビューを返します。. . 関数に渡されるパラメーターが「TABLE、VIEW」または「%」の場合、関数はすべてのタイプのテーブルとすべてのタイプのビューに関する情報を返します。

カタログ関数に渡された名前に無効な文字がある場合、または名前がどのデータベースオブジェクトとも一致しない場合、関数は空の結果セットを返します。

SQL_ATTR_METADATA_ID の設定は、 SQLTables 関数、 SQLColumns 関数、および SQLProcedures 関数のみに影響します。

ステートメントの終了

関数名

サポート対象

メモ

SQLFreeStmt

✔

SQLCloseCursor

✔

SQLCancel

✔

SQLEndTran

✔

SQLTransact

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。SQLEndTran に置き換えられました。

接続の終了

関数名

サポート対象

メモ

SQLCancelHandle

バージョン3.52以後の API に導入されました。

SQLDisconnect

✔

SQLFreeHandle

✔

SQLFreeConnect

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

SQLFreeEnv

✔

Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。

カスタム SQL データ型

Snowflakeでサポートされている一部の SQL データ型には、 ODBC に直接マッピングがありません(例:TIMESTAMP_*tz、 VARIANT)。サポートされていないデータ型で ODBC ドライバーを使用できるようにするために、ドライバーに付属のヘッダーファイルには、次のカスタムデータ型の定義が含まれています。

////////////////////////////////////////////////////////////////////////////////////////////////////
/// Custom SQL Data Type Definition
///
///
////////////////////////////////////////////////////////////////////////////////////////////////////

#define SQL_SF_TIMESTAMP_LTZ 2000
#define SQL_SF_TIMESTAMP_TZ  2001
#define SQL_SF_TIMESTAMP_NTZ 2002
#define SQL_SF_ARRAY         2003
#define SQL_SF_OBJECT        2004
#define SQL_SF_VARIANT       2005

次のコードは、カスタムデータ型の使用例を示しています。

// bind insert as timestamp_ntz
SQLRETURN rc;
rc = SQLPrepare(odbc.StmtHandle,
               (SQLCHAR *) "insert into testtimestampntz values (?)",
               SQL_NTS);

 SQL_TIMESTAMP_STRUCT bindData;
 SQLLEN datalen = sizeof(SQL_TIMESTAMP_STRUCT);
 bindData.year = 2017;
 bindData.month = 11;
 bindData.day = 30;
 bindData.hour = 18;
 bindData.minute = 17;
 bindData.second = 5;
 bindData.fraction = 123456789;

 rc = SQLBindParameter(
   odbc.StmtHandle, 1, SQL_PARAM_INPUT,
   SQL_C_TIMESTAMP, SQL_SF_TIMESTAMP_NTZ,
   100, 0, &bindData, sizeof(bindData), &datalen);

 rc = SQLExecute(odbc.StmtHandle);

 // query table
 rc = SQLExecDirect(odbc.StmtHandle, (SQLCHAR *)"select * from testtimestampntz", SQL_NTS);

 rc = SQLFetch(odbc.StmtHandle);

 // fetch data as timestamp
 SQL_TIMESTAMP_STRUCT ret;
 SQLLEN retLen = (SQLLEN) 0;
 rc = SQLGetData(odbc.StmtHandle, 1, SQL_C_TIMESTAMP, &ret, (SQLLEN)sizeof(ret), &retLen);

例

このセクションでは、APIの使用例を示します。

最後のクエリ IDの取得

最後のクエリ ID の取得は、 ODBC 標準のSnowflake拡張機能です。

最後のクエリ ID を取得するには、関数 SQLGetStmtAttr (または SQLGetStmtAttrW)を呼び出し、属性 SQL_SF_STMT_ATTR_LAST_QUERY_ID とクエリ ID を保持するのに十分な大きさの文字配列を渡します。

以下の例は、クエリのクエリ ID を取得する方法を示しています。

// Space to store the query ID.
// The SQLGetStmtAttr() function fills this in with the actual ID.
char queryId[37];   // Maximum 36 chars plus string terminator.

// The length (in characters) of the query ID. The SQLGetStmtAttr() function fills this in
// with the actual length of the query ID (usually 36).
SQLINTEGER idLen;

// Execute a query.
rc = SQLExecDirect(odbc.StmtHandle, (SQLCHAR *) "select 1", SQL_NTS);

// Retrieve the query ID (queryId) and the length of that query ID (idLen).
SQLGetStmtAttr(odbc.StmtHandle, SQL_SF_STMT_ATTR_LAST_QUERY_ID, queryId, sizeof(queryId), &idLen);

Linuxまたは macOSで実行している場合は、 SQLGetStmtAttrW を呼び出して、適切なデータ型のパラメーター(たとえば、「char」ではなく「wchar」)を渡します。

データを取得する際のパフォーマンスを向上させるためのベストプラクティス

SQLFetch でデータを取得する場合は、 SQLGetData または SQLBindCol 関数を使用してセルの内容にアクセスできます。ほとんどの場合、 SQLBindCol を使用すると、データを取得するために必要な ODBC 呼び出しの数が減り、メモリ内のデータのコピーを利用できるため、パフォーマンスが向上します。

SQLGetData を使用したセルデータの取得

次の例では、 SQLGetData 関数を使用して、 SQLFetch によって返されたデータバッファーからセル値を取得します。行のセルごとに SQLGetData を1回呼び出す必要があることに注意してください。

SQLRETURN rc;
SQLSMALLINT numCols;
const size_t s_MaxDataLen = 300;

// fetch with SQLGetData()
// query table
rc = SQLExecDirect(stmt, (SQLCHAR *)"select * from table", SQL_NTS);

// Find out the number of result set columns.
rc = SQLNumResultCols(stmt, &numCols);

// buffer for one cell
vector<char> dataBuffer(s_MaxDataLen);
SQLLEN dataLen = (SQLLEN)0;

// call SQLFetch() per row and SQLGetData() per column per row
while (true)
{
    rc = SQLFetch(stmt);
    if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
    {
        break;
    }
    for (SQLUSMALLINT i = 0; i < numCols; i++)
    {
        rc = SQLGetData(stmt, i + 1, SQL_C_CHAR, dataBuffer.data(), (SQLLEN)s_MaxDataLen, &dataLen);
        std::string data;
        if (SQL_NULL_DATA == dataLen)
            continue;
        if (SQL_NO_TOTAL == dataLen)
            dataLen = s_MaxDataLen;
        data = std::string(dataBuffer.data(), dataLen);
    }
}
rc = SQLCloseCursor(stmt);

SQLBindCol を使用した1行のデータ列のバインド

次の例では、 SQLBindCol 関数を使用して、 SQLFetch によって返されたデータバッファーからセル値を取得します。行にある列数のメモリ内バッファーを作成して、 SQLBindCol を1回呼び出し、アプリケーションバッファーを結果セットにバインドします。最後に、行ごとに SQLFetch を1回呼び出し、セルの値をバッファーにロードします。このアプローチにより、データの取得速度と効率を大幅に向上させることができます。

SQLRETURN rc;
SQLSMALLINT numCols;
const size_t s_MaxDataLen = 300;

// fetch with SQLBindCol()
// query table
rc = SQLExecDirect(stmt, (SQLCHAR *)"select * from table", SQL_NTS);

// Find out the number of result set columns.
rc = SQLNumResultCols(stmt, &numCols);

// buffer for one row
vector<char> rowBuffer(s_MaxDataLen * numCols);
vector<SQLLEN> columnLenBuffer(numCols);

// call SQLBindCol() per column
for (SQLSMALLINT i = 0; i < numCols; ++i)
{
    SQLBindCol(stmt, i + 1, SQL_C_CHAR, &rowBuffer[s_MaxDataLen * i],
               s_MaxDataLen, &columnLenBuffer[i]);
}

// call SQLFetch() per row
while (true)
{
    rc = SQLFetch(stmt);
    if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
    {
         break;
    }
    // go through data for each cell in buffer without ODBC calls
    for (SQLUSMALLINT i = 0; i < numCols; i++)
    {
        std::string data;
        SQLLEN len = columnLenBuffer[i];
        if (SQL_NULL_DATA == len)
            continue;
        if (SQL_NO_TOTAL == len)
            len = s_MaxDataLen;
        data = std::string(&rowBuffer[s_MaxDataLen * i], len);
    }
}
rc = SQLCloseCursor(stmt);

SQLBindCol を使用した複数行のデータ列のバインド

SQLFetch を1回呼び出して複数の行をフェッチすると、パフォーマンスをさらに向上させることができます。これにより、クエリテーブルのすべての行を処理するために必要な ODBC SQLFetch 呼び出しの数が減ります。

次の例では、

  • 結果セットの列数を決定します。

  • 複数列からのデータを保存するためのメモリ内配列を作成します。

  • 各列に対して SQLBindCol を呼び出し、アプリケーションバッファーを結果セットにバインドします。

  • SQLFetch を呼び出して、指定された行数(100)を取得し、クエリテーブルの最後に到達するまで ODBC を呼び出さずに、メモリ内バッファーにあるデータを処理します。

このアプローチにより、データの取得速度と効率を大幅に向上させることができます。20列と1000行のクエリテーブルの場合、この例では、すべてのテーブルデータを読み込むために SQLGetData を20000回呼び出すのではなく、 SQLBindCol を20回、 SQLFetch を10回のみ呼び出します。

SQLRETURN rc;
SQLSMALLINT numCols;
const size_t s_MaxDataLen = 300;

// fetch with SQLBindCol() and SQL_ATTR_ROW_ARRAY_SIZE > 1
const size_t s_numRowsPerSQLFetch = 100;
SQLULEN numRowsFetched = 0;
rc = SQLSetStmtAttr(stmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)s_numRowsPerSQLFetch, 0);
rc = SQLSetStmtAttr(stmt, SQL_ATTR_ROWS_FETCHED_PTR, (SQLPOINTER)&numRowsFetched, sizeof(SQLULEN));

// query table
rc = SQLExecDirect(stmt, (SQLCHAR *)"select * from table", SQL_NTS);

// Find out the number of result set columns.
rc = SQLNumResultCols(stmt, &numCols);

// buffer for all columns; each column has buffer size of s_numRowsPerSQLFetch
// To retrieve multiple rows per SQLFetch() call, use the default behavior of SQL_BIND_BY_COLUMN
vector<vector<char> > colArray(numCols);
vector<vector<SQLLEN> > colLenArray(numCols);

// call SQLBindCol() per column
for (SQLSMALLINT i = 0; i < numCols; ++i)
{
    // initialize buffer for each column
    colArray[i].resize(s_MaxDataLen * s_numRowsPerSQLFetch);
    colLenArray[i].resize(s_numRowsPerSQLFetch);

    SQLBindCol(stmt, i + 1, SQL_C_CHAR, colArray[i].data(),
                s_MaxDataLen, colLenArray[i].data());
}

// call SQLFetch() per s_numRowsPerSQLFetch rows
while (true)
{
    rc = SQLFetch(stmt);
    if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
    {
        break;
    }
    // go through data for each cell in buffer without ODBC calls
    for (SQLULEN rowIndex = 0; rowIndex < numRowsFetched; rowIndex++)
    {
        for (SQLUSMALLINT colIndex = 0; colIndex < colIndex; colIndex++)
        {
            std::string data;
            SQLLEN len = colLenArray[colIndex][rowIndex];
            if (SQL_NULL_DATA == len)
                continue;
            if (SQL_NO_TOTAL == len)
                len = s_MaxDataLen;
            data = std::string(&(colArray[colIndex][s_MaxDataLen * rowIndex]), len);
        }
    }
}
rc = SQLCloseCursor(stmt);