ODBC Driver for Linux での API パラメータの文字コードについて

Microsoft Japan Data Platform Tech Sales Team

中川

先日、とあるパートナー様より標題の件についてご質問をいただきました。例えば SQLGetDiagRec 関数のマニュアルを見ますと ”MessageText” の型は SQLCHAR となっております。そして、Microsoft ODBC Driver for SQL Server on Linux のプログラミングガイドラインには以下のような記述がございます。

文字のサポート

SQLCHAR データは、UTF-8 である必要があります。 SQLWCHAR データは UTF 16LE (リトル エンディアン) である必要があります。

Microsoft ODBC Driver for SQL Server on Linux の ODBC API のパラメータの内、 文字列部分の多くは SQLCHAR で定義されております。よって標題のご質問に対する回答は UTF-8 ということになります。

以上です、で終わってしまっては寂しいので実機にて確認してみました。

 

[実機環境]

APサーバー

OS : Redhat 6

ODBC Driver : ODBC Driver 11 for SQL SQL Server on Redhat

DBサーバー

OS : Windows Server 2012 R2

DB Software : SQL Server 2014 SP1

DB : AdventureWorks2014

 

[確認手順]

1. 先ずはこちらより msodbcsql-11.0.2270.0.tar.gz をダウンロードします。

2. Linux 環境で展開します。

$ tar zxvf msodbcsql-11.0.2270.0.tar.gz

3. unixODBC Driver Manager をインストールします。詳細についてはこちらをご参照ください。(2016/7/20追記)

$ cd msodbcsql-11.0.2270.0

$ sudo ./build_dm.sh

4. ODBC Driver をインストールするために事前チェックを実行します。事前チェック、インストールの詳細についてはこちらをご参照ください。(2016/7/20追記)

$ sudo ./install.sh verify

5. 問題なければ ODBC Driver をインストールします。

$ sudo ./install.sh install

6. /etc/odbc.ini ファイルに以下を記述します。

[MSSQLTest]

Driver = ODBC Driver 11 for SQL Server Server = <Server Name or IP Address>,<必要であればポート番号>

7. /etc/odbcinst.ini に以下が登録されていることを確認します。

[ODBC Driver 11 for SQL Server]

Description=Microsoft ODBC Driver 11 for SQL Server Driver=/opt/microsoft/msodbcsql/lib64/libmsodbcsql-11.0.so.2270.0 Threading=1 UsageCount=1

8. 以下のようなテストコードを用意します。(なお、このコードはあくまでもサンプル用で簡略化しています。エラーハンドリングや注釈などもございませんがご了承ください。)

SQLGetDiagRecTest.c

 
 #include <stdio.h>#include <stdlib.h>#include <sqlext.h>#include <sql.h>int main() { SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt = 0; SQLRETURN retcode; SQLRETURN r = 0; SQLCHAR szSqlState[6] = { 0 }; SQLINTEGER fNativeError = 0; SQLCHAR szErrorMsg[256] = { 0 }; SQLSMALLINT cbErrorMsgMax = sizeof(szErrorMsg) - 1; SQLSMALLINT cbErrorMsg = 0;  char *strenv; strenv = getenv("LANG"); //printf("%s\n",strenv); // Allocate environment handle retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); // Set the ODBC version environment attribute if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {  retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);  // Allocate connection handle  if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);   // Set login timeout to 5 seconds   if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {    SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);    // Connect to data source    retcode = SQLConnect(hdbc, (SQLCHAR*) "MSSQLTest", SQL_NTS, (SQLCHAR*) "" , 5, (SQLCHAR*) "", 9);    // Allocate statement handle    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {     retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);     retcode = SQLExecDirect (hstmt, (SQLCHAR *) "USE [AdventureWorksDW2014]", SQL_NTS);     r = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt,(SQLSMALLINT) 1, szSqlState, &fNativeError, szErrorMsg, cbErrorMsgMax, &cbErrorMsg);     printf("%s\n",szErrorMsg);     if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {      SQLCancel(hstmt);      SQLFreeHandle(SQL_HANDLE_STMT, hstmt);     }     SQLDisconnect(hdbc);    }    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);   }  }  SQLFreeHandle(SQL_HANDLE_ENV, henv); }}

 

9. 上記ソースをコンパイル

$ export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib:/usr/local/include$ cc -m64 -g -I/usr/include -L/usr/local/lib -L/usr/lib -L/usr/local/include -lodbc -std=c99 -o SQLGetDiagRecTest SQLGetDiagRecTest.c

10. strace でトレースを取得

$ strace -o trace.log ./SQLGetDiagRecTest > SQLGetDiagRecTest.log

11. 出力結果の確認

トレースファイル ”trace.log“ を確認したところ、SQLGetDiagRec の MessageText 部分には以下が返ってきておりました。

"[Microsoft][ODBC Driver 11 for SQL Server][SQL Server]\343\203\207\343\203\274\343\202\277\343\203\231\343\203\274\343\202\271 \343\202\263\343\203\263\343\203\206\343\202\255\343\202\271\343\203\210\343\201\214 'AdventureWorksDW2014' \343\201\253\345\244\211\346\233\264\343\201\225\343\202\214\343\201\276\343\201\227\343\201\237\343\200\202\"

文字列としては “USE [AdventureWorksDW2014]" を実行しておりますので、以下が返ってきているはずです。

[Microsoft][ODBC Driver 11 for SQL Server][SQL Server]データベース コンテキストが 'AdventureWorksDW2014' に変更されました。

そこで、マルチバイト文字部分の赤字部分について文字コードを比較したところ以下となりました。

  UTF-8(8進)
\343\203\207
\343\203\274 
\343\202\277 
\343\203\231 
\343\203\274 
\343\202\271 

つまり、SQLGetDiagRec の SQLCHAR 型である MessageText 部分は UTF-8 であることが確認できました。

上記より、繰り返しとなりますが ODBC API を使用したアプリケーションを実装される際、 API パラメータ の SQLCHAR 型部分は UTF-8 となります。