- Java
- C言語
- .Net(Windowsのみ)
まず、system ユーザーでログインして試験用ユーザーを作成
~$ sqlplus SQL*Plus: Release 10.2.0.1.0 - Production on Fri Sep 7 13:22:00 2012 Copyright (c) 1982, 2005, Oracle. All rights reserved. Enter user-name: system/manager Connected to: Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production SQL> create user extproc_test identified by extproc_test 2 default tablespace users temporary tablespace temp; User created. SQL> grant connect, resource, create library to extproc_test; Grant succeeded.次に試験用ユーザーでログインして、共有ライブラリの場所を指定。
SQL> connect extproc_test/extproc_test Connected. SQL> create library extproc_test as '${ORACLE_HOME}/lib/extproc_test.so'; 2 / Library created.$ORACLE_HOME/lib, $ORACLE_HOME/bin 以外の場所に共有ライブラリを置くときは 環境変数EXTPROC_DLLSを設定すること。
次にSQL関数を作成。
SQL> create function add_func(x pls_integer, y pls_integer) 2 return pls_integer 3 as language C library extproc_test name "add_func"; 4 / Function created.次にC言語の関数を作成。
int add_func(int x, int y) { return x + y; }pls_integer はデフォルトでは C 言語の int にマッピングされる。
コンパイルして $ORACLE_HOME/lib にコピー。
$ gcc -shared -o extproc_test.so extproc_test.c $ cp extproc_test.so $ORACLE_HOME/lib実行してみる。
SQL> select add_func(1, 2) from dual; ADD_FUNC(1,2) ------------- 3期待通りに動いた。
試しにNULLを渡してみる。
SQL> select add_func(1, NULL) from dual; select add_func(1, NULL) from dual * ERROR at line 1: ORA-01405: fetched column value is NULLC言語では NULL かどうかの判断ができないから当然か。。。
C言語側にNULLかどうかのフラグを渡せるよう関数定義を修正する。
SQL> create or replace function add_func(x pls_integer, y pls_integer) 2 return pls_integer 3 as language c library extproc_test name "add_func" 4 parameters(x, x indicator, y, y indicator, return indicator); 5 / Function created.parameters の指定に従い、C言語の関数定義も変更する。
#include再度コンパイルしてコピー。int add_func(int x, short x_ind, int y, short y_ind, short *rind) { if (x_ind || y_ind) { /* x または y が NULL のとき */ *rind = OCI_IND_NULL; /* 戻り値は NULL */ return 0; } *rind = 0; /* 戻り値は非NULL */ return x + y; /* 戻り値 */ }
$ gcc -shared -o extproc_test.so extproc_test.c -I$ORACLE_HOME/rdbms/public $ cp extproc_test.so $ORACLE_HOME/lib実行してみる。
SQL> select add_func(1, NULL) from dual; select add_func(1, NULL) from dual * ERROR at line 1: ORA-28576: lost RPC connection to external procedure agent使用中の共有ライブラリを上書きしたせいか、それともメモリ上には古い共有ライブラリが 載っているのにOracle側の関数定義を変えたせいか。 まあ、どちらにしても、これでextprocプロセスが再起動してくれれば次はうまく行くはず。
SQL> select add_func(1, NULL) from dual; ADD_FUNC(1,NULL) ----------------今度は動いた。
念のため非NULL値の試験も行う。
SQL> select add_func(1, 2) from dual; ADD_FUNC(1,2) ------------- 3動いた。
以上。