ODBC ドライバー API サポート¶
Snowflake ODBC ドライバーは、 ODBC API のバージョン3.52をサポートしています。このトピックでは、Snowflakeに関連する ODBC ルーチンをリストし、それらがサポートされているかどうかを示します。ルーチンは、実行する機能に基づいてカテゴリに分類されます。
完全な API リファレンスについては、 Microsoft ODBC プログラマーズリファレンス をご参照ください。
このトピックの内容:
データソースへの接続¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
ドライバーおよびデータソースに関する情報の取得¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
ドライバー属性の設定および取得¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
SQL_ATTR_METADATA_ID の設定は、 SQLTables 関数と SQLColumns 関数のみに影響します(他の サポートされているカタログ関数 には影響なし)。 |
|
✔ |
読み取り専用モードはサポートされていません。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。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
|
|
✔ |
SQL_ATTR_CONNECTION_POOLING 属性は、 ODBCAPI バージョン3.52の後に導入されており、サポートされていません。 |
|
✔ |
SQL_ATTR_CURSOR_SCROLLABLE は、SQL_NONSCROLLABLE 値のみをサポートします。 . SQL_ATTR_USE_BOOKMARKS は、SQL_UB_OFF 値のみをサポートします。 . . サードパーティツールとの互換性のために、ODBC 標準ではデフォルトはfalseであると規定されていますが、SQL_ATTR_ENABLE_AUTO_IPD はデフォルトでtrueに設定されています。デフォルト値をfalseに変更するには、 EnableAutoIpdByDefault パラメーターを |
|
✔ |
標準属性に加えて、Snowflake実装は属性 SQL_SF_STMT_ATTR_LAST_QUERY_ID をサポートします。これにより、ユーザーは指定されたステートメントハンドルに関連付けられた最新のクエリ ID を取得できます。部分的な例は、以下の 例 セクションに記載されています。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
上記の各関数には、ワイド文字(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は、この属性を使用して秘密キーを設定することをお勧めします。
記述子フィールドの設定および取得¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
SQL リクエストの準備¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API では非推奨です。 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン2.xでは非推奨です。 |
注釈
バインドできるデータのサイズには上限があります。詳細については、 クエリテキストサイズの制限 をご参照ください。
準備のためにサポートされている SQL ステートメント は、準備のためにサポートされている SQL ステートメントの型をリストします。
リクエストの送信¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
パラメーターにバインドされているデータ型に関係なく、Snowflakeはサーバー側の変換を実行し、最大長が16777216の VARCHAR を返します。 |
|
✔ |
|
|
✔ |
この機能のサポートは、 ODBC ドライバーのバージョン2.23.3で追加されました。 |
|
✔ |
この機能のサポートは、 ODBC ドライバーのバージョン2.23.3で追加されました。 |
結果および結果に関する情報の取得¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
ODBC ドライバーは現在、 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
GEOGRAPHY 列に対して、 |
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン2.xでは非推奨です。 |
|
✔ |
|
|
✔ |
|
|
API バージョン3.xドライバーで、 |
|
|
Snowflakeはこの機能をサポートしていません。 |
|
|
Snowflakeはこの機能をサポートしていません。 |
データソースのシステムテーブルに関する情報の取得(カタログ関数)¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
空の結果セットを返します。 |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
結果セットの |
|
空の結果セットを返します。 |
|
|
空の結果セットを返します。 |
|
|
空の結果セットを返します。 |
|
|
✔ |
関数に渡されるパラメーターが「TABLE」の場合、関数は一時テーブルや仮テーブルを含むすべてのタイプのテーブルを返します。 . . 関数に渡されるパラメーターが「VIEW」の場合、関数はマテリアライズドビューを含むすべてのタイプのビューを返します。 . . 関数に渡されるパラメーターが「TABLE、VIEW」または「%」の場合、関数はすべてのタイプのテーブルとすべてのタイプのビューに関する情報を返します。 |
カタログ関数に渡された名前に無効な文字がある場合、または名前がどのデータベースオブジェクトとも一致しない場合、関数は空の結果セットを返します。
SQL_ATTR_METADATA_ID
の設定は、 SQLTables
関数、 SQLColumns
関数、および SQLProcedures
関数のみに影響します。
ステートメントの終了¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
接続の終了¶
関数名 |
サポート対象 |
メモ |
---|---|---|
|
バージョン3.52以後の API に導入されました。 |
|
|
✔ |
|
|
✔ |
|
|
✔ |
Snowflakeドライバーによりサポートされていますが、 ODBC API バージョン3.xでは非推奨です。 |
|
✔ |
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);