[AWS] MariaDB+unixODBCでCONNECT接続時に文字化けする問題

前々回前回の記事で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のエンコード問題が根本原因だと思われるが、検証する余力がないため現状打つ手がない。誰か直してくれないかなぁ(他力本願)

コメントする