導入
こんにちは。phpでお仕事してます。
お仕事の傍、php-srcのコントリビュータもしています。
今回、phpのodbc_connect()
およびodbc_pconnect()
の改修をするにあたり、いろんなODBCドライバの挙動を見る必要が出てきてIBMi db2に初めて触ることになりました。
日本語にしろ英語にしろまとまった情報源がなく、かなり手探りで接続までたどり着いたので、備忘録を兼ねて記事にすることにしました
なお、この記事では
- DBにPUB400のIBMi db2を使用
- phpは8.4(執筆時点のphp-src masterブランチのビルド)、localのdocker ubuntu22.04環境
での操作の備忘録となります(ただし、php-srcのビルドは本記事の趣旨と逸れるので、割愛します)。
IBMi db2とは
IBMiに搭載されているdb2のことです。IBMiについての説明はwikipedia先生に任せます。
Linuxなどとは全然違うので、同じdb2でもドライバが違っていたりします。
IBMiを利用する
IBMiの実機を気軽に手に入れるのは現実的ではないので、IBMiの学習用サービスを利用します。
PUB400.COM - Your public IBM i server
こちらのサービスでは、400MBまでですが無料でIBMiを使用することができます(学習用です)。
PUB400に登録する
登録すると、結構経ってから登録確認メールが届きます。メールアドレスの認証を終えると初期ログイン情報その他諸々が記載されたメールが届きます。
初期設定を行なう
初期設定とは言っても、初期パスワードを変更するだけです。初期パスワードの変更をした後なら、SSH接続もできるようになります。
では最初の接続はどうするか?というと、IBM 5250のターミナルエミュレータからTelnetで接続します。
IBM 5250の実機をお持ちの方はそちらを使用してもいいと思います。
私はMacOSなので、「Mocha TN5250 Lite」を利用しました。
Mocha TN5250 Liteの設定
設定項目が色々ありますが、
- IPに「PUB400.COM」
- Userに、メールに記載されているユーザ名
- Passwordに、初期パスワード
を入力する以外はデフォルトのままで問題ありません。
「設定を保存する」というようなボタンなどないロックな仕様なので、「×」で設定画面を閉じます。
いざIBMiに接続
上部メニューの「Open」を押下すると、接続できます。
初手、パスワードの変更を求められます。
ちなみに、入力欄はEnterやTABで移動するのではなく普通に十字キーで移動します。画像のカーソル位置が文字入力開始位置なのですが、普通に後ろ方向へもカーソルが移動できます。
そして、開始位置ピッタリからちゃんと入力しないとエラーで怒られます。なんてロック。
最後のドットの真横の位置から、カーソル2つ分右に移動したところが文字入力開始位置です。
全部入力したら、Enter押下でパスワードが更新されます。怒られる場合は大体カーソルの位置が間違っています。
以上で、db2に接続するためのIBMi側の操作は終了です。
ubuntu側の準備をする
php本体とodbc extをインストールした状態だとします。
他、curl, unixodbc, unixodbc-devあたりが入っていると良いと思います(php odbcが入っている時点でunixodbc系は多分入っているのではないかと思います)。
IBMのリポジトリを追加する
ibm-iaccessというパッケージをインストールすることで、IBMi db2用のODBCドライバが手に入ります。
そのために、IBMのリポジトリを追加します。
ubuntuでは次のコマンドで追加できます。apt系なら同じなので、Debianもこれでいけます。dockerなのでsudoはつけません。環境によってはつけてください。
curl https://public.dhe.ibm.com/software/ibmi/products/odbc/debs/dists/1.1.0/ibmi-acs-1.1.0.list | tee /etc/apt/sources.list.d/ibmi-acs-1.1.0.list
Redhat系ならこちら。こちらもsudoは環境次第です。
curl https://public.dhe.ibm.com/software/ibmi/products/odbc/rpms/ibmi-acs.repo | tee /etc/yum.repos.d/ibmi-acs.repo
ibm-iaccessをインストール
リポジトリを追加したら、updateしてからibm-iaccessをインストールします。これもsudoは環境次第。Redhat系はyumで読み替えてください。
apt-get update
apt-get install ibm-iaccess
odbcinst.iniの確認
odbcの設定ファイルとも言えるodbcinst.ini
を確認します。ubuntu22.04のdocker環境では、次の場所にありました。
/etc/odbcinst.ini
docker使うのであればvolumeをマウントしてしまって、ホストOSからすぐ確認できるようにしておくと便利です。
ibm-iaccessをインストールすると、次のような項目が追加されました。
[IBM i Access ODBC Driver]
Description=IBM i Access for Linux ODBC Driver
Driver=/opt/ibm/iaccess/lib/libcwbodbc.so
Setup=/opt/ibm/iaccess/lib/libcwbodbcs.so
Driver64=/opt/ibm/iaccess/lib64/libcwbodbc.so
Setup64=/opt/ibm/iaccess/lib64/libcwbodbcs.so
Threading=0
DontDLClose=1
UsageCount=1
[IBM i Access ODBC Driver 64-bit]
Description=IBM i Access for Linux 64-bit ODBC Driver
Driver=/opt/ibm/iaccess/lib64/libcwbodbc.so
Setup=/opt/ibm/iaccess/lib64/libcwbodbcs.so
Threading=0
DontDLClose=1
UsageCount=1
自動で設定されるって楽ですね...。
私は64bit環境ですので、64ibitの方を使用します。
[]
で括られている文字列IBM i Access ODBC Driver 64-bit
を、後で接続文字列として使用します。
ここまででubuntuの準備は完了です。
phpを書く
接続用のphpを書きます。こんな感じです。
<?php
$db = odbc_pconnect(
'Driver={IBM i Access ODBC Driver 64-bit};System=PUB400.COM;Port=50000;protocol=TCPIP',
'ユーザ名',
'パスワード'
);
接続文字列については、次のようになります(uidとpwdをここに含めることもできるのですが、ちょっとその辺り今改修中で色々どうなるかわからないので触れません)。
- Driver => 先ほど確認した
odbcinst.ini
の項目名 - System => 要はホスト名。PDO MySQLで言うところの
host
と同義 - Port => 50000
- protocol => TCPIP
ユーザー名とパスワードは、IBMiの認証情報と全く同じです。ロック。
いざ実行
phpを実行してみましょう。
認証に成功すると、何も出力されずに終了します。
認証失敗時は次のようなエラーになります。
Warning: odbc_pconnect(): SQL error: [IBM][System i Access ODBC Driver]Communication link failure. comm rc=8002 - CWBSY0002 - Password for user {ユーザ名} on system PUB400.COM is not correct, Password length = 0, Prompt Mode = Never, System IP Address = {多分相手のIP}, SQL state 28000 in SQLConnect in {phpファイル}
また、レアケースですがシンタックスエラーを引いた場合は次のようになります(こうならないように今改修頑張ってます)。
Warning: odbc_pconnect(): SQL error: [IBM][System i Access ODBC Driver]Syntax error in connection string., SQL state S1000 in SQLConnect in {phpファイル}
まとめ
IBMiを比較的手軽に利用できるサービスがあるのはとても助かります。
情報が少ないというか、あるにはあるのですがかなり断片化していて、最短かつ正解の手順の確立まで結構苦労しました。
phpでIBMi db2へODBCで接続しようとして困っているとても珍しい人のお役に立てたら幸いです。