diff --git a/db/PKG_P8PANELS_QE_BASE.pck b/db/PKG_P8PANELS_QE_BASE.pck index 85715ef..70fb7b8 100644 --- a/db/PKG_P8PANELS_QE_BASE.pck +++ b/db/PKG_P8PANELS_QE_BASE.pck @@ -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; /