暗黙スキーマの挙動の違い
PCからお手軽に、既存のIBM i(AS/400)のプログラムを呼び出す方法に、SQLのCALLを投げる方法があります。こんな感じで
■PC系の文法
CALL スキーマ名.プログラム名 ('引数','引数2')
CALL スキーマ名/プログラム名 ('引数','引数2')
通常自分は、ユーザーによって実行ライブラリが異なる可能性があるので、ライブラリ名(スキーマ名)を指定しません。スキーマ名を変数にしても良いのですが、AS/400の伝統的に暗黙のオープンというのがあります。暗黙オープンの方法としては...
- ユーザージョブの”ライブラリーリスト”に入れる。
- ”set schema ライブラリ名”をする。
が、考えられます。前者は、本番運用向きとは思いますが、開発の場合は環境毎にユーザーが変わるので、自分は後者の「set schema」を使っています。
この”暗黙のスキーマ”なのですが、PHPのDB2関数で、微妙にAS/400とPCで挙動の違いが有ったので、メモをしておきます。
AS/400(Zend Core for i5 2.6.1)の場合は、”set schema”でスキーマを指定すれば、暗黙でプログラムをcall出来ます。しかし開発用PC(Zend Server CE 4.0)から発行されたSQLの場合には、次の様なメッセージが返されました。
call hoge ('fuga') SQL0204N "ユーザ名.hoge" は未定義の名前です。 SQLSTATE=42704
PHPのDB2関数かDB2 Connectなのか分かりませんが、暗黙のスキーマが見つからない場合は、自動でユーザー名を明示的スキーマに置き換えます。(間違って存在していて勝手にプログラムが動かれても困りますが...。)
今回は対応方法として、AS/400のプログラムをストアドプロシージャ定義する事にしました。方法は以下の通りです。
-
- OPMプログラムならばILE化する。(OPMだとストアド情報の保管・復元が出来ないため)
- ”create procedure”で、プログラムをストアド定義する。
■ストアド定義SQLの例(※CLプログラムで5バイト文字列の引数を1つ取る場合)
CREATE PROCEDURE スキーマ名/プロシージャ名(IN 引数名 CHAR (5 )) LANGUAGE CL NOT DETERMINISTIC CONTAINS SQL EXTERNAL NAME ライブラリ名/プログラム名 PARAMETER STYLE GENERAL
-
- 実行時に”set path スキーマ名”で関数パスを指定して、プロシージャ名をcallで呼びだす。
OPMをILE化するのは、SAVLIBやRSTLIBでストアド定義の情報が反映されないからです。検証してわかったのですが、プログラムのリネームや削除、ライブラリのリネームをしてもストアド情報と同期はされません。プログラムをSAVOBJ,RSTOBJしても同様に、ストアド情報は同期されませんでした。但し、ライブラリを削除した時だけは、ストアド情報も消えるようです。ライブラリを保管→ライブラリ削除→ライブラリ復元だと、ストアド情報も同期された状態で、復元しました。この事から、ILEオブジェクトの何処かに、ストアドに関するメタ情報を持っていると思うのですが、何処にあるか見つける事が出来ませんでした。(DSPPGMなどには無かった)
※追記:その後、DMPOBJコマンドでメタ情報を確認出来ました。SQL文が丸ごと残ってます。
ちなみに、OPMでストアド定義すると、プロシージャは作成されますが、その旨の警告メッセージが出力されました。
■注意書き(※DB2 Universal Database for iSeries SQL 解説書より)
*PGM オブジェクトが保管された後、このシステムや別のシステムに復元すると、カタログはそれらの属性を使用して自動的に更新されます。 外部プロシージャーの場合は、次の制約の範囲内で属性を保管することができます。 ・ 外部プログラム・ライブラリーは、QSYS であってはなりません。 ・ 外部プログラムは、CREATE PROCEDURE ステートメントの発行時に存在していなければなりません。 ・ 外部プログラムは、ILE *PGM オブジェクトか*SRVPGM オブジェクトにする必要があります。 オブジェクトを更新できない場合でも、それにかかわらず、プロシージャーは作成されます。
これでプロシージャ名を呼び出せば、AS/400でもPCでも暗黙的にプログラムを呼び出す事が出来ます。
但しこの場合は、プログラム名の呼出と違って、AS/400でも”set path”で関数パスを指定する必要があります。ちなみに、ジョブのライブラリーリストに入っていれば、”set path”は不要です。本番運用ならばライブラリーリストでやるのが、一番楽チンかもしれませんネ。
ストアドプロシージャ定義の一覧を確認するには、次のSQLを投げると確認出来ます。
select * from sysroutines where specific_schema = 'スキーマ名'