環境構築と関数定義
LightDBのorafce拡張機能において、以下のSQLを実行します。
CREATE DOMAIN oracle.clob AS TEXT;
-- バージョン1
CREATE FUNCTION oracle.btrim(text, text)
RETURNS text
AS 'btrim'
LANGUAGE internal STRICT IMMUTABLE;
-- バージョン2
CREATE FUNCTION oracle.btrim(text, char)
RETURNS text
AS 'btrim'
LANGUAGE internal STRICT IMMUTABLE;
-- バージョン3
CREATE FUNCTION oracle.btrim(oracle.clob, varchar)
RETURNS oracle.clob
AS 'MODULE_PATHNAME', 'oracle_btrim'
LANGUAGE C STRICT;
クエリ実行と問題の特定
LightDBのOracleモードで以下のSQLを実行します。
SELECT TRIM('x' FROM 'x'); -- OracleではNULLになるべき
CREATE TABLE foo(a clob);
INSERT INTO foo VALUES ('x');
SELECT TRIM('x' FROM a) FROM foo; -- OracleではNULLにならないべき
-- '::varchar'構文はOracle非対応
SELECT TRIM('x'::varchar FROM a) FROM foo;
このクエリから、btrim(clob, varchar) -> clobが正しく選択されていないことが確認できます。
関数候補選定アルゴリズムの調査
PostgreSQL 13.3における関数解決処理はfunc_get_detail関数内で行われます。LightDBではlt_func_get_detailが使用されます。
主な処理フロー
parse_analyzetransformFuncCallParseFuncOrColumnfunc_get_detail
段階的な候補選定処理
FuncnameGetCandidatesでシステムカタログpg_procから候補関数を取得- 関数引数の変換後、完全一致する関数を検索
- 暗黙的な型変換によって引数を調整
func_select_candidateによる最終的な候補選定
具体的な動作確認
現在の状況では以下の引数型と候補関数が存在します。
-- 実際の引数型
(76716, 705)
-- 候補関数の引数型
(76716, 1043) -- clob, varchar
(25, 1042) -- text, char
(25, 25) -- text, text
各段階での候補選定処理の結果:
-- 最終候補
(25, 25) -- text, text
暗黙的型変換の検証
PostgreSQLのルールに従って、以下の暗黙変換が可能:
unknown→varcharclob→textunknown→charclob→textunknown→text
スコアリング処理
各候補関数に対するスコアリング結果:
-- 基底型と比較
(25, 25) -- スコア1
(25, 1042) -- スコア1
(76716, 1043) -- スコア0
タイプカテゴリによる絞り込み
未知型unknownに対する処理:
- 文字列カテゴリ
'S'として扱われる - 優先型は
text
最終的に選定された関数:
btrim(text, text) -> text