2. はじめに
●
本日は PostgreSQL 14 で追加予定の
SQL-standard function body
についてお話します
●
2021/4/7 に PostgreSQL の HEAD に commit されました
– https://git.postgresql.org/gitweb/?
p=postgresql.git;a=commit;h=e717a9a18b2e34c9c40e5259ad4d31cd
7e420750
●
すでに HEAD で利用可能ですが 仕様変更 or revert される
可能性もあるため、参考程度にお聞きください
3. SQL-standard Function Body について
●
CREATE FUNCTION / PROCEDURE によるユーザ定義関数を
作成する際の新しい記述方法です
●
従来は PostgreSQL 特有の記述方法でしたが、 SQL 標準に即した
記述方法がサポートされました
– MySQL や DB2 、 SQL Server などでも類似の記述方法が可能
●
従来の書き方も継続して利用できます
●
LANGUAGE SQL でのみ有効です
– PL/PgSQL や PL/python などのプロシージャ言語ではサポー
トされていません
4. 記述例
●
従来の書き方
CREATE FUNCTION f_test1(int, int)
RETURNS bigint
LANGUAGE sql
AS 'SELECT $1 + $2;';
--AS $$ SELECT $1 + $2 $$;
CREATE FUNCTION f_test2(int)
RETURNS text
LANGUAGE sql
AS 'SELECT name FROM t WHERE id = $1;';
--AS $$ SELECT name FROM t WHERE id = $1 $$;
CREATE FUNCTION fb_test1(int, int)
RETURNS bigint
LANGUAGE sql
RETURN $1 + $2; --RETURN 式
CREATE FUNCTION fb_test2(int)
RETURNS text
LANGUAGE sql
BEGIN ATOMIC
SELECT name FROM t WHERE id = $1;
-- 複数のステートメントを記述可能
END;
●
新しい書き方
5. SQL-standard Function Body の特長 1
●
関数定義時にパースされ、その結果 (Expression nodes) が
pg_proc システムテーブルに格納される
– 従って以降の実行時はパースがスキップされる
– 従来の記述方法は実行時にパースされる
– 若干ですが性能上の恩恵があるかもしれません
SELECT proname, prosrc, substr(prosqlbody,1,50) as body
FROM pg_proc WHERE proname IN ('f_test', 'fb_test');
proname | prosrc | body
---------+-----------------------------------+----------------------------------------------------
f_test | SELECT name FROM t WHERE id = $1; |
fb_test | | (({QUERY :commandType 1 :querySource 0 :canSetTag
6. SQL-standard Function Body の特長 2
●
関数定義時にパースされるため、実行時に決定される多様型は
使えません
– 多様型を使う場合は従来の書き方で・・
=# CREATE FUNCTION f_test_poly (anyelement, anyelement)
RETURNS anyarray
LANGUAGE sql
AS 'SELECT ARRAY[$1, $2];' ;
CREATE FUNCTION
=# CREATE FUNCTION fb_test_poly (anyelement, anyelement)
RETURNS anyarray
LANGUAGE sql
RETURN ARRAY[$1, $2];
ERROR: SQL function with unquoted function body cannot have polymorphic arguments
7. SQL-standard Function Body の特長 3
●
関数定義時にパースされると共に、依存関係の解析がされ pg_depend システ
ムテーブルで管理されるようになります
– 厳密には、関数が依存 ( 利用 ) しているオブジェクトは何か?を管理するよ
うになります
=# CREATE TABLE t (id int, name text);
--テ ブル
ー tを参照する2つの 数を作成
関
=# CREATE FUNCTION f_test(int) RETURNS text LANGUAGE sql AS 'SELECT name FROM t WHERE id = $1;';
=# CREATE FUNCTION fb_test(int) RETURNS text LANGUAGE sql BEGIN ATOMIC SELECT name FROM t WHERE id = $1;
END;
=# SELECT * FROM pg_depend WHERE objid = 'fb_test'::regproc; --()内情 は 足したもの
報 補
classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype
---------------+----------------+----------+--------------------+--------------+-------------+---------
1255(pg_proc) | 16409(fb_test) | 0 | 2615(pg_namespace) | 2200(public) | 0 | n
1255(pg_proc) | 16409(fb_test) | 0 | 1259(pg_class) | 16403(t) | 1 | n
1255(pg_proc) | 16409(fb_test) | 0 | 1259(pg_class) | 16403(t) | 2 | n
8. SQL-standard Function Body の特長 3
●
関数が参照しているオブジェクトを削除する場合、 CASCADE
オプションで関数も一緒に削除してくれます
– スキーマ管理の運用性向上に役立つでしょう
--前ペ ジからの き
ー 続
=# DROP TABLE t;
ERROR: cannot drop table t because other objects depend on it
DETAIL: function fb_test(integer) depends on table t
HINT: Use DROP ... CASCADE to drop the dependent objects too.
=# DROP TABLE t CASCADE;
NOTICE: drop cascades to function fb_test(integer)
DROP TABLE
-- 来の 述方法で作成した
従 記 function f_test(integer) は残る
9. SQL-standard Function Body の特長 4
●
SQL 標準に準拠しているので、移植性が ( 多少 ) 向上します
– PostgreSQL から他の DBMS へ、あるいはその逆の移行時
などに便利
●
PostgreSQL の system functions のいくつかは SQL-
standard-body style に書き直されました