1032 lines
58 KiB
SQL
1032 lines
58 KiB
SQL
create or replace package PKG_P8PANELS_BASE as
|
||
|
||
/*Константы - Типовой постфикс тега для массива (при переводе XML -> JSON) */
|
||
SXML_ALWAYS_ARRAY_POSTFIX constant PKG_STD.TSTRING := '__SYSTEM__ARRAY__';
|
||
|
||
/* Константы - признаки наличия доступа */
|
||
NACCESS_YES constant number(1) := 1; -- Доступ есть
|
||
NACCESS_NO constant number(1) := 0; -- Доступа нет
|
||
|
||
/* Конвертация строки в число */
|
||
function UTL_S2N
|
||
(
|
||
SVALUE in varchar2 -- Конвертируемое строковое значение
|
||
) return number; -- Конвертированное число
|
||
|
||
/* Конвертация даты в число */
|
||
function UTL_S2D
|
||
(
|
||
SVALUE in varchar2 -- Конвертируемое строковое значение
|
||
) return date; -- Конвертированная дата
|
||
|
||
/* Проверка доступности документа */
|
||
function UTL_DOC_ACCESS_CHECK
|
||
(
|
||
NCOMPANY in number, -- Рег. номер организации
|
||
SUNIT_CODE in varchar2, -- Код раздела
|
||
NDOCUMENT in number -- Рег. номер документа
|
||
) return number; -- Флаг доступности (см. константы NACCESS_*)
|
||
|
||
/* Подготовка пользовательской строки поиска для вставки в запрос */
|
||
procedure UTL_SEARCH_PREPARE
|
||
(
|
||
SSEARCH in varchar2, -- Пользовательская строка поиска
|
||
SSEARCH_PREPARED out varchar2 -- Подготовленная строка поиска
|
||
);
|
||
|
||
/* Базовое исполнение действий */
|
||
procedure PROCESS
|
||
(
|
||
CIN in clob, -- Входные параметры
|
||
COUT out clob -- Результат
|
||
);
|
||
|
||
/* Базовая инициализация буфера отмеченных записей для панели */
|
||
procedure SELECTLIST_INIT
|
||
(
|
||
NIDENT in number -- Идентификатор буфера отмеченных записей
|
||
);
|
||
|
||
/* Базовая очистка буфера отмеченных записей для панели */
|
||
procedure SELECTLIST_CLEAR
|
||
(
|
||
NIDENT in number -- Идентификатор буфера отмеченных записей
|
||
);
|
||
|
||
end PKG_P8PANELS_BASE;
|
||
/
|
||
create or replace package body PKG_P8PANELS_BASE as
|
||
|
||
/* Константы - коды дествий запросов */
|
||
SRQ_ACTION_EXEC_STORED constant PKG_STD.TSTRING := 'EXEC_STORED'; -- Запрос на исполнение хранимой процедуры
|
||
|
||
/* Константы - тэги запросов */
|
||
SRQ_TAG_XREQUEST constant PKG_STD.TSTRING := 'XREQUEST'; -- Корневой тэг запроса
|
||
SRQ_TAG_XPAYLOAD constant PKG_STD.TSTRING := 'XPAYLOAD'; -- Тэг для данных запроса
|
||
SRQ_TAG_SACTION constant PKG_STD.TSTRING := 'SACTION'; -- Тэг для действия запроса
|
||
SRQ_TAG_SSTORED constant PKG_STD.TSTRING := 'SSTORED'; -- Тэг для имени хранимого объекта в запросе
|
||
SRQ_TAG_SRESP_ARG constant PKG_STD.TSTRING := 'SRESP_ARG'; -- Тэг для имени аргумента, формирующего данные ответа
|
||
SRQ_TAG_XARGUMENTS constant PKG_STD.TSTRING := 'XARGUMENTS'; -- Тэг для списка аргументов хранимого объекта/выборки в запросе
|
||
SRQ_TAG_XARGUMENT constant PKG_STD.TSTRING := 'XARGUMENT'; -- Тэг для аргумента хранимого объекта/выборки в запросе
|
||
SRQ_TAG_SNAME constant PKG_STD.TSTRING := 'SNAME'; -- Тэг для наименования в запросе
|
||
SRQ_TAG_SDATA_TYPE constant PKG_STD.TSTRING := 'SDATA_TYPE'; -- Тэг для типа данных в запросе
|
||
SRQ_TAG_VALUE constant PKG_STD.TSTRING := 'VALUE'; -- Тэг для значения в запросе
|
||
|
||
/* Константы - тэги ответов */
|
||
SRESP_TAG_XPAYLOAD constant PKG_STD.TSTRING := 'XPAYLOAD'; -- Тэг для данных ответа
|
||
SRESP_TAG_XOUT_ARGUMENTS constant PKG_STD.TSTRING := 'XOUT_ARGUMENTS'; -- Тэг для выходных аргументов хранимого объекта в ответе
|
||
SRESP_TAG_SDATA_TYPE constant PKG_STD.TSTRING := 'SDATA_TYPE'; -- Тэг для типа данных в ответе
|
||
SRESP_TAG_VALUE constant PKG_STD.TSTRING := 'VALUE'; -- Тэг для значения в ответе
|
||
SRESP_TAG_SNAME constant PKG_STD.TSTRING := 'SNAME'; -- Тэг для наименования в ответе
|
||
|
||
/* Константы - типы данных */
|
||
SDATA_TYPE_STR constant PKG_STD.TSTRING := 'STR'; -- Тип данных "строка"
|
||
SDATA_TYPE_NUMB constant PKG_STD.TSTRING := 'NUMB'; -- Тип данных "число"
|
||
SDATA_TYPE_DATE constant PKG_STD.TSTRING := 'DATE'; -- Тип данных "дата"
|
||
SDATA_TYPE_CLOB constant PKG_STD.TSTRING := 'CLOB'; -- Тип данных "текст"
|
||
|
||
/* Константы - состояния объектов БД */
|
||
SDB_OBJECT_STATE_VALID constant PKG_STD.TSTRING := 'VALID'; -- Объект валиден
|
||
|
||
/* Типы данных - аргументы */
|
||
type TARGUMENT is record
|
||
(
|
||
SNAME PKG_STD.TSTRING, -- Наименование
|
||
SDATA_TYPE PKG_STD.TSTRING, -- Тип данных (см. константы SPWS_DATA_TYPE_*)
|
||
SVALUE PKG_STD.TSTRING, -- Значение (строка)
|
||
NVALUE PKG_STD.TLNUMBER, -- Значение (число)
|
||
DVALUE PKG_STD.TLDATE, -- Значение (дата)
|
||
CVALUE clob -- Значение (текст)
|
||
);
|
||
|
||
/* Типы данных - коллекция аргументов запроса */
|
||
type TARGUMENTS is table of TARGUMENT;
|
||
|
||
/* Конвертация строки в число */
|
||
function UTL_S2N
|
||
(
|
||
SVALUE in varchar2 -- Конвертируемое строковое значение
|
||
) return number -- Конвертированное число
|
||
is
|
||
NVALUE PKG_STD.TNUMBER; -- Результат работы
|
||
begin
|
||
/* Пробуем конвертировать */
|
||
NVALUE := TO_NUMBER(replace(SVALUE, ',', '.'));
|
||
/* Отдаём результат */
|
||
return NVALUE;
|
||
exception
|
||
when others then
|
||
P_EXCEPTION(0, 'Неверный формат числа (%s).', SVALUE);
|
||
end UTL_S2N;
|
||
|
||
/* Конвертация даты в число */
|
||
function UTL_S2D
|
||
(
|
||
SVALUE in varchar2 -- Конвертируемое строковое значение
|
||
) return date -- Конвертированная дата
|
||
is
|
||
DVALUE PKG_STD.TLDATE; -- Результат работы
|
||
begin
|
||
/* Пробуем конвертировать */
|
||
begin
|
||
DVALUE := TO_DATE(SVALUE, 'YYYY-MM-DD');
|
||
exception
|
||
when others then
|
||
begin
|
||
DVALUE := TO_DATE(SVALUE, 'YYYY/MM/DD');
|
||
exception
|
||
when others then
|
||
begin
|
||
DVALUE := TO_DATE(SVALUE, 'DD.MM.YYYY');
|
||
exception
|
||
when others then
|
||
DVALUE := TO_DATE(SVALUE, 'DD/MM/YYYY');
|
||
end;
|
||
end;
|
||
end;
|
||
/* Отдаём результат */
|
||
return DVALUE;
|
||
exception
|
||
when others then
|
||
P_EXCEPTION(0, 'Неверный формат даты (%s).', SVALUE);
|
||
end UTL_S2D;
|
||
|
||
/* Проверка доступности документа */
|
||
function UTL_DOC_ACCESS_CHECK
|
||
(
|
||
NCOMPANY in number, -- Рег. номер организации
|
||
SUNIT_CODE in varchar2, -- Код раздела
|
||
NDOCUMENT in number -- Рег. номер документа
|
||
) return number -- Флаг доступности (см. константы NACCESS_*)
|
||
is
|
||
NRES PKG_STD.TNUMBER; -- Буфер для результата
|
||
NVERSION PKG_STD.TREF; -- Рег. номер версии
|
||
NCATALOG PKG_STD.TREF; -- Рег. номер каталога
|
||
NJUR_PERS PKG_STD.TREF; -- Рег. номер юридической принадлежности
|
||
NHIERARCHY PKG_STD.TREF; -- Рег. номер ирерархии
|
||
BTMP boolean; -- Буфер для расчетов
|
||
NTMP PKG_STD.TNUMBER; -- Буфер для расчетов
|
||
begin
|
||
/* Считаем стандартную атрибутику */
|
||
PKG_DOCUMENT.GET_ATTRS(NFLAG_SMART => 0,
|
||
SUNITCODE => SUNIT_CODE,
|
||
NDOCUMENT => NDOCUMENT,
|
||
BFOUND => BTMP,
|
||
NCOMPANY => NTMP,
|
||
NVERSION => NVERSION,
|
||
NCATALOG => NCATALOG,
|
||
NJUR_PERS => NJUR_PERS,
|
||
NHIERARCHY => NHIERARCHY);
|
||
/* Проверким доступ */
|
||
PKG_ENV.SMART_ACCESS(NCOMPANY => NCOMPANY,
|
||
NVERSION => NVERSION,
|
||
NCATALOG => NCATALOG,
|
||
NJUR_PERS => NJUR_PERS,
|
||
NHIERARCHY => NHIERARCHY,
|
||
SUNIT => SUNIT_CODE,
|
||
SACTION => null,
|
||
NRESULT => NRES);
|
||
/* Вернём результат */
|
||
if (NRES = 1) then
|
||
return NACCESS_YES;
|
||
else
|
||
return NACCESS_NO;
|
||
end if;
|
||
exception
|
||
/* В случае ошибки - доступ закрыт */
|
||
when others then
|
||
return NACCESS_NO;
|
||
end UTL_DOC_ACCESS_CHECK;
|
||
|
||
/* Подготовка пользовательской строки поиска для вставки в запрос */
|
||
procedure UTL_SEARCH_PREPARE
|
||
(
|
||
SSEARCH in varchar2, -- Пользовательская строка поиска
|
||
SSEARCH_PREPARED out varchar2 -- Подготовленная строка поиска
|
||
)
|
||
is
|
||
/* Локальные константы */
|
||
SANY_SYS constant char(1) := '%'; -- Маска "любое количество любых символов" Oracle
|
||
SONE_SYS constant char(1) := '_'; -- Маска "любой один символ" Oracle
|
||
SENT_WRD_DELIM constant varchar2(1) := ' '; -- Разделитель слов в предложении
|
||
SANY_PRS constant varchar2(240) := PKG_OPTIONS.STARSYMB; -- Маска "любое количество любых символов" Парус
|
||
SONE_PRS constant varchar2(240) := PKG_OPTIONS.QUESTSYMB; -- Маска "любой один символ" Парус
|
||
begin
|
||
/* Если пользовательская строка пустая - то это всё что угодно */
|
||
if (SSEARCH is null)
|
||
then
|
||
SSEARCH_PREPARED := SANY_SYS;
|
||
else
|
||
/* Подменим пользовательские маски на системные и соберем подготовленную строку поиска */
|
||
SSEARCH_PREPARED := '%' || replace(replace(replace(SSEARCH
|
||
,SANY_PRS
|
||
,SANY_SYS)
|
||
,SONE_PRS
|
||
,SONE_SYS)
|
||
,SENT_WRD_DELIM
|
||
,SANY_SYS) || '%';
|
||
end if;
|
||
end UTL_SEARCH_PREPARE;
|
||
|
||
/* Формирование сообщения об отсутствии значения */
|
||
function MSG_NO_DATA_MAKE
|
||
(
|
||
SPATH in varchar2 := null, -- Путь по которому ожидалось значение
|
||
SMESSAGE_OBJECT in varchar2 := null -- Наимемнование объекта для формулирования сообщения об ошибке
|
||
) return varchar2 -- Сформированное сообщение об ошибке
|
||
is
|
||
SPATH_ PKG_STD.TSTRING; -- Буфер для пути
|
||
SMESSAGE_OBJECT_ PKG_STD.TSTRING; -- Буфер для наименования объекта
|
||
begin
|
||
/* Подготовим путь к выдаче */
|
||
if (SPATH is not null) then
|
||
SPATH_ := ' (' || SPATH || ')';
|
||
end if;
|
||
/* Подготовим наименование объекта к выдаче */
|
||
if (SMESSAGE_OBJECT is not null) then
|
||
SMESSAGE_OBJECT_ := ' элемента "' || SMESSAGE_OBJECT || '"';
|
||
else
|
||
SMESSAGE_OBJECT_ := ' элемента';
|
||
end if;
|
||
/* Вернём сформированное сообщение */
|
||
return 'Не указано значение' || SMESSAGE_OBJECT_ || SPATH_ || '.';
|
||
end MSG_NO_DATA_MAKE;
|
||
|
||
/* Конвертация стандартного типа данных (PKG_STD) в тип данных сервиса (PWS) */
|
||
function STD_DATA_TYPE_TO_STR
|
||
(
|
||
NSTD_DATA_TYPE in number -- Станартный тип данных
|
||
) return varchar2 -- Соответствующий тип данных сервиса
|
||
is
|
||
SRES PKG_STD.TSTRING; -- Буфер для результата
|
||
begin
|
||
/* Работаем от типа данных */
|
||
case NSTD_DATA_TYPE
|
||
/* Строка */
|
||
when PKG_STD.DATA_TYPE_STR then
|
||
SRES := SDATA_TYPE_STR;
|
||
/* Число */
|
||
when PKG_STD.DATA_TYPE_NUM then
|
||
SRES := SDATA_TYPE_NUMB;
|
||
/* Дата */
|
||
when PKG_STD.DATA_TYPE_DATE then
|
||
SRES := SDATA_TYPE_DATE;
|
||
/* Текст */
|
||
when PKG_STD.DATA_TYPE_CLOB then
|
||
SRES := SDATA_TYPE_CLOB;
|
||
/* Неизвестный тип данных */
|
||
else
|
||
P_EXCEPTION(0,
|
||
'Тип данных "%s" не поддерживается.',
|
||
COALESCE(TO_CHAR(NSTD_DATA_TYPE), '<НЕ ОПРЕДЕЛЁН>'));
|
||
end case;
|
||
/* Возвращаем результат */
|
||
return SRES;
|
||
end STD_DATA_TYPE_TO_STR;
|
||
|
||
/* Считывание значения ветки XML (строка) */
|
||
function NODE_SVAL_GET
|
||
(
|
||
XROOT in PKG_XPATH.TNODE, -- Корневая ветка для считывания значения
|
||
SPATH in varchar2, -- Путь для считывания данных
|
||
NREQUIRED in number := 0, -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
SMESSAGE_OBJECT in varchar2 := null -- Наимемнование объекта для формулирования сообщения об ошибке
|
||
) return varchar2 -- Считанное значение
|
||
is
|
||
XNODE PKG_XPATH.TNODE; -- Искомая ветка со значением (подходящая под шаблон)
|
||
SVAL PKG_STD.TSTRING; -- Результат работы
|
||
begin
|
||
/* Найдем нужную ветку по шаблону */
|
||
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => SPATH);
|
||
/* Если там нет ничего */
|
||
if (PKG_XPATH.IS_NULL(RNODE => XNODE)) then
|
||
/* Его и вернём */
|
||
SVAL := null;
|
||
else
|
||
/* Что-то есть - читаем данные */
|
||
begin
|
||
SVAL := PKG_XPATH.VALUE(RNODE => XNODE);
|
||
exception
|
||
when others then
|
||
P_EXCEPTION(0, 'Неверный формат строки (%s).', SPATH);
|
||
end;
|
||
end if;
|
||
/* Если значения нет, а оно должно быть - скажем об этом */
|
||
if ((SVAL is null) and (NREQUIRED = 1)) then
|
||
P_EXCEPTION(0, MSG_NO_DATA_MAKE(SPATH => SPATH, SMESSAGE_OBJECT => SMESSAGE_OBJECT));
|
||
end if;
|
||
/* Отдаём результат */
|
||
return SVAL;
|
||
end NODE_SVAL_GET;
|
||
|
||
/* Считывание значения ветки XML (число) */
|
||
function NODE_NVAL_GET
|
||
(
|
||
XROOT in PKG_XPATH.TNODE, -- Корневая ветка для считывания значения
|
||
SPATH in varchar2, -- Путь для считывания данных
|
||
NREQUIRED in number := 0, -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
SMESSAGE_OBJECT in varchar2 := null -- Наимемнование объекта для формулирования сообщения об ошибке
|
||
) return number -- Считанное значение
|
||
is
|
||
XNODE PKG_XPATH.TNODE; -- Искомая ветка со значением (подходящая под шаблон)
|
||
NVAL PKG_STD.TLNUMBER; -- Результат работы
|
||
begin
|
||
/* Найдем нужную ветку по шаблону */
|
||
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => SPATH);
|
||
/* Если там нет ничего */
|
||
if (PKG_XPATH.IS_NULL(RNODE => XNODE)) then
|
||
/* Его и вернём */
|
||
NVAL := null;
|
||
else
|
||
/* Что-то есть - читаем данные */
|
||
begin
|
||
NVAL := PKG_XPATH.VALUE_NUM(RNODE => XNODE);
|
||
exception
|
||
when others then
|
||
P_EXCEPTION(0, 'Неверный формат числа (%s).', SPATH);
|
||
end;
|
||
end if;
|
||
/* Если значения нет, а оно должно быть - скажем об этом */
|
||
if ((NVAL is null) and (NREQUIRED = 1)) then
|
||
P_EXCEPTION(0, MSG_NO_DATA_MAKE(SPATH => SPATH, SMESSAGE_OBJECT => SMESSAGE_OBJECT));
|
||
end if;
|
||
/* Отдаём результат */
|
||
return NVAL;
|
||
end NODE_NVAL_GET;
|
||
|
||
/* Считывание значения ветки XML (дата) */
|
||
function NODE_DVAL_GET
|
||
(
|
||
XROOT in PKG_XPATH.TNODE, -- Корневая ветка для считывания значения
|
||
SPATH in varchar2, -- Путь для считывания данных
|
||
NREQUIRED in number := 0, -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
SMESSAGE_OBJECT in varchar2 := null -- Наимемнование объекта для формулирования сообщения об ошибке
|
||
) return date -- Считанное значение
|
||
is
|
||
XNODE PKG_XPATH.TNODE; -- Искомая ветка со значением (подходящая под шаблон)
|
||
DVAL PKG_STD.TLDATE; -- Результат работы
|
||
begin
|
||
/* Найдем нужную ветку по шаблону */
|
||
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => SPATH);
|
||
/* Если там нет ничего */
|
||
if (PKG_XPATH.IS_NULL(RNODE => XNODE)) then
|
||
/* Его и вернём */
|
||
DVAL := null;
|
||
else
|
||
/* Что-то есть - читаем данные */
|
||
begin
|
||
DVAL := PKG_XPATH.VALUE_DATE(RNODE => XNODE);
|
||
exception
|
||
when others then
|
||
begin
|
||
DVAL := PKG_XPATH.VALUE_TS(RNODE => XNODE);
|
||
exception
|
||
when others then
|
||
begin
|
||
DVAL := PKG_XPATH.VALUE_TZ(RNODE => XNODE);
|
||
exception
|
||
when others then
|
||
P_EXCEPTION(0,
|
||
'Неверный формат даты (%s). Ожидалось: YYYY-MM-DD"T"HH24:MI:SS.FF3tzh:tzm, YYYY-MM-DD"T"HH24:MI:SS.FF3, YYYY-MM-DD"T"HH24:MI:SS, YYYY-MM-DD.',
|
||
SPATH);
|
||
end;
|
||
end;
|
||
end;
|
||
end if;
|
||
/* Если значения нет, а оно должно быть - скажем об этом */
|
||
if ((DVAL is null) and (NREQUIRED = 1)) then
|
||
P_EXCEPTION(0, MSG_NO_DATA_MAKE(SPATH => SPATH, SMESSAGE_OBJECT => SMESSAGE_OBJECT));
|
||
end if;
|
||
/* Отдаём результат */
|
||
return DVAL;
|
||
end NODE_DVAL_GET;
|
||
|
||
/* Считывание значения ветки XML (текст) */
|
||
function NODE_CVAL_GET
|
||
(
|
||
XROOT in PKG_XPATH.TNODE, -- Корневая ветка для считывания значения
|
||
SPATH in varchar2, -- Путь для считывания данных
|
||
NREQUIRED in number := 0, -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
SMESSAGE_OBJECT in varchar2 := null -- Наимемнование объекта для формулирования сообщения об ошибке
|
||
) return clob -- Считанное значение
|
||
is
|
||
XNODE PKG_XPATH.TNODE; -- Искомая ветка со значением (подходящая под шаблон)
|
||
CVAL clob; -- Результат работы
|
||
begin
|
||
/* Найдем нужную ветку по шаблону */
|
||
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => SPATH);
|
||
/* Если там нет ничего */
|
||
if (PKG_XPATH.IS_NULL(RNODE => XNODE)) then
|
||
/* Его и вернём */
|
||
CVAL := null;
|
||
else
|
||
/* Что-то есть - читаем данные */
|
||
begin
|
||
CVAL := PKG_XPATH.VALUE_CLOB(RNODE => XNODE);
|
||
exception
|
||
when others then
|
||
P_EXCEPTION(0, 'Неверный формат текстовых данных (%s).', SPATH);
|
||
end;
|
||
end if;
|
||
/* Если значения нет, а оно должно быть - скажем об этом */
|
||
if ((CVAL is null) and (NREQUIRED = 1)) then
|
||
P_EXCEPTION(0, MSG_NO_DATA_MAKE(SPATH => SPATH, SMESSAGE_OBJECT => SMESSAGE_OBJECT));
|
||
end if;
|
||
/* Отдаём результат */
|
||
return CVAL;
|
||
end NODE_CVAL_GET;
|
||
|
||
/* Считывание аргумента из коллекции */
|
||
function TARGUMENTS_GET
|
||
(
|
||
ARGUMENTS in TARGUMENTS, -- Коллекция аргументов
|
||
SARGUMENT in varchar2, -- Код аргумента
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return TARGUMENT -- Найденный аргумент
|
||
is
|
||
begin
|
||
/* Если данные в коллекции есть */
|
||
if ((ARGUMENTS is not null) and (ARGUMENTS.COUNT > 0)) then
|
||
/* Обходим её */
|
||
for I in ARGUMENTS.FIRST .. ARGUMENTS.LAST
|
||
loop
|
||
/* Если встретился нужный аргумент */
|
||
if (ARGUMENTS(I).SNAME = SARGUMENT) then
|
||
/* Вернём его */
|
||
return ARGUMENTS(I);
|
||
end if;
|
||
end loop;
|
||
end if;
|
||
/* Если мы здесь - аргумент не нашелся, будем выдавать сообщение об ошибке если он был обязательным */
|
||
if (NREQUIRED = 1) then
|
||
P_EXCEPTION(0, 'Не задан обязательный аргумент "%s".', SARGUMENT);
|
||
else
|
||
/* Он не обязательный - вернём отсутствие данных */
|
||
return null;
|
||
end if;
|
||
end TARGUMENTS_GET;
|
||
|
||
/* Считывание значения аргумента из коллекции (строка) */
|
||
function TARGUMENTS_SVAL_GET
|
||
(
|
||
ARGUMENTS in TARGUMENTS, -- Коллекция аргументов
|
||
SARGUMENT in varchar2, -- Код аргумента
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return varchar2 -- Значение аргумента
|
||
is
|
||
begin
|
||
/* Считаем и вернём значение */
|
||
return TARGUMENTS_GET(ARGUMENTS => ARGUMENTS, SARGUMENT => SARGUMENT, NREQUIRED => NREQUIRED).SVALUE;
|
||
end TARGUMENTS_SVAL_GET;
|
||
|
||
/* Считывание значения параметра из запроса (число) */
|
||
function TARGUMENTS_NVAL_GET
|
||
(
|
||
ARGUMENTS in TARGUMENTS, -- Коллекция аргументов
|
||
SARGUMENT in varchar2, -- Код аргумента
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return number -- Значение аргумента
|
||
is
|
||
begin
|
||
/* Считаем и вернём значение */
|
||
return TARGUMENTS_GET(ARGUMENTS => ARGUMENTS, SARGUMENT => SARGUMENT, NREQUIRED => NREQUIRED).NVALUE;
|
||
end TARGUMENTS_NVAL_GET;
|
||
|
||
/* Считывание значения параметра из запроса (дата) */
|
||
function TARGUMENTS_DVAL_GET
|
||
(
|
||
ARGUMENTS in TARGUMENTS, -- Коллекция аргументов
|
||
SARGUMENT in varchar2, -- Код аргумента
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return date -- Значение аргумента
|
||
is
|
||
begin
|
||
/* Считаем и вернём значение */
|
||
return TARGUMENTS_GET(ARGUMENTS => ARGUMENTS, SARGUMENT => SARGUMENT, NREQUIRED => NREQUIRED).DVALUE;
|
||
end TARGUMENTS_DVAL_GET;
|
||
|
||
/* Считывание значения параметра из запроса (текст) */
|
||
function TARGUMENTS_CVAL_GET
|
||
(
|
||
ARGUMENTS in TARGUMENTS, -- Коллекция аргументов
|
||
SARGUMENT in varchar2, -- Код аргумента
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return clob -- Значение аргумента
|
||
is
|
||
begin
|
||
/* Считаем и вернём значение */
|
||
return TARGUMENTS_GET(ARGUMENTS => ARGUMENTS, SARGUMENT => SARGUMENT, NREQUIRED => NREQUIRED).CVALUE;
|
||
end TARGUMENTS_CVAL_GET;
|
||
|
||
/* Получение корневого элемента тела запроса */
|
||
function RQ_ROOT_GET
|
||
(
|
||
CRQ in clob -- Запрос
|
||
) return PKG_XPATH.TNODE -- Корневой элемент первой ветки тела документа
|
||
is
|
||
begin
|
||
/* Возвращаем корневой элемент документа */
|
||
return PKG_XPATH.ROOT_NODE(RDOCUMENT => PKG_XPATH.PARSE_FROM_CLOB(LCXML => CRQ));
|
||
end RQ_ROOT_GET;
|
||
|
||
/* Получение пути к запросу */
|
||
function RQ_PATH_GET
|
||
return varchar2 -- Путь к запросу
|
||
is
|
||
begin
|
||
return '/' || SRQ_TAG_XREQUEST;
|
||
end RQ_PATH_GET;
|
||
|
||
/* Получение пути к элементу действия запроса */
|
||
function RQ_ACTION_PATH_GET
|
||
return varchar2 -- Путь к элементу действия запроса
|
||
is
|
||
begin
|
||
return RQ_PATH_GET() || '/' || SRQ_TAG_SACTION;
|
||
end RQ_ACTION_PATH_GET;
|
||
|
||
/* Получение кода действия запроса */
|
||
function RQ_ACTION_GET
|
||
(
|
||
XRQ_ROOT in PKG_XPATH.TNODE := null, -- Корневая ветка запроса
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return varchar2 -- Код действия запроса
|
||
is
|
||
begin
|
||
/* Вернем значение элемента тела с кодом действия */
|
||
return NODE_SVAL_GET(XROOT => XRQ_ROOT,
|
||
SPATH => RQ_ACTION_PATH_GET(),
|
||
NREQUIRED => NREQUIRED,
|
||
SMESSAGE_OBJECT => 'Код действия');
|
||
end RQ_ACTION_GET;
|
||
|
||
/* Получение пути к параметрам запроса */
|
||
function RQ_PAYLOAD_PATH_GET
|
||
return varchar2 -- Путь к параметрам запроса
|
||
is
|
||
begin
|
||
/* Вернем значение */
|
||
return RQ_PATH_GET() || '/' || SRQ_TAG_XPAYLOAD;
|
||
end RQ_PAYLOAD_PATH_GET;
|
||
|
||
/* Получение пути к элкменту параметров запроса */
|
||
function RQ_PAYLOAD_ITEM_PATH_GET
|
||
(
|
||
SITEM_TAG in varchar2 -- Тэг элемента
|
||
)
|
||
return varchar2 -- Путь к элементу параметров запроса
|
||
is
|
||
begin
|
||
/* Вернем значение */
|
||
return RQ_PAYLOAD_PATH_GET() || '/' || SITEM_TAG;
|
||
end RQ_PAYLOAD_ITEM_PATH_GET;
|
||
|
||
/* Считывание наименования исполняемого хранимого объекта из запроса */
|
||
function RQ_PAYLOAD_STORED_GET
|
||
(
|
||
XRQ_ROOT in PKG_XPATH.TNODE := null, -- Корневая ветка запроса
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return varchar2 -- Наименование исполняемого хранимого объекта из запроса
|
||
is
|
||
begin
|
||
/* Вернем значение элемента тела с наименованием хранимого объекта */
|
||
return NODE_SVAL_GET(XROOT => XRQ_ROOT,
|
||
SPATH => RQ_PAYLOAD_ITEM_PATH_GET(SITEM_TAG => SRQ_TAG_SSTORED),
|
||
NREQUIRED => NREQUIRED,
|
||
SMESSAGE_OBJECT => 'Наименование процедуры/функции');
|
||
end RQ_PAYLOAD_STORED_GET;
|
||
|
||
/* Проверка исполняемого хранимого объекта из запроса */
|
||
procedure RQ_PAYLOAD_STORED_CHECK
|
||
(
|
||
XRQ_ROOT in PKG_XPATH.TNODE, -- Корневая ветка запроса
|
||
SSTORED in varchar2 := null -- Наименование проверяемого хранимого объекта (null - автоматическое считывание из запроса)
|
||
)
|
||
is
|
||
SSTORED_ PKG_STD.TSTRING; -- Буфер для наименования проверяемого хранимого объекта
|
||
RSTORED PKG_OBJECT_DESC.TSTORED; -- Описание хранимого объекта из БД
|
||
SPROCEDURE PKG_STD.TSTRING; -- Буфер для наименования хранимой процедуры
|
||
SPACKAGE PKG_STD.TSTRING; -- Буфер для наименования пакета, содержащего хранимый объект
|
||
RPACKAGE PKG_OBJECT_DESC.TPACKAGE; -- Описание пакета, содержащего хранимый объект
|
||
begin
|
||
/* Считаем наименование объекта из запроса или используем переданное в параметрах */
|
||
if (SSTORED is not null) then
|
||
SSTORED_ := SSTORED;
|
||
else
|
||
SSTORED_ := RQ_PAYLOAD_STORED_GET(XRQ_ROOT => XRQ_ROOT, NREQUIRED => 1);
|
||
end if;
|
||
/* Проверим, что это процедура или функция и она вообще существует */
|
||
if (PKG_OBJECT_DESC.EXISTS_STORED(SSTORED_NAME => SSTORED_) = 0) then
|
||
P_EXCEPTION(0,
|
||
'Хранимая процедура/функция "' || SSTORED_ || '" не определена.');
|
||
else
|
||
/* Проверим, что в имени нет ссылки на пакет */
|
||
PKG_EXS.UTL_STORED_PARSE_LINK(SSTORED => SSTORED_, SPROCEDURE => SPROCEDURE, SPACKAGE => SPACKAGE);
|
||
/* Если в имени есть ссылка на пакет - сначала проверим его состояние */
|
||
if (SPACKAGE is not null) then
|
||
RPACKAGE := PKG_OBJECT_DESC.DESC_PACKAGE(SPACKAGE_NAME => SPACKAGE, BRAISE_ERROR => false);
|
||
end if;
|
||
/* Если есть ссылка на пакет, или он не валиден - это ошибка */
|
||
if ((SPACKAGE is not null) and (RPACKAGE.STATUS <> SDB_OBJECT_STATE_VALID)) then
|
||
P_EXCEPTION(0,
|
||
'Пакет "' || SPACKAGE ||
|
||
'", содержащий хранимую процедуру/функцию, невалиден. Обращение к объекту невозможно.');
|
||
else
|
||
/* Нет ссылки на пакет или он валиден - проверяем глубже, получим описание объекта из БД */
|
||
RSTORED := PKG_OBJECT_DESC.DESC_STORED(SSTORED_NAME => SSTORED_, BRAISE_ERROR => false);
|
||
/* Проверим, что валидна */
|
||
if (RSTORED.STATUS <> SDB_OBJECT_STATE_VALID) then
|
||
P_EXCEPTION(0,
|
||
'Хранимая процедура/функция "' || SSTORED_ || '" невалидна. Обращение к объекту невозможно.');
|
||
else
|
||
/* Проверим, что это клиентский объект */
|
||
if (PKG_OBJECT_DESC.EXISTS_PRIV_EXECUTE(SSTORED_NAME => COALESCE(RSTORED.PACKAGE_NAME, SSTORED_)) = 0) then
|
||
P_EXCEPTION(0,
|
||
'Хранимая процедура/функция "' || SSTORED_ ||
|
||
'" не является клиентской. Обращение к объекту невозможно.');
|
||
end if;
|
||
end if;
|
||
end if;
|
||
end if;
|
||
end RQ_PAYLOAD_STORED_CHECK;
|
||
|
||
/* Считывание списка аргументов из запроса */
|
||
function RQ_PAYLOAD_ARGUMENTS_GET
|
||
(
|
||
XRQ_ROOT in PKG_XPATH.TNODE, -- Корневая ветка запроса
|
||
NREQUIRED in number := 0 -- Флаг выдачи сообщения об ошибке в случае отсутствия значения (0 - не выдавать, 1 - выдавать)
|
||
) return TARGUMENTS -- Коллекция аргументов из запроса
|
||
is
|
||
RES TARGUMENTS; -- Результат работы
|
||
SRQ_ARGUMENTS_PATH PKG_STD.TSTRING; -- Полный путь до аргументов выборки в запросе
|
||
XRQ_ARGUMENTS PKG_XPATH.TNODES; -- Коллекция элементов документа запроса с аргументами
|
||
XRQ_ARGUMENT PKG_XPATH.TNODE; -- Элемент документа запроса с аргументов
|
||
begin
|
||
/* Инициализируем результат */
|
||
RES := TARGUMENTS();
|
||
/* Сформируем полный путь до аргументов в выборке */
|
||
SRQ_ARGUMENTS_PATH := RQ_PAYLOAD_ITEM_PATH_GET(SITEM_TAG => SRQ_TAG_XARGUMENTS) || '/' || SRQ_TAG_XARGUMENT;
|
||
/* Считаем коллекцию аргументов из документа */
|
||
XRQ_ARGUMENTS := PKG_XPATH.LIST_NODES(RPARENT_NODE => XRQ_ROOT, SPATTERN => SRQ_ARGUMENTS_PATH);
|
||
/* Обходим коллекцию аргументов из документа */
|
||
for I in 1 .. PKG_XPATH.COUNT_NODES(RNODES => XRQ_ARGUMENTS)
|
||
loop
|
||
/* Берем очередной аргумент */
|
||
XRQ_ARGUMENT := PKG_XPATH.ITEM_NODE(RNODES => XRQ_ARGUMENTS, INUMBER => I);
|
||
/* Добавляем его в выходную коллекцию */
|
||
RES.EXTEND();
|
||
RES(RES.LAST).SNAME := NODE_SVAL_GET(XROOT => XRQ_ARGUMENT, SPATH => SRQ_TAG_SNAME);
|
||
RES(RES.LAST).SDATA_TYPE := NODE_SVAL_GET(XROOT => XRQ_ARGUMENT, SPATH => SRQ_TAG_SDATA_TYPE);
|
||
/* Проверим корректность данных - наименование */
|
||
if (RES(RES.LAST).SNAME is null) then
|
||
P_EXCEPTION(0,
|
||
'Для аргумента не задано наименование (%s).',
|
||
SRQ_ARGUMENTS_PATH || '/' || SRQ_TAG_SNAME);
|
||
end if;
|
||
/* Проверим корректность данных - тип данных */
|
||
if (RES(RES.LAST).SDATA_TYPE is null) then
|
||
P_EXCEPTION(0,
|
||
'Для аргумента "%s" не задан тип данных (%s).',
|
||
RES(RES.LAST).SNAME,
|
||
SRQ_ARGUMENTS_PATH || '/' || SRQ_TAG_SDATA_TYPE);
|
||
end if;
|
||
/* Считаем значение в зависимости от типа данных */
|
||
case
|
||
/* Строка */
|
||
when (RES(RES.LAST).SDATA_TYPE = SDATA_TYPE_STR) then
|
||
RES(RES.LAST).SVALUE := NODE_SVAL_GET(XROOT => XRQ_ARGUMENT, SPATH => SRQ_TAG_VALUE);
|
||
/* Число */
|
||
when (RES(RES.LAST).SDATA_TYPE = SDATA_TYPE_NUMB) then
|
||
RES(RES.LAST).NVALUE := NODE_NVAL_GET(XROOT => XRQ_ARGUMENT, SPATH => SRQ_TAG_VALUE);
|
||
/* Дата */
|
||
when (RES(RES.LAST).SDATA_TYPE = SDATA_TYPE_DATE) then
|
||
RES(RES.LAST).DVALUE := NODE_DVAL_GET(XROOT => XRQ_ARGUMENT, SPATH => SRQ_TAG_VALUE);
|
||
/* Текст */
|
||
when (RES(RES.LAST).SDATA_TYPE = SDATA_TYPE_CLOB) then
|
||
RES(RES.LAST).CVALUE := NODE_CVAL_GET(XROOT => XRQ_ARGUMENT, SPATH => SRQ_TAG_VALUE);
|
||
/* Неподдерживаемый тип данных */
|
||
else
|
||
P_EXCEPTION(0,
|
||
'Указанный для аргумента "%s" тип данных "%s" не поддерживается (%s).',
|
||
RES(RES.LAST).SNAME,
|
||
RES(RES.LAST).SDATA_TYPE,
|
||
SRQ_ARGUMENTS_PATH || '/' || SRQ_TAG_SDATA_TYPE);
|
||
end case;
|
||
end loop;
|
||
/* Проверка обязательности */
|
||
if ((RES.COUNT = 0) and (NREQUIRED = 1)) then
|
||
P_EXCEPTION(0, 'Не указаны аргументы (' || SRQ_ARGUMENTS_PATH || ').');
|
||
end if;
|
||
/* Возвращаем результат */
|
||
return RES;
|
||
end RQ_PAYLOAD_ARGUMENTS_GET;
|
||
|
||
/* Исполнение хранимой процедуры */
|
||
procedure EXEC_STORED
|
||
(
|
||
XRQ_ROOT in PKG_XPATH.TNODE, -- Корневой элемент тела документа запроса
|
||
COUT out clob -- Ответ на запрос
|
||
)
|
||
is
|
||
SRQ_STORED PKG_STD.TSTRING; -- Наименование исполняемого хранимого объекта из запроса
|
||
SRQ_RESP_ARG PKG_STD.TSTRING; -- Наименование выходного аргумента хранимого объекта из запроса для формирования тела ответа
|
||
RQ_ARGUMENTS TARGUMENTS; -- Коллекция аргументов хранимого объекта из запроса
|
||
ARGS PKG_OBJECT_DESC.TARGUMENTS; -- Коллекция формальных параметров хранимого объекта
|
||
RARG PKG_OBJECT_DESC.TARGUMENT; -- Формальный параметр хранимого объекта
|
||
ARGS_VALS PKG_CONTPRMLOC.TCONTAINER; -- Контейнер для фактических параметров хранимого объекта
|
||
RARG_VAL PKG_CONTAINER.TPARAM; -- Фактический параметр хранимого объекта
|
||
SARG_NAME PKG_STD.TSTRING; -- Наименование текущего обрабатываемого фактического параметра хранимого объекта
|
||
XRESP integer; -- Документ для ответа
|
||
XRESP_OUT_ARGUMENTS PKG_XMAKE.TNODE; -- Элемент для коллекции выходных параметров хранимого объекта
|
||
RRESP_ARGUMENT_VALUE PKG_XMAKE.TVALUE; -- Значение выходного параметра хранимого объекта
|
||
BRESP_ARG_FOUND boolean := false; -- Флаг присутствия в составе выходных аргументов аргумента с типом CLOB и именем, указанным в параметре запроса SRESP_ARG
|
||
begin
|
||
/* Создаём документ для ответа */
|
||
XRESP := PKG_XMAKE.OPEN_CURSOR();
|
||
/* Проверим хранимый объект в запросе */
|
||
RQ_PAYLOAD_STORED_CHECK(XRQ_ROOT => XRQ_ROOT);
|
||
/* Считываем наименование хранимого объекта из запроса */
|
||
SRQ_STORED := RQ_PAYLOAD_STORED_GET(XRQ_ROOT => XRQ_ROOT, NREQUIRED => 1);
|
||
/* Считываем наименование выходного аргумента хранимого объекта из запроса для формирования тела ответа */
|
||
SRQ_RESP_ARG := NODE_SVAL_GET(XROOT => XRQ_ROOT,
|
||
SPATH => RQ_PAYLOAD_ITEM_PATH_GET(SITEM_TAG => SRQ_TAG_SRESP_ARG),
|
||
NREQUIRED => 0,
|
||
SMESSAGE_OBJECT => 'Наименование выходного аргумента для формирования тела ответа');
|
||
/* Считаем список аргументов из запроса */
|
||
RQ_ARGUMENTS := RQ_PAYLOAD_ARGUMENTS_GET(XRQ_ROOT => XRQ_ROOT);
|
||
/* Считываем описание параметров хранимого объекта */
|
||
ARGS := PKG_OBJECT_DESC.DESC_ARGUMENTS(SSTORED_NAME => SRQ_STORED, BRAISE_ERROR => true);
|
||
/* Обходим входные параметры и формируем коллекцию значений */
|
||
for I in 1 .. PKG_OBJECT_DESC.COUNT_ARGUMENTS(RARGUMENTS => ARGS)
|
||
loop
|
||
/* Считываем очередной параметр */
|
||
RARG := PKG_OBJECT_DESC.FETCH_ARGUMENT(RARGUMENTS => ARGS, IINDEX => I);
|
||
/* Если это входной параметр */
|
||
if (RARG.IN_OUT in (PKG_STD.PARAM_TYPE_IN, PKG_STD.PARAM_TYPE_IN_OUT)) then
|
||
/* Добавим его значение в коллекцию фактических параметров */
|
||
case RARG.DATA_TYPE
|
||
/* Строка */
|
||
when PKG_STD.DATA_TYPE_STR then
|
||
PKG_CONTPRMLOC.APPENDS(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG.ARGUMENT_NAME,
|
||
SVALUE => TARGUMENTS_SVAL_GET(ARGUMENTS => RQ_ARGUMENTS,
|
||
SARGUMENT => RARG.ARGUMENT_NAME),
|
||
NIN_OUT => RARG.IN_OUT);
|
||
/* Число */
|
||
when PKG_STD.DATA_TYPE_NUM then
|
||
PKG_CONTPRMLOC.APPENDN(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG.ARGUMENT_NAME,
|
||
NVALUE => TARGUMENTS_NVAL_GET(ARGUMENTS => RQ_ARGUMENTS,
|
||
SARGUMENT => RARG.ARGUMENT_NAME),
|
||
NIN_OUT => RARG.IN_OUT);
|
||
/* Дата */
|
||
when PKG_STD.DATA_TYPE_DATE then
|
||
PKG_CONTPRMLOC.APPENDD(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG.ARGUMENT_NAME,
|
||
DVALUE => TARGUMENTS_DVAL_GET(ARGUMENTS => RQ_ARGUMENTS,
|
||
SARGUMENT => RARG.ARGUMENT_NAME),
|
||
NIN_OUT => RARG.IN_OUT);
|
||
/* Текст */
|
||
when PKG_STD.DATA_TYPE_CLOB then
|
||
PKG_CONTPRMLOC.APPENDLC(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG.ARGUMENT_NAME,
|
||
LCVALUE => TARGUMENTS_CVAL_GET(ARGUMENTS => RQ_ARGUMENTS,
|
||
SARGUMENT => RARG.ARGUMENT_NAME),
|
||
NIN_OUT => RARG.IN_OUT);
|
||
/* Неизвестный тип данных */
|
||
else
|
||
P_EXCEPTION(0,
|
||
'Тип данных (%s) входного параметра "%s" не поддерживается.',
|
||
RARG.DB_DATA_TYPE,
|
||
RARG.ARGUMENT_NAME);
|
||
end case;
|
||
end if;
|
||
end loop;
|
||
/* Исполняем процедуру */
|
||
PKG_SQL_CALL.EXECUTE_STORED(SSTORED_NAME => SRQ_STORED, RPARAM_CONTAINER => ARGS_VALS);
|
||
/* Обходим выходные параметры и собираем их в ответ */
|
||
SARG_NAME := PKG_CONTPRMLOC.FIRST_(RCONTAINER => ARGS_VALS);
|
||
while (SARG_NAME is not null)
|
||
loop
|
||
/* Считываем значение параметра */
|
||
RARG_VAL := PKG_CONTPRMLOC.GET(RCONTAINER => ARGS_VALS, SNAME => SARG_NAME);
|
||
/* Считываем описание параметра */
|
||
RARG := PKG_OBJECT_DESC.FETCH_ARGUMENT(RARGUMENTS => ARGS, SARGUMENT_NAME => SARG_NAME);
|
||
/* Если это выходной параметр */
|
||
if (RARG.IN_OUT in (PKG_STD.PARAM_TYPE_IN_OUT, PKG_STD.PARAM_TYPE_OUT)) then
|
||
/* Сформируем для него значение в зависимости от его типа */
|
||
case RARG.DATA_TYPE
|
||
/* Строка */
|
||
when PKG_STD.DATA_TYPE_STR then
|
||
RRESP_ARGUMENT_VALUE := PKG_XMAKE.VALUE(ICURSOR => XRESP,
|
||
SVALUE => PKG_CONTPRMLOC.GETS(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG_VAL.NAME));
|
||
/* Число */
|
||
when PKG_STD.DATA_TYPE_NUM then
|
||
RRESP_ARGUMENT_VALUE := PKG_XMAKE.VALUE(ICURSOR => XRESP,
|
||
NVALUE => PKG_CONTPRMLOC.GETN(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG_VAL.NAME));
|
||
/* Дата */
|
||
when PKG_STD.DATA_TYPE_DATE then
|
||
RRESP_ARGUMENT_VALUE := PKG_XMAKE.VALUE(ICURSOR => XRESP,
|
||
DVALUE => PKG_CONTPRMLOC.GETD(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG_VAL.NAME));
|
||
/* Текст */
|
||
when PKG_STD.DATA_TYPE_CLOB then
|
||
RRESP_ARGUMENT_VALUE := PKG_XMAKE.VALUE(ICURSOR => XRESP,
|
||
LCVALUE => PKG_CONTPRMLOC.GETLC(RCONTAINER => ARGS_VALS,
|
||
SNAME => RARG_VAL.NAME));
|
||
if ((SRQ_RESP_ARG is not null) and (RARG_VAL.NAME = SRQ_RESP_ARG)) then
|
||
COUT := PKG_CONTPRMLOC.GETLC(RCONTAINER => ARGS_VALS, SNAME => RARG_VAL.NAME);
|
||
BRESP_ARG_FOUND := true;
|
||
exit;
|
||
end if;
|
||
/* Неизвестный тип данных */
|
||
else
|
||
P_EXCEPTION(0,
|
||
'Тип данных (%s) выходного параметра "%s" не поддерживается.',
|
||
RARG.DB_DATA_TYPE,
|
||
RARG.ARGUMENT_NAME);
|
||
end case;
|
||
/* Добавим ветку выходного параметра в выходную коллекцию */
|
||
XRESP_OUT_ARGUMENTS := PKG_XMAKE.CONCAT(ICURSOR => XRESP,
|
||
RNODE00 => XRESP_OUT_ARGUMENTS,
|
||
RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => XRESP,
|
||
SNAME => SRESP_TAG_XOUT_ARGUMENTS,
|
||
RNODE00 => PKG_XMAKE.ELEMENT(ICURSOR => XRESP,
|
||
SNAME => SRESP_TAG_SNAME,
|
||
RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => XRESP,
|
||
SVALUE => RARG_VAL.NAME)),
|
||
RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => XRESP,
|
||
SNAME => SRESP_TAG_VALUE,
|
||
RVALUE00 => RRESP_ARGUMENT_VALUE),
|
||
RNODE02 => PKG_XMAKE.ELEMENT(ICURSOR => XRESP,
|
||
SNAME => SRESP_TAG_SDATA_TYPE,
|
||
RVALUE00 => PKG_XMAKE.VALUE(ICURSOR => XRESP,
|
||
SVALUE => STD_DATA_TYPE_TO_STR(NSTD_DATA_TYPE => RARG.DATA_TYPE)))));
|
||
end if;
|
||
/* Считываем наименование следующего параметра */
|
||
SARG_NAME := PKG_CONTPRMLOC.NEXT_(RCONTAINER => ARGS_VALS, SNAME => SARG_NAME);
|
||
end loop;
|
||
/* Проверим, что был найден опциональный аргумент для формирования полного ответа */
|
||
if ((SRQ_RESP_ARG is not null) and (not BRESP_ARG_FOUND)) then
|
||
P_EXCEPTION(0,
|
||
'В составе выходных параметров "%s" отсуствует аргумент "%s" типа "CLOB".',
|
||
SRQ_STORED,
|
||
SRQ_RESP_ARG);
|
||
end if;
|
||
/* Собираем ответ (только если не формировали полный ответ через аргумент для формирования полного ответа) */
|
||
if (not BRESP_ARG_FOUND) then
|
||
COUT := PKG_XMAKE.SERIALIZE_TO_CLOB(ICURSOR => XRESP,
|
||
ITYPE => PKG_XMAKE.CONTENT_,
|
||
RNODE => PKG_XMAKE.ELEMENT(ICURSOR => XRESP,
|
||
SNAME => SRESP_TAG_XPAYLOAD,
|
||
RNODE00 => XRESP_OUT_ARGUMENTS));
|
||
end if;
|
||
/* Очистим контейнер параметров */
|
||
PKG_CONTPRMLOC.PURGE(RCONTAINER => ARGS_VALS);
|
||
/* Освобождаем документ результата */
|
||
PKG_XMAKE.CLOSE_CURSOR(ICURSOR => XRESP);
|
||
exception
|
||
when others then
|
||
/* Закроем курсор и вернем ошибку */
|
||
PKG_XMAKE.CLOSE_CURSOR(ICURSOR => XRESP);
|
||
/* Покажем ошибку */
|
||
PKG_STATE.DIAGNOSTICS_STACKED();
|
||
P_EXCEPTION(0, PKG_STATE.SQL_ERRM());
|
||
end EXEC_STORED;
|
||
|
||
/* Базовое исполнение действий */
|
||
procedure PROCESS
|
||
(
|
||
CIN in clob, -- Входные параметры
|
||
COUT out clob -- Результат
|
||
)
|
||
is
|
||
XRQ_ROOT PKG_XPATH.TNODE; -- Корневой элемент тела документа запроса
|
||
SRQ_ACTION PKG_STD.TSTRING; -- Код действия из запроса
|
||
begin
|
||
/* Разбираем запрос */
|
||
XRQ_ROOT := RQ_ROOT_GET(CRQ => CIN);
|
||
/* Считываем код действия из запроса */
|
||
SRQ_ACTION := RQ_ACTION_GET(XRQ_ROOT => XRQ_ROOT, NREQUIRED => 1);
|
||
/* Вызываем обработчик в зависимости от кода действия */
|
||
case SRQ_ACTION
|
||
/* Исполнение хранимой процедуры */
|
||
when SRQ_ACTION_EXEC_STORED then
|
||
EXEC_STORED(XRQ_ROOT => XRQ_ROOT, COUT => COUT);
|
||
/* Неизвестное действие */
|
||
else
|
||
P_EXCEPTION(0, 'Действие "%s" не поддерживается.', SRQ_ACTION);
|
||
end case;
|
||
end PROCESS;
|
||
|
||
/* Базовое добавление в буфер отмеченных записей для панели */
|
||
procedure SELECTLIST_INSERT
|
||
(
|
||
NIDENT in number, -- Идентификатор процесса
|
||
SAUTHID in varchar2, -- Пользователь
|
||
SSESSION_ID in varchar2, -- Идентификатор сеанса
|
||
SCONNECT_EXT in varchar2, -- Внешний идентификатор сеанса
|
||
NCOMPANY in number := null, -- Организация
|
||
NDOCUMENT in number, -- Документ
|
||
SUNITCODE in varchar2 := null, -- Код раздела документа
|
||
SACTIONCODE in varchar2 := null, -- Код действия документа
|
||
NCRN in number := null, -- Каталог документа
|
||
NDOCUMENT1 in number := null, -- Документ 1
|
||
SUNITCODE1 in varchar2 := null, -- Код раздела документа 1
|
||
SACTIONCODE1 in varchar2 := null, -- Код действия документа 1
|
||
NRN out number -- Рег. номер добавленной записи
|
||
)
|
||
is
|
||
begin
|
||
/* Формируем рег. номер */
|
||
NRN := GEN_ID();
|
||
/* Добвляем запись */
|
||
insert into P8PNL_SELECTLIST
|
||
(RN,
|
||
IDENT,
|
||
authid,
|
||
SESSION_ID,
|
||
CONNECT_EXT,
|
||
COMPANY,
|
||
DOCUMENT,
|
||
UNITCODE,
|
||
ACTIONCODE,
|
||
CRN,
|
||
DOCUMENT1,
|
||
UNITCODE1,
|
||
ACTIONCODE1)
|
||
values
|
||
(NRN,
|
||
NIDENT,
|
||
SAUTHID,
|
||
SSESSION_ID,
|
||
SCONNECT_EXT,
|
||
NCOMPANY,
|
||
NDOCUMENT,
|
||
SUNITCODE,
|
||
SACTIONCODE,
|
||
NCRN,
|
||
NDOCUMENT1,
|
||
SUNITCODE1,
|
||
SACTIONCODE1);
|
||
end SELECTLIST_INSERT;
|
||
|
||
/* Удаление записи буфера отмеченных записей для панели */
|
||
procedure SELECTLIST_DELETE
|
||
(
|
||
NRN in number -- Рег. номер удаляемой записи
|
||
)
|
||
is
|
||
begin
|
||
delete from P8PNL_SELECTLIST T where T.RN = NRN;
|
||
end SELECTLIST_DELETE;
|
||
|
||
/* Базовая инициализация буфера отмеченных записей для панели */
|
||
procedure SELECTLIST_INIT
|
||
(
|
||
NIDENT in number -- Идентификатор буфера отмеченных записей
|
||
)
|
||
is
|
||
NRN PKG_STD.TREF; -- Рег. номер добавленной записи буфера панелей
|
||
begin
|
||
/* Очищаем буфер панелей */
|
||
SELECTLIST_CLEAR(NIDENT => NIDENT);
|
||
/* Обходим системный буфер отмеченных записей */
|
||
for C in (select T.* from SELECTLIST T where T.IDENT = NIDENT)
|
||
loop
|
||
/* Копируем запись */
|
||
SELECTLIST_INSERT(NIDENT => C.IDENT,
|
||
SAUTHID => C.AUTHID,
|
||
SSESSION_ID => C.SESSION_ID,
|
||
SCONNECT_EXT => C.CONNECT_EXT,
|
||
NCOMPANY => C.COMPANY,
|
||
NDOCUMENT => C.DOCUMENT,
|
||
SUNITCODE => C.UNITCODE,
|
||
SACTIONCODE => C.ACTIONCODE,
|
||
NCRN => C.CRN,
|
||
NDOCUMENT1 => C.DOCUMENT1,
|
||
SUNITCODE1 => C.UNITCODE1,
|
||
SACTIONCODE1 => C.ACTIONCODE1,
|
||
NRN => NRN);
|
||
end loop;
|
||
end SELECTLIST_INIT;
|
||
|
||
/* Базовая очистка буфера отмеченных записей для панели */
|
||
procedure SELECTLIST_CLEAR
|
||
(
|
||
NIDENT in number -- Идентификатор буфера отмеченных записей
|
||
)
|
||
is
|
||
begin
|
||
/* Обходим буфер панелей */
|
||
for C in (select T.RN from P8PNL_SELECTLIST T where T.IDENT = NIDENT)
|
||
loop
|
||
SELECTLIST_DELETE(NRN => C.RN);
|
||
end loop;
|
||
end SELECTLIST_CLEAR;
|
||
|
||
end PKG_P8PANELS_BASE;
|
||
/
|