oracle では PL/SQL から c で作成した外部ルーチンをコールするための機構として、 外部プロシージャコール (extproc) を用意しています。
extproc は $ORACLE_HOME/bin にあり、指定された共有ライブラリを動的にリンクし、 その中に含まれる指定された関数をコールします。
また extproc は tnslsnr から起動されます。 以下にプロセス概念図を示します。
oracle サーバ | tnslsnr | 外部プロシージャコール | ||
---|---|---|---|---|
PL/SQL | ipc ⇔ |
LISTENER | fork ⇔ |
extproc + 共有ライブラリ |
KROWN 13162 の例を作ります。(macB:ora817)
[ 課題 ] sample() を実行して、その返値が 1 の場合、テーブル sam に aaa をinsert します。 ただし、sample() は常に 1 を返します。
1. tnsnames.ora/listener.ora
tnsnames.ora
EXTPROC_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = extproc)) ) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO) ) )
listener.ora
LISTENER2 = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) ) ) SID_LIST_LISTENER2 = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /home1/METEOR/app/oracle/product/8.1.7) (PROGRAM = extproc) ) )
2. ライブラリの作成
cc -c sample.c -o sample.o ld -G -o sample.so sample.o cp sample.so /tmp
3. sql を作成し、登録する
SQL> @sample SQL> @gcd
4. 該当する listener を起動する
> lsnrctl start LISTENER2
5. PL/SQL のルーチンをコールする
SQL> execute test SQL> select * from sam; C ---------- aaa
6. extproc プロセスの確認
> ps -ef | grep extproc | grep -v grep ora817 19549 1 0 15:32 ? 00:00:00 extprocPLSExtProc (LOCAL=NO)
sample.c
int sample(){ return 1; }
sample.sql
-- テストテーブルの作成 create table sam(c char(10)); -- ライブラリの作成(共有ライブラリの場所をプルパスで指定) create or replace library sample10 as '/tmp/sample.so'; / -- sample を外部ファンクションとして登録 create or replace function gcd return binary_integer as external library sample10 name "sample" language c; /
gcd.sql
-- gcd をコール create or replace procedure test is g binary_integer; begin g := gcd(); -- gcd をコール if g = 1 then insert into sam values('aaa'); end if; end; /
oracle9i よりセキュリティが強化されたため、 listener.ora に以下の設定が必要になりました。
(ENVS="EXTPROC_DLLS=ANY")
また 32bit/64bit 版が作成できるものの場合は、特別な配慮が必要です。
(ENVS="XXXXX/lib:XXXXX:lib32")
外部プロシージャがコールされたかどうかは、以下で確認できます。 以下のコマンドで出力があれば、起動された extproc が動いていることを確認できます。 またエラーなどは $ORACLE_HOME/rdbms/log に書かれます。
truss -f -vall -o ext.truss -p IPC_TNSLSNR_PID
質問
ORA-28575: 外部プロシージャ・エージェントへのRPC接続をオープンできません。 ORA-06512: "TAKA.GCD", 行 0 ORA-06512: "TAKA.TEST", 行 4