PostgreSQL v14 で追加 ( 予定 ) の
SQL-standard function body
2021.5.11
第 23 回 PostgreSQL アンカンファレンス @ オンライン
笠原辰仁 @kasa_zip
はじめに
●
本日は 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 される
可能性もあるため、参考程度にお聞きください
SQL-standard Function Body について
●
CREATE FUNCTION / PROCEDURE によるユーザ定義関数を
作成する際の新しい記述方法です
●
従来は PostgreSQL 特有の記述方法でしたが、 SQL 標準に即した
記述方法がサポートされました
– MySQL や DB2 、 SQL Server などでも類似の記述方法が可能
●
従来の書き方も継続して利用できます
●
LANGUAGE SQL でのみ有効です
– PL/PgSQL や PL/python などのプロシージャ言語ではサポー
トされていません
記述例
●
従来の書き方
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;
●
新しい書き方
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
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
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
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) は残る
SQL-standard Function Body の特長 4
●
SQL 標準に準拠しているので、移植性が ( 多少 ) 向上します
– PostgreSQL から他の DBMS へ、あるいはその逆の移行時
などに便利
●
PostgreSQL の system functions のいくつかは SQL-
standard-body style に書き直されました
まとめ
●
CREATE FUNCTION/PROCEDURE の新しい記述方法がサ
ポートされました
– LANGUAGE SQL のみのサポートです
– 多様型 (any* 型 ) を扱う場合は利用できません
●
SQL 標準に沿った記述方法であり、地味ですが性能・運用
性・移植性の向上が期待できます
●
差し支えなければ、 PostgreSQL 14 以降は今回紹介した記述
方法を使うのがオススメです

Pg14_sql_standard_function_body

  • 1.
    PostgreSQL v14 で追加( 予定 ) の SQL-standard function body 2021.5.11 第 23 回 PostgreSQL アンカンファレンス @ オンライン 笠原辰仁 @kasa_zip
  • 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 に書き直されました
  • 10.
    まとめ ● CREATE FUNCTION/PROCEDURE の新しい記述方法がサ ポートされました –LANGUAGE SQL のみのサポートです – 多様型 (any* 型 ) を扱う場合は利用できません ● SQL 標準に沿った記述方法であり、地味ですが性能・運用 性・移植性の向上が期待できます ● 差し支えなければ、 PostgreSQL 14 以降は今回紹介した記述 方法を使うのがオススメです