前々回、前回の記事でMariaDBからOracleやSQL Serverのデータを取得するため、unixODBCとCONNECTストレージエンジンを使って環境を構築した。
一部動作が怪しい所はあるものの概ね問題なく動いているのだが、一つ困ったこととして「エラーメッセージが文字化けする」という問題がある。
エラーメッセージ文字化け問題(Oracle編)
Oracleのビューに対してCONNECTでCREATE TABLEし、そのテーブルに対して編集しようとした(つまりビューを編集しようとした)らこのようなエラーメッセージが出た。
#HY000Got error 122 'Remote SQLExecDirect: [Oracle][ODBC][Ora]ORA-01732: ã\0081"ã\0081®ãƒ"ューã\0081§ã\0081¯ãƒ‡ãƒ¼ã‚¿æ"\008D作ã\0081Œç„¡åŠ¹ã\0081§ã\0081™
ヘルãƒ--: https://docs.orac' from CONNECT
↑ビューは編集できないのは分かるし、ORA-xxxxxの番号があるのでWeb検索すればエラー内容は理解できるんだけど、見事に文字化けしてる...。
まず調べてみた所、OracleのエラーメッセージはNLS_LANGに依存するとのこと。
確かに前々回の記事でSQL取得結果(日本語文字列)が「?」に文字化けしてしまうことから、環境変数に下記を設定した。
NLS_LANG=JAPANESE_JAPAN.JA16SJISTILDE
これによりエラーメッセージも日本語で表示されるようになったわけだ。
そこまではいいのだが、肝心の文字化けしてしまう原因については、どうやらUnixODBCがコード変換時に誤ってISO-8859-1でエンコードしてしまっているらしい。うーんポンコツ。困った。
エラーメッセージ文字化け問題(SQL Server編)
SQL Server側でも同じ問題が出ている。
#HY000Got error 174 'SQLDriverConnect: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]ユーザー 'user' ã\0081¯ãƒã‚°ã‚¤ãƒ³ã\0081§ã\0081\008Dã\0081¾ã\0081›ã‚"ã\0081§ã\0081--ã\0081Ÿã€‚' from CONNECT
↑ユーザーID/パスワードが間違っているときに出るエラーメッセージ。こちらはOracleと違ってエラー番号が無いので完全に意味不明。
#HY000Got error 174 'SQLExecDirect: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]üïüÉ 'key' ØÑk
i\0007jˇLBŠ~Y\0002' from CONNECT
↑存在しないカラムをSELECTしようとした時のエラーメッセージ。こっちも見事に文字化けしている。
いろいろと調べてみると、SQL Serverについては間に「FreeTDS」というツールを間に挟み、odbc.iniに
client charset = UTF-8
server charset = CP1252
のようにクライアント、サーバーそれぞれの文字コードを指定することで解決できるらしい。
が、このツールでSQL Server側の問題は解決したとしても、Oracle側の問題は解決できそうにない。
逃げの一手
さらに調べるも、文字コードのミスマッチを解消するのは難しいと判断。
(根本原因であるUnixODBCを自分で直してプルリクを出すぐらいの工数があれば話は別だが...)
仕方なく考え方を変えることに。
つまり「メッセージが日本語だから文字化けする」わけで、「エラーメッセージを英語で返すようにしてしまえばいい」のだ(ちょっと苦しいか...)
SQL Serverの言語設定を英語にする
幸いにもSQL Server側は接続文字列に Language=English を追加すればいい、ということが分かった。
/etc/odbc.iniを開き、SQLServerのDSN定義に
Language=English
を追加した。
その他にも接続文字列に指定できるパラメータはこちらに記載がある。
記載した内容はMariaDBのサービスを再起動すれば反映される。
# sudo systemctl restart mariadb.service
再度SQLを実行してみると、
#HY000Got error 174 'SQLExecDirect: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Invalid column name 'aaaid'.' from CONNECT
↑存在しないカラムをSELECTしようとした時のエラーメッセージ。英語になった。
HY000Got error 174 'SQLDriverConnect: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]ユーザー 'user' ã\0081¯ãƒã‚°ã‚¤ãƒ³ã\0081§ã\0081\008Dã\0081¾ã\0081›ã‚"ã\0081§ã\0081--ã\0081Ÿã€‚' from CONNECT
↑ただ、ログインエラーだけは変わらなかった。
どうやら接続文字列で設定した内容はSQLExecDirectには効力はあるものの、SQLDriverConnectには影響しないようだ。
いろいろ試してみたがここの文字化けは解決できず。まぁ滅多に起きないエラーなので無視していいだろう。
Oracleの言語設定を英語にする
Oracleは先述のとおりNLS_LANGによってエラーメッセージの言語を設定しているとのことなので、
# systemctl edit mariadb.service
を叩いて下記を追記して、
[Service]
Environment=NLS_LANG=AMERICAN_AMERICA.JA16SJISTILDE
下記コマンドを叩いてサービスを再起動する。
# systemctl restart mariadb.service
これで「言語指定は英語」「文字セットは日本語(SJISチルダ)」という指定ができた。
データはSJISで取得しつつ、メッセージは英語で表示されるようになる。
#HY000Got error 122 'Remote SQLExecDirect: [Oracle][ODBC][Ora]ORA-00971: missing SET keyword
Help: https://docs.oracle.com/error-help/db/ora-00971/' from CONNECT
↑ビューを変更しようとしたときのエラーメッセージ。(出てくるエラーはちょっと違うけど)無事、英語にはなった。
一旦は解決したが・・・
とりあえずエラーメッセージを英語にすることで文字化けは回避できたが、根本的な解決にはなっていない。
例えばOracleやSQL Server側に「日本語のテーブル名」や「日本語のカラム名」があった場合、CONNECTでリンクしたテーブルはテーブル名やカラム名が文字化けしてしまい、SELECTしてもエラーになってしまう。
一応この問題にも「逃げの一手」はあって、「日本語名を含まないビューを別途作ってそれをCONNECTでリンクする」ことで回避は可能。
ただリンク先DBに(ビューを作るなどの)手を加える必要があるためイマイチ。現状の「逃げ」はちょっとモヤモヤするのが正直なところ。
UnixODBCのエンコード問題が根本原因だと思われるが、検証する余力がないため現状打つ手がない。誰か直してくれないかなぁ(他力本願)
コメントする