テクニカル ノート 42: ODBC ドライバの開発に関する推奨事項
更新 : 2007 年 11 月
メモ : |
---|
次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。 |
このテクニカル ノートは、ODBC (Open Database Connectivity) ドライバを作成する場合のガイドラインです。MFC (Microsoft Foundation Class) データベース クラスを使用した ODBC 機能に対する条件や前提、および要求される構文の詳細について説明します。また、CRecordset の 3 つのオープン モード (forwardOnly、snapshot、dynaset) に必要なドライバの機能についても説明します。
ODBC カーソル ライブラリ
多くの場合、MFC データベース クラスでは、レベル 1 の ODBC ドライバよりも高度な機能が用意されています。ODBC カーソル ライブラリはデータベース クラスとドライバの間に位置するため、カーソル ライブラリの追加機能の多くはそのまま利用できます。
たとえば、1.0 ドライバの多くは後方スクロールをサポートしていません。しかし、カーソル ライブラリを使用すると、行の内容をドライバからキャッシュして、SQLExtendedFetch の FETCH_PREV の呼び出しに応じて表示できます。
他にも、カーソル ライブラリの機能を利用している重要な例として、位置を指定した更新機能があります。ほとんどの 1.0 ドライバは位置を指定した更新を行うことはできませんでしたが、カーソル ライブラリは、キャッシュされているデータ値またはタイムスタンプ値から、データ ソース内のターゲット行を特定する更新ステートメントを作成します。
クラス ライブラリは複数行セットを利用しません。したがって、いくつかの SQLSetPos ステートメントは、常に行セットの最初の行に適用されます。
CDatabase
CDatabase ごとに HDBC を 1 つずつ割り当てます。CDatabase の ExecuteSQL 関数が使用されると、一時的に HSTMT が割り当てられます。したがって、複数の CDatabase を使用する場合は、1 つの HENV に対して複数の HDBC が利用可能であることが必要です。
データベース クラスは、カーソル ライブラリを必要とします。これは、SQLSetConnections から SQL_ODBC_CURSORS や SQL_CUR_USE_ODBC が呼び出されるためです。
SQLDriverConnect の SQL_DRIVER_COMPLETE は、データ ソースと接続するために CDatabase::Open 関数で使われます。
ドライバは、SQLGetInfoSQL_ODBC_API_CONFORMANCE >= SQL_OAC_LEVEL1 および SQLGetInfoSQL_ODBC_SQL_CONFORMANCE >= SQL_OSC_MINIMUM をサポートする必要があります。
CDatabase およびそれに依存するレコードセットでトランザクションをサポートするには、SQLGetInfo の SQL_CURSOR_COMMIT_BEHAVIOR と SQL_CURSOR_ROLLBACK_BEHAVIOR に SQL_CR_PRESERVE が必要です。SQL_CR_PRESERVE がないと、トランザクションは無視されます。
SQLGetInfo の SQL_DATA_SOURCE_READ_ONLY がサポートされている必要もあります。この関数が "Y" を返す場合は、データ ソースに対する更新操作は行われません。
CDatabase を読み取り専用で開くと、データ ソースは SQLSetConnectOption の SQL_ACCESS_MODE と SQL_MODE_READ_ONLY によって読み取り専用に設定されます。
SQLGetInfo の SQL_IDENTIFIER_QUOTE_CHAR を呼び出すと、識別子を二重引用符で囲む必要があるかどうかを示す情報がドライバによって返されます。
デバッグ用に、SQLGetInfo の SQL_DBMS_VER および SQL_DBMS_NAME がドライバから取得されます。
CDatabase の HDBC に対して SQLSetStmtOption の SQL_QUERY_TIMEOUT および SQL_ASYNC_ENABLE を呼び出すことができます。
SQLError は、任意の引数またはすべての引数を NULL にして呼び出すことができます。
SQLAllocEnv、SQLAllocConnect、SQLDisconnect、および SQLFreeConnect は、当然サポートする必要があります。
ExecuteSQL
ExecuteSQL は、一時的な HSTMT の割り当てと解放を行うだけでなく、SQLExecDirect、SQLFetch、SQLNumResultCol、SQLMoreResults を呼び出します。SQLCancel は、HSTMT に対して呼び出されます。
GetDatabaseName
SQLGetInfo の SQL_DATABASE_NAME が呼び出されます。
BeginTrans、CommitTrans、Rollback
トランザクション要求が発生すると、SQLSetConnectOption の SQL_AUTOCOMMIT および SQLTransact の SQL_COMMIT、SQL_ROLLBACK、SQL_AUTOCOMMIT が呼び出されます。
CRecordsets
SQLAllocStmt、SQLPrepare、SQLExecute (Open と Requery 用)、SQLExecDirect (更新操作用)、および SQLFreeStmt がサポートされている必要があります。SQLNumResultCols と SQLDescribeCol は、さまざまな場合に結果セットに対して呼び出されます。
SQLSetParam は、パラメータデータと DATA_AT_EXEC 機能を結び付けるために使用されます。
SQLBindCol は、出力列のデータ格納位置を ODBC に登録するために使用します。
SQL_LONG_VARCHAR と SQL_LONG_VARBINARY のデータを取得するには、SQLGetData を 2 回呼び出します。最初の呼び出しでは、cbMaxValue に 0、pcbValue に有効な値を指定して SQLGetData を呼び出し、列の値を格納するために必要な領域の大きさを取得します。pcbValue に SQL_NO_TOTAL を設定すると、例外がスローされます。それ以外の場合は、HGLOBAL が割り当てられ、次の SQLGetData 呼び出しで列の値が返されます。
更新
排他ロックが要求された場合は、SQLGetInfo の SQL_LOCK_TYPES を問い合わせます。SQL_LCK_EXCLUSIVE がサポートされていない場合は、例外がスローされます。
CRecordset (snapshot または dynaset) を更新するときは、別の HSTMT が割り当てられます。複数の HSTMT をサポートしないドライバの場合は、カーソル ライブラリがその機能を実現します。このとき、2 番目の HSTMT への要求が処理される前に、最初の HSTMT への現在のクエリが完了してしまうことがあります。
SQLFreeStmt の SQL_CLOSE と SQL_RESET_PARAMS と SQLGetCursorName が更新操作の間に呼び出されます。
outputColumns の中に CLongBinarys がある場合は、ODBC の DATA_AT_EXEC 機能をサポートする必要があります。SQLExecDirect、SQLParamData、SQLPutData は SQL_NEED_DATA を返す必要があります。
SQLExecDirect によってレコードが 1 つだけ更新されたことを確認するために、実行後に SQLRowCount が呼び出されます。
前方向カーソル
Move 操作に必要なのは、SQLFetch のみです。forwardOnly カーソルは更新をサポートしません。
スナップショット カーソル
スナップショット機能を使用するには、SQLExtendedFetch がサポートされている必要があります。ドライバで SQLExtendedFetch がサポートされていない場合は、上に述べたように、ODBC カーソル ライブラリによって必要なサポートが提供されます。
SQLGetInfo の SQL_SCROLL_OPTIONS は SQL_SO_STATIC をサポートする必要があります。
ダイナセット カーソル
ダイナセットを開くために必要な最小限のサポートを次に示します。
SQLGetInfo の SQL_ODBC_VER は "01" より大きな値を返します。
SQLGetInfo の SQL_SCROLL_OPTIONS は SQL_SO_KEYSET_DRIVEN をサポートする必要があります。
SQLGetInfo の SQL_ROW_UPDATES は "Y" を返す必要があります。
SQLGetInfo の SQL_POSITIONED_UPDATES は SQL_PS_POSITIONED_DELETE と SQL_PS_POSITIONED_UPDATE をサポートする必要があります。
さらに、排他ロックが必要な場合は、irow を 1、fRefresh を FALSE、fLock を SQL_LCK_EXCLUSIVE として SQLSetPos を呼び出します。