Как перепроверить функцию SQL, созданную с check_function_bodies = false? - PullRequest
0 голосов
/ 29 января 2019

После этого ответа Я узнал, что могу отключить проверку синтаксиса для функции SQL, установив check_function_bodies=false.

В моем случае: запуск обновления с помощью Flyway, где

  1. Порядок создания функций не совсем определен
  2. Некоторые функции используют другие функции, которые еще не созданы в рамках того же обновления.

Мой вопрос - возможно ли это?выполнить «перепроверку» такой функции без необходимости ее фактического вызова - после того, как все другие зависимости на месте?Нечто похожее на Oracle alter function ... compile.

В идеале я хотел бы установить check_function_bodies=false в начале обновления, а затем перепроверить каждую функцию SQL в конце.

Я хочуизбегайте:

  1. управления порядком запуска сценариев.
  2. повторного запуска сценариев создания функций

То, что я пробовал:

  • Манекен alter function
  • Звонок pg_get_functiondef

Ответы [ 2 ]

0 голосов
/ 30 января 2019

После блестящего ответа Лоренца я написал эту маленькую вспомогательную функцию - делиться на пользу другим.

CREATE OR REPLACE FUNCTION recompile_functions()
RETURNS void
LANGUAGE plpgsql
VOLATILE
AS $$
DECLARE
    l_func regproc;
BEGIN
    --schema name can also be an input param or current_schema.
    --test sql functions
    FOR l_func IN (
        SELECT oid
        FROM pg_proc
        WHERE pronamespace='my_schema'::regnamespace
        AND prolang=(SELECT oid FROM pg_language WHERE lanname='sql')
    ) 
    LOOP
        PERFORM fmgr_sql_validator(l_func);
    END LOOP;

    --test plpgsql functions
    FOR l_func IN (
        SELECT oid
        FROM pg_proc
        WHERE pronamespace='my_schema'::regnamespace
        AND prolang=(SELECT oid FROM pg_language WHERE lanname='plpgsql')
    ) 
    LOOP
        PERFORM plpgsql_validator(l_func);
    END LOOP;

EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'Function % failed validation checks: %', l_func::text, SQLERRM;
END; $$;
0 голосов
/ 29 января 2019

Я могу придумать два пути:

  1. Вы можете напрямую вызвать функцию проверки языка:

    SELECT lanname, lanvalidator::regprocedure FROM pg_language;
    
      lanname   |         lanvalidator         
    ------------+------------------------------
     internal   | fmgr_internal_validator(oid)
     c          | fmgr_c_validator(oid)
     sql        | fmgr_sql_validator(oid)
     plpgsql    | plpgsql_validator(oid)
     plpython3u | plpython3_validator(oid)
    (5 rows)
    

    Для функций SQL, которые будут работать следующим образом:

    SET check_function_bodies = off;
    CREATE FUNCTION bad() RETURNS void LANGUAGE sql AS 'SELECT $1';
    
    SET check_function_bodies = on;
    SELECT fmgr_sql_validator('bad()'::regprocedure);
    
    ERROR:  there is no parameter $1
    LINE 1: SELECT $1
                   ^
    QUERY:  SELECT $1
    
  2. Вы можете переопределить функцию и проверить, выдает ли она ошибку:

    SET check_function_bodies = on;
    DO $$BEGIN
       EXECUTE pg_get_functiondef('bad()'::regprocedure);
    END;$$;
    
...