1 つのデータベースに、同じ関数名を持つ 2 つの類似したスキーマがあります。各スキーマは、スキーマ名に一致するロールによって所有されます。
ネストされた関数での関数名の解決に問題があります。外側の関数が同じスキーマ内の内側の関数を呼び出すことを期待していましたが、そうではありません! 名前は、実行時に search_path に基づいて動的に解決されます。
これがテストケースです。たとえば、次のようにスキーマとロールに test と prod という名前が付けられているとします。
テスト スキーマ:CREATE ROLE test NOLOGIN;
CREATE SCHEMA test AUTHORIZATION test;
CREATE OR REPLACE FUNCTION test.inner_func() RETURNS TEXT
AS $BODY$
BEGIN
RETURN 'test function';
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION test.inner_func() OWNER TO test;
CREATE OR REPLACE FUNCTION test.outer_func() RETURNS SETOF TEXT
AS $BODY$
BEGIN
RETURN QUERY SELECT inner_func();
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION test.outer_func() OWNER TO test;
製品スキーマ:
CREATE ROLE prod NOLOGIN;
CREATE SCHEMA prod AUTHORIZATION prod;
CREATE OR REPLACE FUNCTION prod.inner_func() RETURNS TEXT
AS $BODY$
BEGIN
RETURN 'prod function';
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION prod.inner_func() OWNER TO prod;
CREATE OR REPLACE FUNCTION prod.outer_func() RETURNS SETOF TEXT
AS $BODY$
BEGIN
RETURN QUERY SELECT inner_func();
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION prod.outer_func() OWNER TO prod;
テストケース:
SET search_path=test,public;
SELECT outer_func();
> test function
SELECT prod.outer_func();
> test function <<<---- was expecting prod function
SET search_path=prod,public;
SELECT prod.outer_func();
> prod function
search_path
このテストは、関数名が実行時に基づいて動的に解決されることを示しています。スキーマのスコープ内で内部関数をバインドする方法はありますか?
SECURITY DEFINER
動的 SQL および で関数を使用することでこのような動作を得ることができますが、CURRENT_USER
もっと簡単なものを探しています。