ЦИТК-979 - Редактор запросов - Исполнение запроса (серверная процедура)

This commit is contained in:
Mim 2026-04-15 12:31:21 +03:00
parent 1c110a25d7
commit e1c77731be

View File

@ -343,7 +343,15 @@ create or replace package PKG_P8PANELS_QE_BASE as
SQRY out varchar2, -- SQL-выражение
SQRY_BND out varchar2, -- SQL-выражение с подставленными значениями аргументов
SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
);
);
/* Исполнение запроса */
procedure QUERY_EXECUTE
(
NRN in number, -- Рег. номер запроса
CARGS in clob, -- Значения аргументов
CDATA out clob -- Данные
);
end PKG_P8PANELS_QE_BASE;
/
@ -492,7 +500,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
if (NDATA_TYPE is null) then
P_EXCEPTION(0, 'Не указан тип данных аргумента.');
end if;
if (NDATA_TYPE not in (PKG_STD.DATA_TYPE_STR, PKG_STD.DATA_TYPE_NUM, PKG_STD.DATA_TYPE_DATE)) then
if (NDATA_TYPE not in (PKG_STD.DATA_TYPE_STR(), PKG_STD.DATA_TYPE_NUM(), PKG_STD.DATA_TYPE_DATE())) then
P_EXCEPTION(0,
'Аргументы типа "%s" не поддерживаются.',
COALESCE(TO_CHAR(NDATA_TYPE), '<НЕ УКАЗАН>'));
@ -2792,7 +2800,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
'" отсутствует в составе его аргументов.',
BCLEAR_QRY => false);
end if;
/* Ищем следующу */
/* Ищем следующую */
SCOND_VAR := PKG_CONTVARLOC.NEXT_(RCONTAINER => RCOND_VARS, SNAME => SCOND_VAR);
end loop;
end if;
@ -2873,7 +2881,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
if (RENTS(I).RATTRS(J).NSHOW = 1) then
if (RENTS(I).RATTRS(J).SALIAS is null) then
P_EXCEPTION(0,
'Для атрибута ("%s") не задан севдоним.',
'Для атрибута ("%s") не задан псевдоним.',
RENTS(I).RATTRS(J).SID);
end if;
SFIELD := RENTS(I).RATTRS(J).SID || ' "' || RENTS(I).RATTRS(J).SALIAS || '", ';
@ -2991,15 +2999,15 @@ create or replace package body PKG_P8PANELS_QE_BASE as
loop
begin
case
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_STR then
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_STR() then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_STR(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
SVALUE => ROPT.RARGS(I).SVALUE);
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_NUM then
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_NUM() then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_NUM(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
NVALUE => TO_NUMBER(ROPT.RARGS(I).SVALUE));
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_DATE then
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_DATE() then
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_DATE(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
DVALUE => TO_DATE(ROPT.RARGS(I).SVALUE, 'yyyy-mm-dd'));
@ -3053,6 +3061,191 @@ create or replace package body PKG_P8PANELS_QE_BASE as
PKG_STATE.DIAGNOSTICS_STACKED();
ADD_QRY_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false);
end QUERY_QRY_BUILD;
/* Исполнение запроса */
procedure QUERY_EXECUTE
(
NRN in number, -- Рег. номер запроса
CARGS in clob, -- Значения аргументов
CDATA out clob -- Данные
)
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
ICURSOR integer; -- Курсор для исполнения запроса
ROPT TOPT; --
RARGS TARGS; -- Полученные аргументы
NARG PKG_STD.TNUMBER; --
SARG_VALUE PKG_STD.TLSTRING; --
RCUR_COLS PKG_CONTUNVLOC.TCONTAINER; -- Описание колонок запроса
SCOL_VALUE PKG_STD.TLSTRING; --
NCOL_VALUE PKG_STD.TLNUMBER; --
DCOL_VALUE PKG_STD.TLDATE; --
TSCOL_VALUE timestamp; --
TZCOL_VALUE timestamp with time zone; --
NROW PKG_STD.TNUMBER := 0; --
begin
/* Читаем описание запроса */
RQ := QUERY_GET(NRN => NRN);
/* Проверим, что существует SQL-выражение */
if (RQ.QRY is null) then
P_EXCEPTION(0, 'Для запроса не сформировано SQL-выражение.');
end if;
/* Читаем настройки запроса */
ROPT := QUERY_OPT_FROM_XML(CXML => RQ.OPT);
/* Читаем полученные аргументы */
RARGS := TARGS_FROM_XML(CXML => CARGS);
if (RARGS.COUNT > 0) then
for I in RARGS.FIRST .. RARGS.LAST
loop
DBMS_OUTPUT.PUT_LINE(RARGS(I).SNAME || ' = ' || RARGS(I).SVALUE);
end loop;
else
DBMS_OUTPUT.PUT_LINE('Нет аргументов');
end if;
/* Если для запроса заявлены аргументы, то проверим, что переданы значения для обязательных */
if (ROPT.RARGS.COUNT > 0) then
for I in ROPT.RARGS.FIRST .. ROPT.RARGS.LAST
loop
if (ROPT.RARGS(I).NMANDATORY = 1) then
NARG := TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => ROPT.RARGS(I).SNAME);
if ((NARG is null) or (RARGS(NARG).SVALUE is null)) then
P_EXCEPTION(0,
'Не указано значение обязательного аргумента запроса "%s".',
ROPT.RARGS(I).SNAME);
end if;
end if;
end loop;
end if;
/* Разбираем его */
ICURSOR := PKG_SQL_DML.OPEN_CURSOR(SWHAT => 'SELECT');
PKG_SQL_DML.PARSE(ICURSOR => ICURSOR, SQUERY => RQ.QRY);
/* Получим описание колонок */
PKG_SQL_DML.DESCRIBE_COLUMNS(ICURSOR => ICURSOR, RDESC_CONTAINER => RCUR_COLS);
if (PKG_CONTUNVLOC.COUNT_(RCONTAINER => RCUR_COLS) > 0) then
/* Обходим их */
for I in PKG_CONTUNVLOC.FIRST_(RCONTAINER => RCUR_COLS) .. PKG_CONTUNVLOC.LAST_(RCONTAINER => RCUR_COLS)
loop
/* Определяем типы данных колонок курсора */
case PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')
when PKG_STD.DATA_TYPE_STR() then
PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_NUM() then
PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_DATE() then
PKG_SQL_DML.DEFINE_COLUMN_DATE(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_TS() then
PKG_SQL_DML.DEFINE_COLUMN_TS(ICURSOR => ICURSOR, IPOSITION => I);
when PKG_STD.DATA_TYPE_TZ() then
PKG_SQL_DML.DEFINE_COLUMN_TZ(ICURSOR => ICURSOR, IPOSITION => I);
else
P_EXCEPTION(0,
'Тип данных "%s" не поддерживается.',
TO_CHAR(PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')));
end case;
DBMS_OUTPUT.PUT_LINE(I || ' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'COLUMN_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'NATIVE_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE'));
end loop;
else
P_EXCEPTION(0, 'Для запроса не определен набор полей.');
end if;
/* Делаем подстановку значений аргументов, если они заявлены в запросе */
if (ROPT.RARGS.COUNT > 0) then
/* Обходим формальные аргументы запроса */
for I in ROPT.RARGS.FIRST .. ROPT.RARGS.LAST
loop
begin
/* Ищем значение соответствующего фактического аргумента */
NARG := TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => ROPT.RARGS(I).SNAME);
if (NARG is not null) then
SARG_VALUE := RARGS(NARG).SVALUE;
else
SARG_VALUE := null;
end if;
/* Подставляем в запрос */
case ROPT.RARGS(I).NDATA_TYPE
when PKG_STD.DATA_TYPE_STR() then
PKG_SQL_DML.BIND_VARIABLE_STR(ICURSOR => ICURSOR, SNAME => ROPT.RARGS(I).SNAME, SVALUE => SARG_VALUE);
when PKG_STD.DATA_TYPE_NUM() then
PKG_SQL_DML.BIND_VARIABLE_NUM(ICURSOR => ICURSOR,
SNAME => ROPT.RARGS(I).SNAME,
NVALUE => TO_NUMBER(SARG_VALUE));
when PKG_STD.DATA_TYPE_DATE() then
PKG_SQL_DML.BIND_VARIABLE_DATE(ICURSOR => ICURSOR,
SNAME => ROPT.RARGS(I).SNAME,
DVALUE => TO_DATE(SARG_VALUE, 'yyyy-mm-dd'));
else
P_EXCEPTION(0,
'Тип данных "%s" не поддерживается.',
TO_CHAR(ROPT.RARGS(I).NDATA_TYPE));
end case;
exception
when others then
PKG_STATE.DIAGNOSTICS_STACKED();
P_EXCEPTION(0, 'Ошибка подстановки аргументов: %s.', PKG_STATE.SQL_ERRM());
end;
end loop;
end if;
/* Делаем выборку */
if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then
null;
end if;
/* Обходим выборку */
while (PKG_SQL_DML.FETCH_ROWS(ICURSOR => ICURSOR) > 0)
loop
/* Инкремент счетчика строк */
NROW := NROW + 1;
DBMS_OUTPUT.PUT_LINE('===== СТРОКА # ' || TO_CHAR(NROW) || '=====');
/* Обходим колонки */
for I in PKG_CONTUNVLOC.FIRST_(RCONTAINER => RCUR_COLS) .. PKG_CONTUNVLOC.LAST_(RCONTAINER => RCUR_COLS)
loop
/* Сброс значений предыдущей колонки */
SCOL_VALUE := null;
NCOL_VALUE := null;
DCOL_VALUE := null;
TSCOL_VALUE := null;
TZCOL_VALUE := null;
/* Определяем типы данных колонок курсора */
case PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')
when PKG_STD.DATA_TYPE_STR() then
PKG_SQL_DML.COLUMN_VALUE_STR(ICURSOR => ICURSOR, IPOSITION => I, SVALUE => SCOL_VALUE);
when PKG_STD.DATA_TYPE_NUM() then
PKG_SQL_DML.COLUMN_VALUE_NUM(ICURSOR => ICURSOR, IPOSITION => I, NVALUE => NCOL_VALUE);
when PKG_STD.DATA_TYPE_DATE() then
PKG_SQL_DML.COLUMN_VALUE_DATE(ICURSOR => ICURSOR, IPOSITION => I, DVALUE => DCOL_VALUE);
when PKG_STD.DATA_TYPE_TS() then
PKG_SQL_DML.COLUMN_VALUE_TS(ICURSOR => ICURSOR, IPOSITION => I, TSVALUE => TSCOL_VALUE);
when PKG_STD.DATA_TYPE_TZ() then
PKG_SQL_DML.COLUMN_VALUE_TZ(ICURSOR => ICURSOR, IPOSITION => I, TZVALUE => TZCOL_VALUE);
else
P_EXCEPTION(0,
'Тип данных "%s" не поддерживается.',
TO_CHAR(PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE')));
end case;
DBMS_OUTPUT.PUT_LINE(I || ' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'COLUMN_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETS(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'NATIVE_NAME') ||
' - ' ||
PKG_CONTUNVLOC.GETN(RCONTAINER => RCUR_COLS, IROWID => I, SCOLUMN_NAME => 'DATA_TYPE') ||
' - ' ||
NVL(SCOL_VALUE,
NVL(TO_CHAR(NCOL_VALUE),
NVL(TO_CHAR(DCOL_VALUE), NVL(TO_CHAR(TSCOL_VALUE), TO_CHAR(TZCOL_VALUE))))));
end loop;
end loop;
/* Освобождаем курсор */
PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR);
exception
when others then
if (PKG_SQL_DML.IS_OPEN(ICURSOR => ICURSOR)) then
PKG_SQL_DML.CLOSE_CURSOR(ICURSOR => ICURSOR);
end if;
raise;
end QUERY_EXECUTE;
end PKG_P8PANELS_QE_BASE;
/