UbuntuでnanodbcからSQLServerに接続する #2 - テスト編
前回の記事では Ubuntu 環境下で nanodbc の構築とテストを実施しました。
C++ で ODBC 接続するのに便利な nanodbc は、そのテスト範囲も広かったです。
もう少し nanodbc で用意されているテストについて掘り下げてみます。
1. テスト内容
SQL Server 用のテスト mssql_test.cpp の内容を簡単にまとめてみました。
次の表は MS 版 ODBC ドライバでのmake test
の実行結果です。
# | テスト項目 | 内 容 | 結果 |
---|---|---|---|
1 | test_driver | 接続文字列"DRIVER"の確認 | OK |
2 | test_affected_rows | DDL/DMLを発行してresult::affected_rows()の確認 | OK |
3 | test_batch_insert_integral | int型の配列の値をまとめてINSERTした後、SELECTして確認 | OK |
4 | test_batch_insert_string | std::string型の配列の値をまとめて、varchar(60)にINSERTする | OK |
5 | test_batch_insert_mixed | int, std::string, float型の配列の値をまとめて、int, varchar(60), float に INSERTする | OK |
6 | test_batch_insert_describe _param |
statement::describe_param()で値をまとめてINSERTする | OK |
7 | test_blob | バイト列をvarbinary(max)で格納 | OK |
8 | test_large_blob | ファイルをvarbinary(max)で格納 | OK |
9 | test_large_blob_geometry | STGeomFromText()でgeometryインスタンスを作成して格納 | OK |
10 | test_large_blob_geometry _with_bind_statement |
STGeomFromText()でgeometryインスタンスを作成してプレースホルダを経由 | OK |
11 | test_blob_with_varchar | 文字列をvarbinary(max)で格納 | OK |
12 | test_block_cursor_with _nvarchar |
2行INSERTした後、SELECT時にrowset_size=2として動作確認 | OK |
13 | test_block_cursor_with _nvarchar_and_first_row _null |
1行目がNULL値で2行INSERTした後、SELECT時にrowset_size=2として動作確認 | OK |
14 | test_block_cursor_with _nvarchar_and_second _row_null |
2行目がNULL値で2行INSERTした後、SELECT時にrowset_size=2として動作確認 | OK |
15 | test_blob_retrieve_out_of _order |
"Invalid Description Index"の発生を確認 ※元ネタはこちらとの事。 |
OK |
16 | test_catalog_list_catalogs | catalog::list_catalogs()の確認 データベース一覧 |
OK |
17 | test_catalog_list_schemas | catalog::list_schemas()の確認 スキーマ一覧 |
OK |
18 | test_catalog_columns | calalog::find_columns()の確認 カラム情報 |
OK |
19 | test_catalog_primary_keys | catalog::find_primary_keys()の確認 主キー情報 |
OK |
20 | test_catalog_tables | catalog::find_tables()の確認 テーブル情報 |
OK |
21 | test_catalog_table _privileges |
catalog::find_table_privileges()の確認 テーブルの権限 |
OK |
22 | test_column_descriptor | result::column_name(), result::column_datatype()等の確認 | OK |
23 | test_connection _environment |
connectionオブジェクトと接続環境の情報確認 | OK |
24 | test_dbms_info | connection::dbms_name(), connection::dbms_version()の確認 | OK |
25 | test_get_info | connection::get_info<T>()の確認 | OK |
26 | test_decimal_conversion | decimal型の変換精度の確認 | OK |
27 | test_exception | 実行時例外発生の確認 | OK |
28 | test_execute_multiple _transaction |
statement::prepare()で複数回実行 transaction付き |
OK |
29 | test_execute_multiple | statement::prepare()で複数回実行 | OK |
30 | test_integral | int型, float型, double precision型の確認 double precisionはfloat(53)のシノニム |
OK |
31 | test_move | connectionのstd::move()を確認 | OK |
32 | test_null | NULL値のバインド、NULL値判別の確認 | OK |
33 | test_nullptr_nulls | statement::bind()の第3パラメータにnullptrを指定時の動作確認 | OK |
34 | test_result_iterator | resultの各種イテレーション確認 | OK |
35 | test_simple | 接続から結果解析まで一連のテスト | OK |
36 | test_string | std::stringとvarchar型の確認 | OK |
37 | test_string_with_nvarchar _max |
std::stringとnvarchar(max)型の確認 | OK |
38 | test_string_with_varchar _max |
std::stringとvarchar(max)型の確認 | OK |
39 | test_string_with_ntext | std::stringとntext型の確認 | OK |
40 | test_string_with_text | std::stringとtext型の確認 | OK |
41 | test_string_vector | std::vector<std::string>で用意したパラメータをstatemet::bind_strings()でバインドする | OK |
42 | test_batch_binary | std::vector<std::vector<uint8_t>>で用意した複数行のバイト列をバインドする | OK |
43 | test_time | nanodbc::timeとtime型の確認 | OK |
44 | test_date | nanodbc::dateとdate型の確認 | OK |
45 | test_datetime | nanodbc::timestampとdatetime型の確認 | OK |
46 | test_decimal | decimal(19,4)型の精度確認 | OK |
47 | test_money | money型の精度確認 | OK |
48 | test_datetime2 | datetime2型の精度確認 | OK |
49 | test_datetimeoffset | datetimeoffset型の精度確認 | Failed |
50 | test_statement_with _empty_connection |
statementオブジェクトに空の接続を指定した場合の動作確認 | OK |
51 | test_transaction | transaction付きの一連の動作確認 | OK |
52 | test_while_not_end _iteration |
result::at_end()で判断してからresult::next()して処理 | OK |
53 | test_while_next_iteration | result::next()の戻り値で判断して処理 | OK |
- | test_async | Windowsのみ。 | - |
- | test_bind_variant | Windowsのみ。 | - |
Linux 環境での mssql_tests のテスト内容は、以上の 53 項目です。
意訳/異訳/省略してる箇所もありますが、テストの内容はこんな感じです。
2. test_datetimeoffset の失敗について
ソースコードを読むと、現在の nanodbc の仕様では、datetimeoffset 型の値は SQL_C_SS_TIMESTAMPOFFSET ではなく、SQL_C_TIMESTAMP として扱うようです。
その際、タイムゾーンに基づいたローカルタイムへの変換を引き起こす、との事。
テストでは datetimeoffset 型に '2006-12-30T13:45:12.345-08:00' をINSERTします。
この値は、日本のタイムゾーンに従って変換されると、日付が変わってしまいます。
・datetimeoffset_test.sql :
このクエリの実行結果がこちらです。
$ sqlcmd -Slocalhost -Usa -Pabcd1234$ -i datetimeoffset_test.sql
tz dt
--- ---------------------------------------------
2006-12-30 13:45:12.3450000 -08:00
PST 2006-12-30 13:45:12.3450000 -08:00
UTC 2006-12-30 21:45:12.3450000 +00:00
JST 2006-12-31 06:45:12.3450000 +09:00
これは、nanodbc というより Time Zone / Local Time の解釈の程度問題かと。
テストを通過するには、ソースコードの当該 REQUIRE を改変するしかないです。
3. 補足 : FreeTDS の ODBC ドライバの場合
Ubuntu 18.04 LTS のパッケージ tdsodbc (1.00.82) でも試してみました。
詳細は省きますが、テストの 53 項目中 23 項目が失敗します。
試してませんが、本家 FreeTDS stable版 1.1.26 だと、結果が異なるかもしれません。
....
FreeTDS の名誉の為に書きますが、私はこの結果をあまり問題視していません。
テストの REQUIRE と実行結果の差異は、nanodbc 利用時の挙動を確認する手段でしかない、という認識です。
実際、 tdsodbc は細かい部分で、MS 版 ODBC ドライバとは挙動が異なります。
例えば、#46 test_deciaml の件では、数値型 decimal(19,4) を受ける際、64bit 固定小数で扱える最大値・最小値を評価します。
MS 版 ODBC は文字列と同じですが、tdsodbc では数値として double で丸めた後に文字列化した値と同じになり、評価としては小数部の一部が欠落したように見えます。
C++のプリミティブ型に 64bit 固定小数型が存在しない以上、受けた値をどのように扱うかは Coder 次第かなと。
続きはこちら
- UbuntuでnanodbcからSQLServerに接続する #1 - 導入編
- UbuntuでnanodbcからSQLServerに接続する #2 - テスト編
- UbuntuでnanodbcからSQLServerに接続する #3 - 追試編 ←続き