Конвертация в PostgreSQL функции с параметрами INOUT/OUT

Oracle позволяет создавать функции, которые возвращают значение и при этом имеют параметры OUT и INOUT. Написание таких функций, хотя и является плохой практикой, довольно часто встречается в базах данных Oracle, особенно в очень старых. В нашей практике мы часто сталкиваемся с такими функциями, и мы обучили наш инструмент преобразованию такого типа функций. В силу некоторых особенностей и ограничений PostgreSQL, конвертация таких функций из Oracle в PostgreSQL — не самая тривиальная задача. Ниже будет описан наш общий подход к преобразованию таких функций из Oracle в PostgreSQL.

Для примера мы используем простую функции в Oracle:

create or replace function fun (a in number,b out number, c in out number) return number is
 begin
   b:=a+10;
   c:=c+a;
   return(50);
 end;

Основная проблема заключается в том, что в PostgreSQL невозможно создать функцию, которая возвращала бы значение и в то же время имела бы параметры OUT (INOUT). Если у функции есть такие параметры, то она не может ничего вернуть. Поэтому мы преобразуем такие функции следующим образом — принуждаем функцию ничего не возвращать и добавляем дополнительный OUT-параметр для возвращаемого значения. По умолчанию этот параметр называется SWP_RETVALUE, но при необходимости вы можете его изменить. После преобразования этой функции с помощью нашего инструмента мы получим следующий результат:

 CREATE OR REPLACE FUNCTION FUN(in A DOUBLE PRECISION ,OUT B DOUBLE PRECISION , INOUT C DOUBLE PRECISION , OUT 
 SWP_RETVALUE DOUBLE PRECISION)
 LANGUAGE plpgsql
    AS $$
 BEGIN
    B := A+10;
    C := C+A;
    SWP_RETVALUE :=(50);
    RETURN;
 END; $$;

На выходе получается функция, которая ничего не возвращает, сохраняет все типы в качестве параметров и получает дополнительный — OUT SWP_RETVALUE DOUBLE PRECISION. Также наш инструмент применяет соответствующие изменения для всех вызовов этой функции в других объектах. Например, в каком-то другом объекте будет следующий вызов этой функции:

 RES:=FUN(X,Y,Z);

В результате перехода с Oracle на PostgreSQL этот вызов будет заменен следующим вызовом функции:

 SELECT * FROM FUN(X,Z) INTO STRICT Y,Z,RES;

Как видите, в функцию будут переданы только параметры IN и INOUT, а результат будет записан в параметры OUT и INOUT, причем в правильном порядке. Результат функции RES также будет возвращен и сохранен. Как видно в примере, все вызовы функций безошибочно сконвертированы. Кроме того, при таком подходе сохраняется тип объекта (функция преобразуется в функцию), что также удобно для пользователя нашего инструмента.

Мы используем этот подход для всех типов функций с параметрами INOUT (OUT). Исключение составляют функции, один из параметров которых или возвращаемое значение является составным (рекордным) типом. В этом случае наш инструмент преобразует такие функции в процедуры, с дополнительным параметром INOUT (OUT). Это связано с тем, что в PostgreSQL невозможно вернуть несколько параметров из функции, если один из них составной. Поэтому для таких параметров мы преобразуем функции в процедуры. Разумеется, это решение будет работать только для PostgreSQL 11 и выше. Соответственно изменятся и вызовы этих функций в других объектах.


Если у вас есть другие вопросы, пожалуйста, свяжитесь с нами: support@convertum.ru