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