create or replace package PKG_P8PANELS_QE_BASE as /* Типы данных - Атрибут сущности */ type TATTR is record ( SID PKG_STD.TSTRING, -- Уникальный идентификатор в запросе SNAME PKG_STD.TSTRING, -- Имя STITLE PKG_STD.TSTRING, -- Заголовок NDATA_TYPE PKG_STD.TNUMBER, -- Тип данных (см. константы PKG_STD.DATA_TYPE_*) SAGG PKG_STD.TSTRING, -- Агрегатная функция SALIAS PKG_STD.TSTRING, -- Псевдоним в выборке NUSE PKG_STD.TNUMBER, -- Флаг применения в запросе (1 - да, 0 - нет) NSHOW PKG_STD.TNUMBER -- Флаг отображения в выборке (1 - да, 0 - нет) ); /* Типы данных - Коллекция атрибутов сущности */ type TATTRS is table of TATTR; /* Типы данных - Сущность */ type TENT is record ( SID PKG_STD.TSTRING, -- Уникальный идентификатор в запросе SNAME PKG_STD.TSTRING, -- Имя STITLE PKG_STD.TSTRING, -- Заголовок STYPE PKG_STD.TSTRING, -- Тип (см. константы SENT_TYPE_*) NX PKG_STD.TNUMBER := 0, -- Координата по оси абсцисс NY PKG_STD.TNUMBER := 0, -- Координата по оси ординат RATTRS TATTRS -- Атрибуты ); /* Типы данных - Коллекция сущностей */ type TENTS is table of TENT; /* Типы данных - Отношение */ type TRL is record ( SID PKG_STD.TSTRING, -- Уникальный идентификатор в запросе SSOURCE PKG_STD.TSTRING, -- Идентификатор атрибута-источника STARGET PKG_STD.TSTRING -- Идентификатор атрибута-приёмника ); /* Типы данных - Коллекция отношений */ type TRLS is table of TRL; /* Десериализация коллекции атрибутов сущности (из BASE64) */ function TATTRS_FROM_XML_BASE64 ( CXML in clob, -- XML-описание коллекции атрибутов сущности (BASE64) SCHARSET in varchar2, -- Кодировка, в которой XML-данные были упакованы в BASE64 BADD_ROOT in boolean := false -- Флаг необходимости добавления корневого тэга (false - нет, true - да) ) return TATTRS; -- Коллекция атрибутов сущности /* Поиск индекса сущности по идентификатору */ function TENTS_INDEX_BY_ID ( RENTS in TENTS, -- Коллекция сущностей SID in varchar2 -- Искомый идентификатор ) return number; -- Индекс найденной сущности (null - если не найдено) /* Добавление сущности в коллекцию */ procedure TENTS_APPEND ( RENTS in out nocopy TENTS, -- Изменяемая коллекция SNAME in varchar2, -- Имя STYPE in varchar2 -- Тип (см. константы SENT_TYPE_*) ); /* Удаление сущности из коллекции */ procedure TENTS_REMOVE ( RENTS in out nocopy TENTS, -- Изменяемая коллекция SID in varchar2 -- Идентификатор удялемой сущности ); /* Установка координат сущности в коллекции */ procedure TENTS_POSITION_SET ( RENTS in out nocopy TENTS, -- Изменяемая коллекция SID in varchar2, -- Идентификатор сущности NX in number, -- Координата по оси абсцисс NY in number -- Координата по оси ординат ); /* Добавление связи в коллекцию */ procedure TRLS_APPEND ( RRLS in out nocopy TRLS, -- Изменяемая коллекция SSOURCE in varchar2, -- Источник STARGET in varchar2 -- Приёмник ); /* Удаление связи из коллекции */ procedure TRLS_REMOVE ( RRLS in out nocopy TRLS, -- Изменяемая коллекция SID in varchar2 -- Идентификатор удялемой связи ); /* Подчистка коллекции связей по атрибуту */ procedure TRLS_CLEANUP_BY_ATTR ( RRLS in out nocopy TRLS, -- Изменяемая коллекция SATTR_ID in varchar2 -- Идентификатор атрибута ); /* Считывание записи запроса */ function QUERY_GET ( NRN in number -- Рег. номер запроса ) return P8PNL_QE_QUERY%rowtype; -- Запись запроса /* Получение признака возможности изменения запроса */ function QUERY_ACCESS_SIGN_MODIFY ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ) return number; -- Признак возможности изменения запроса (0 - нет, 1 - да) /* Проверка возможности изменения запроса */ procedure QUERY_ACCESS_MODIFY ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ); /* Получение признака возможности просмотра запроса */ function QUERY_ACCESS_SIGN_VIEW ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ) return number; -- Признак возможности просмотра запроса (0 - нет, 1 - да) /* Проверка возможности просмотра запроса */ procedure QUERY_ACCESS_VIEW ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ); /* Добавление запроса */ procedure QUERY_INSERT ( SCODE in varchar2, -- Мнемокод SNAME in varchar2, -- Наименование NRN out number -- Рег. номер добавленного запроса ); /* Исправление запроса */ procedure QUERY_UPDATE ( NRN in number, -- Рег. номер запроса SCODE in varchar2, -- Мнемокод SNAME in varchar2 -- Наименование ); /* Удаление запроса */ procedure QUERY_DELETE ( NRN in number -- Рег. номер запроса ); /* Формирование списка запросов */ function QUERY_LIST_GET ( SUSER in varchar2 -- Имя пользователя ) return clob; -- Список запросов /* Получение описания запроса */ function QUERY_DESC_GET ( NRN in number -- Рег. номер запроса ) return clob; -- XML-описание /* Чтение сущностей запроса */ function QUERY_ENTS_GET ( CENTS in clob -- Сериализованное описание сущностей ) return TENTS; -- Коллекция сущностей /* Запись сущностей запроса */ procedure QUERY_ENTS_SET ( NRN in number, -- Рег. номер запроса RENTS in TENTS -- Коллекция сущностей ); /* Получение состава атрибутов сущности */ procedure QUERY_ENT_ATTRS_GET ( NRN in number, -- Рег. номер запроса SID in varchar2, -- Идентификатор сущности COUT out clob -- Сериализованное описание атрибутов сущности ); /* Чтение связей запроса */ function QUERY_RLS_GET ( CRLS in clob -- Сериализованное описание связей ) return TRLS; -- Коллекция связей /* Запись связей запроса */ procedure QUERY_RLS_SET ( NRN in number, -- Рег. номер запроса RRLS in TRLS -- Коллекция связей ); /* Установка признака "готовности" запроса */ procedure QUERY_READY_SET ( NRN in number, -- Рег. номер запроса NREADY in number -- Флаг готовности к использованию (0 - нет, 1 - да) ); /* Установка признака "публичности" запроса */ procedure QUERY_PBL_SET ( NRN in number, -- Рег. номер запроса NPBL in number -- Флаг публичности (0 - приватный, 1 - публичный) ); end PKG_P8PANELS_QE_BASE; / create or replace package body PKG_P8PANELS_QE_BASE as /* Константы - Типы сущностей */ SENT_TYPE_TABLE constant PKG_STD.TSTRING := 'TABLE'; -- Таблица SENT_TYPE_VIEW constant PKG_STD.TSTRING := 'VIEW'; -- Представление /* Константы - Теги для сериализации */ STAG_DATA constant PKG_STD.TSTRING := 'XDATA'; -- Данные STAG_QUERIES constant PKG_STD.TSTRING := 'XQUERIES'; -- Запросы STAG_QUERY constant PKG_STD.TSTRING := 'XQUERY'; -- Запрос STAG_ATTRS constant PKG_STD.TSTRING := 'XATTRS'; -- Атрибуты сущности STAG_ATTR constant PKG_STD.TSTRING := 'XATTR'; -- Атрибут сущности STAG_ENTS constant PKG_STD.TSTRING := 'XENTS'; -- Сущности STAG_ENT constant PKG_STD.TSTRING := 'XENT'; -- Сущность STAG_RLS constant PKG_STD.TSTRING := 'XRLS'; -- Связи STAG_RL constant PKG_STD.TSTRING := 'XRL'; -- Связь STAG_OPTS constant PKG_STD.TSTRING := 'XOPTS'; -- Параметры STAG_OPT constant PKG_STD.TSTRING := 'XOPT'; -- Параметр /* Константы - Атрибуты для сериализации */ SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор SATTR_RN constant PKG_STD.TSTRING := 'rn'; -- Регистрационный номер SATTR_CODE constant PKG_STD.TSTRING := 'code'; -- Код SATTR_NAME constant PKG_STD.TSTRING := 'name'; -- Имя SATTR_AUTHOR constant PKG_STD.TSTRING := 'author'; -- Автор SATTR_CH_DATE constant PKG_STD.TSTRING := 'chDate'; -- Дата изменения SATTR_READY constant PKG_STD.TSTRING := 'ready'; -- Готовность к использованию SATTR_PBL constant PKG_STD.TSTRING := 'pbl'; -- Публичность SATTR_MODIFY constant PKG_STD.TSTRING := 'modify'; -- Изменяемость SATTR_TITLE constant PKG_STD.TSTRING := 'title'; -- Заголовок SATTR_TYPE constant PKG_STD.TSTRING := 'type'; -- Тип SATTR_DATA_TYPE constant PKG_STD.TSTRING := 'dataType'; -- Тип данных SATTR_X constant PKG_STD.TSTRING := 'x'; -- Координата по X SATTR_Y constant PKG_STD.TSTRING := 'y'; -- Координата по Y SATTR_SOURCE constant PKG_STD.TSTRING := 'source'; -- Источник SATTR_TARGET constant PKG_STD.TSTRING := 'target'; -- Приёмник SATTR_AGG constant PKG_STD.TSTRING := 'agg'; -- Агрегатная функция SATTR_ALIAS constant PKG_STD.TSTRING := 'alias'; -- Псевдоним SATTR_USE constant PKG_STD.TSTRING := 'use'; -- Применение в запросе SATTR_SHOW constant PKG_STD.TSTRING := 'show'; -- Отображение в запросе /* Получение заголовка представления из метаданных */ function DMSCLVIEWS_TITLE_GET ( SVIEW_NAME in varchar2 -- Имя представления ) return varchar2 -- Заголовок представления из метаданных is begin /* Обратимся к метаописанию представления */ for V in (select T.VIEW_NOTE, UL.UNITNAME from DMSCLVIEWS T, UNITLIST UL where T.VIEW_NAME = SVIEW_NAME and T.CUSTOM_QUERY = 0 and T.PRN = UL.RN) loop if (V.VIEW_NOTE = SVIEW_NAME) then return V.UNITNAME; else return V.VIEW_NOTE; end if; end loop; /* Ничего не нашли - вернём обычное имя */ return SVIEW_NAME; end DMSCLVIEWS_TITLE_GET; /* Получение заголовка атрибута представления из метаданных */ function DMSCLVIEWSATTRS_TITLE_GET ( SVIEW_NAME in varchar2, -- Имя представления SATTR_NAME in varchar2 -- Имя атрибута ) return varchar2 -- Заголовок атрибута представления из метаданных is begin /* Обратимся к метаописанию представления */ for V in (select T.RN from DMSCLVIEWS T where T.VIEW_NAME = SVIEW_NAME and T.CUSTOM_QUERY = 0) loop /* Обходим поля найденного представления */ for F in (select A.CAPTION from DMSCLVIEWSATTRS T, DMSCLATTRS A where T.PRN = V.RN and T.COLUMN_NAME = SATTR_NAME and T.ATTR = A.RN) loop return F.CAPTION; end loop; end loop; /* Ничего не нашли - вернём обычное имя */ return SATTR_NAME; end DMSCLVIEWSATTRS_TITLE_GET; /* Формирование идентификатора атрибута сущности */ function TATTR_ID_MAKE ( SENT_ID in varchar2, -- Уникальный идентификатор родительской сущности SNAME in varchar2 -- Имя атрибута ) return varchar2 -- Сформированный идентификатор is begin /* Проверим параметры */ if (SNAME is null) then P_EXCEPTION(0, 'Не указано имя атрибута сущности.'); end if; if (SENT_ID is null) then P_EXCEPTION(0, 'Не указан идентификатор родительской сущности атрибута.'); end if; /* Соберем идентификатор */ return SENT_ID || '.' || SNAME; end TATTR_ID_MAKE; /* Сериализация атрибута сущности */ procedure TATTR_TO_XML ( RATTR in TATTR -- Атрибут сущности ) is begin /* Открываем описание атрибута сущности */ PKG_XFAST.DOWN_NODE(SNAME => STAG_ATTR); /* Атрибут */ PKG_XFAST.ATTR(SNAME => SATTR_ID, SVALUE => RATTR.SID); PKG_XFAST.ATTR(SNAME => SATTR_NAME, SVALUE => RATTR.SNAME); PKG_XFAST.ATTR(SNAME => SATTR_TITLE, SVALUE => RATTR.STITLE); PKG_XFAST.ATTR(SNAME => SATTR_DATA_TYPE, NVALUE => RATTR.NDATA_TYPE); PKG_XFAST.ATTR(SNAME => SATTR_AGG, SVALUE => RATTR.SAGG); PKG_XFAST.ATTR(SNAME => SATTR_ALIAS, SVALUE => RATTR.SALIAS); PKG_XFAST.ATTR(SNAME => SATTR_USE, NVALUE => RATTR.NUSE); PKG_XFAST.ATTR(SNAME => SATTR_SHOW, NVALUE => RATTR.NSHOW); /* Закрываем описание атрибута сущности */ PKG_XFAST.UP(); end TATTR_TO_XML; /* Десериализация атрибута сущности */ function TATTR_FROM_XML ( CXML in clob -- XML-описание атрибута сущности ) return TATTR -- Атрибут сущности is RRES TATTR; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа begin /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_ATTR); /* Получаем значения */ RRES.SID := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ID); RRES.SNAME := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_NAME); RRES.STITLE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TITLE); RRES.NDATA_TYPE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_DATA_TYPE); RRES.SAGG := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_AGG); RRES.SALIAS := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ALIAS); RRES.NUSE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_USE); RRES.NSHOW := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_SHOW); /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём результат */ return RRES; end TATTR_FROM_XML; /* Поиск индекса атрибута по имени */ function TATTRS_INDEX_BY_NAME ( RATTRS in TATTRS, -- Коллекция атрибутов SNAME in varchar2 -- Искомое имя ) return number -- Индекс найденного атрибута (null - если не найдено) is begin /* Обходим коллекцию */ if ((RATTRS is not null) and (RATTRS.COUNT > 0)) then for I in RATTRS.FIRST .. RATTRS.LAST loop begin /* Возвращаем найденный индекс */ if (RATTRS(I).SNAME = SNAME) then return I; end if; exception when NO_DATA_FOUND then null; end; end loop; end if; /* Ничего не нашли */ return null; end TATTRS_INDEX_BY_NAME; /* Формирование списка атрибутов сущности по типу и наименованию */ function TATTRS_MAKE ( RENT in TENT, -- Родительская сущность NCOUNT in number := null -- Количество атрибутов (null - все) ) return TATTRS -- Коллекция атрибутов сущности is RRES TATTRS; -- Буфер для результата RVIEW_FIELDS PKG_OBJECT_DESC.TCOLUMNS; -- Коллекция описаний полей представления RVIEW_FIELD PKG_OBJECT_DESC.TCOLUMN; -- Описание поля представления NATTR_INDEX PKG_STD.TNUMBER; -- Индекс поля в коллекции атрибутов сущности BINIT boolean := false; -- Признак инициализации атрибутов сущности begin /* Проверим корректность типа сущности */ if (RENT.STYPE not in (SENT_TYPE_TABLE, SENT_TYPE_VIEW)) then P_EXCEPTION(0, 'Сущности типа "%s" не поддерживаются.', COALESCE(RENT.STYPE, '<НЕ УКАЗАН>')); end if; /* Проверим, что у сущности задан идентификатор */ if (RENT.SID is null) then P_EXCEPTION(0, 'Ошибка формирования атрибутов - не задан идентификатор сущности.'); end if; /* Проверим, что у сущности задано имя */ if (RENT.SNAME is null) then P_EXCEPTION(0, 'Ошибка формирования атрибутов - не задано имя сущности.'); end if; /* Инициализируем результат */ RRES := TATTRS(); /* Установим флаг инициализации - в сущности нет атрибутов и нас просили ограничить количество */ if (((RENT.RATTRS is null) or (RENT.RATTRS.COUNT = 0)) and (NCOUNT is not null)) then BINIT := true; end if; /* Если сущность это представление */ if (RENT.STYPE = SENT_TYPE_VIEW) then /* Получим список полей представления */ RVIEW_FIELDS := PKG_OBJECT_DESC.DESC_SEL_COLUMNS(SSELECT_NAME => RENT.SNAME, BRAISE_ERROR => true); /* Собираем атрибуты в ответ */ for I in 1 .. PKG_OBJECT_DESC.COUNT_COLUMNS(RCOLUMNS => RVIEW_FIELDS) loop /* Считываем очередное поле из коллекции описания полей представления */ RVIEW_FIELD := PKG_OBJECT_DESC.FETCH_COLUMN(RCOLUMNS => RVIEW_FIELDS, IINDEX => I); /* Если поле поддерживаемого типа */ if (RVIEW_FIELD.DATA_TYPE in (PKG_STD.DATA_TYPE_STR(), PKG_STD.DATA_TYPE_NUM(), PKG_STD.DATA_TYPE_DATE())) then /* Добавляем элемент в результирующую коллекцию */ RRES.EXTEND(); /* Ищем такой атрибут в родительской сущности */ NATTR_INDEX := TATTRS_INDEX_BY_NAME(RATTRS => RENT.RATTRS, SNAME => RVIEW_FIELD.COLUMN_NAME); /* Если это поле уже есть в коллекции атрибутов родительской сущности */ if (NATTR_INDEX is not null) then /* Возьмём элемент оттуда */ RRES(RRES.LAST) := RENT.RATTRS(NATTR_INDEX); else /* Такого элемента нет - берем из представления */ RRES(RRES.LAST).SID := TATTR_ID_MAKE(SENT_ID => RENT.SID, SNAME => RVIEW_FIELD.COLUMN_NAME); RRES(RRES.LAST).SNAME := RVIEW_FIELD.COLUMN_NAME; RRES(RRES.LAST).STITLE := DMSCLVIEWSATTRS_TITLE_GET(SVIEW_NAME => RENT.SNAME, SATTR_NAME => RRES(RRES.LAST).SNAME); RRES(RRES.LAST).NDATA_TYPE := RVIEW_FIELD.DATA_TYPE; /* Если это инициализиция сущности - установим флаг применения в запросе (тогда атрибут будет отображен в диаграмме) */ if (BINIT) then RRES(RRES.LAST).NUSE := 1; RRES(RRES.LAST).NSHOW := 1; else RRES(RRES.LAST).NUSE := 0; RRES(RRES.LAST).NSHOW := 0; end if; end if; /* Ограничим объем коллекции если необходимо */ if (NCOUNT is not null) then exit when RRES.LAST = NCOUNT; end if; end if; end loop; end if; /* Если сущность это таблица */ if (RENT.STYPE = SENT_TYPE_TABLE) then P_EXCEPTION(0, 'Поддержка формирования атрибутов для сущностей типа "Таблица" ещё не реализована.'); end if; /* Возвращаем результат */ return RRES; end TATTRS_MAKE; /* Сериализация коллекции атрибутов сущности */ procedure TATTRS_TO_XML ( RATTRS in TATTRS -- Коллекция атрибутов сущности ) is begin /* Открываем описание атрибутов сущности */ PKG_XFAST.DOWN_NODE(SNAME => STAG_ATTRS); /* Обходим атрибуты из коллекции */ if ((RATTRS is not null) and (RATTRS.COUNT > 0)) then for I in RATTRS.FIRST .. RATTRS.LAST loop /* Добавляем описание атрибута сущности */ TATTR_TO_XML(RATTR => RATTRS(I)); end loop; end if; /* Закрываем описание атрибутов сущности */ PKG_XFAST.UP(); end TATTRS_TO_XML; /* Десериализация коллекции атрибутов сущности */ function TATTRS_FROM_XML ( CXML in clob -- XML-описание коллекции атрибутов сущности ) return TATTRS -- Коллекция атрибутов сущности is RRES TATTRS; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа XNODES PKG_XPATH.TNODES; -- Буфер коллекции узлов документа begin /* Инициализируем результат */ RRES := TATTRS(); /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считывание списка атрибутов */ XNODES := PKG_XPATH.LIST_NODES(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_ATTRS || '/' || STAG_ATTR); /* Цикл по списку атрибутов */ for I in 1 .. PKG_XPATH.COUNT_NODES(RNODES => XNODES) loop /* Считаем элемент по его номеру */ XNODE := PKG_XPATH.ITEM_NODE(RNODES => XNODES, INUMBER => I); /* Сериализуем и добавим его в коллекцию */ RRES.EXTEND(); RRES(RRES.LAST) := TATTR_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => XNODE)); end loop; /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём результат */ return RRES; end TATTRS_FROM_XML; /* Десериализация коллекции атрибутов сущности (из BASE64) */ function TATTRS_FROM_XML_BASE64 ( CXML in clob, -- XML-описание коллекции атрибутов сущности (BASE64) SCHARSET in varchar2, -- Кодировка, в которой XML-данные были упакованы в BASE64 BADD_ROOT in boolean := false -- Флаг необходимости добавления корневого тэга (false - нет, true - да) ) return TATTRS -- Коллекция атрибутов сущности is CTMP clob; -- Буфер для преобразований begin /* Избавимся от BASE64 */ CTMP := BLOB2CLOB(LBDATA => BASE64_DECODE(LCSRCE => CXML), SCHARSET => SCHARSET); /* Если надо - добавим корень */ if (BADD_ROOT) then CTMP := '<' || STAG_ATTRS || '>' || CTMP || ''; end if; /* Десериализуем */ return TATTRS_FROM_XML(CXML => CTMP); end TATTRS_FROM_XML_BASE64; /* Формирование идентификатора сущности */ function TENT_ID_MAKE ( SNAME in varchar2, -- Имя сущности NNUMB in number -- Номер сущности в запросе ) return varchar2 -- Сформированный идентификатор is begin /* Проверим параметры */ if (SNAME is null) then P_EXCEPTION(0, 'Не указано имя сущности.'); end if; /* Соберем идентификатор */ if (NNUMB is null) then return SNAME; else return SNAME || TO_CHAR(NNUMB); end if; end TENT_ID_MAKE; /* Формирование описания сущности */ function TENT_MAKE ( SNAME in varchar2, -- Имя STYPE in varchar2, -- Тип (см. константы SENT_TYPE_*) NNUMB in number -- Номер сущности ) return TENT -- Описание сущности is RENT TENT; -- Буфер для результата RVIEW PKG_OBJECT_DESC.TVIEW; -- Описание представления begin /* Проверим корректность типа сущности */ if (STYPE not in (SENT_TYPE_TABLE, SENT_TYPE_VIEW)) then P_EXCEPTION(0, 'Сущности типа "%s" не поддерживаются.', COALESCE(STYPE, '<НЕ УКАЗАН>')); end if; /* Если сущность это представление */ if (STYPE = SENT_TYPE_VIEW) then /* Получим описание представления */ RVIEW := PKG_OBJECT_DESC.DESC_VIEW(SVIEW_NAME => SNAME, BRAISE_ERROR => true); /* Собираем заголовок сущности */ RENT.SID := TENT_ID_MAKE(SNAME => RVIEW.VIEW_NAME, NNUMB => NNUMB); RENT.SNAME := RVIEW.VIEW_NAME; RENT.STITLE := DMSCLVIEWS_TITLE_GET(SVIEW_NAME => RENT.SNAME); RENT.STYPE := SENT_TYPE_VIEW; /* Формируем набор атрибутов */ RENT.RATTRS := TATTRS_MAKE(RENT => RENT, NCOUNT => 10); end if; /* Если сущность это таблица */ if (STYPE = SENT_TYPE_TABLE) then P_EXCEPTION(0, 'Поддержка сущностей типа "Таблица" ещё не реализована.'); end if; /* Вернем полученное */ return RENT; end TENT_MAKE; /* Сериализация сущности */ procedure TENT_TO_XML ( RENT in TENT -- Сущность ) is begin /* Открываем описание сущности */ PKG_XFAST.DOWN_NODE(SNAME => STAG_ENT); /* Cущность */ PKG_XFAST.ATTR(SNAME => SATTR_ID, SVALUE => RENT.SID); PKG_XFAST.ATTR(SNAME => SATTR_NAME, SVALUE => RENT.SNAME); PKG_XFAST.ATTR(SNAME => SATTR_TITLE, SVALUE => RENT.STITLE); PKG_XFAST.ATTR(SNAME => SATTR_TYPE, SVALUE => RENT.STYPE); PKG_XFAST.ATTR(SNAME => SATTR_X, NVALUE => RENT.NX); PKG_XFAST.ATTR(SNAME => SATTR_Y, NVALUE => RENT.NY); /* Атрибуты */ TATTRS_TO_XML(RATTRS => RENT.RATTRS); /* Закрываем описание сущности */ PKG_XFAST.UP(); end TENT_TO_XML; /* Десериализация сущности */ function TENT_FROM_XML ( CXML in clob -- XML-описание сущности ) return TENT -- Сущность is RRES TENT; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа begin /* Инициализируем сущность */ RRES.RATTRS := TATTRS(); /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считаваем узел сущности */ XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_ENT); /* Получаем значения */ RRES.SID := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ID); RRES.SNAME := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_NAME); RRES.STITLE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TITLE); RRES.STYPE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TYPE); RRES.NX := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_X); RRES.NY := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_Y); RRES.RATTRS := TATTRS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XNODE, SPATTERN => STAG_ATTRS))); /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём результат */ return RRES; end TENT_FROM_XML; /* Поиск индекса сущности по идентификатору */ function TENTS_INDEX_BY_ID ( RENTS in TENTS, -- Коллекция сущностей SID in varchar2 -- Искомый идентификатор ) return number -- Индекс найденной сущности (null - если не найдено) is begin /* Обходим коллекцию */ if ((RENTS is not null) and (RENTS.COUNT > 0)) then for I in RENTS.FIRST .. RENTS.LAST loop begin /* Возвращаем найденный индекс */ if (RENTS(I).SID = SID) then return I; end if; exception when NO_DATA_FOUND then null; end; end loop; end if; /* Ничего не нашли */ return null; end TENTS_INDEX_BY_ID; /* Поиск номера сущности в коллекции */ function TENTS_NEXT_NUMB ( RENTS in TENTS, -- Коллекция сущностей SNAME in varchar2 -- Имя ) return number -- Номер сущности в коллекции is NNUMB PKG_STD.TNUMBER := 0; -- Буфер для результата begin /* Подбираем первый свободный номер */ while (TENTS_INDEX_BY_ID(RENTS => RENTS, SID => TENT_ID_MAKE(SNAME => SNAME, NNUMB => NNUMB)) is not null) loop NNUMB := NNUMB + 1; end loop; /* Возвращаем его */ return NNUMB; end TENTS_NEXT_NUMB; /* Добавление сущности в коллекцию */ procedure TENTS_APPEND ( RENTS in out nocopy TENTS, -- Изменяемая коллекция SNAME in varchar2, -- Имя STYPE in varchar2 -- Тип (см. константы SENT_TYPE_*) ) is RENT TENT; -- Добавляемая сущность begin /* Инициализируем коллекцию если необходимо */ if (RENTS is null) then RENTS := TENTS(); end if; /* Формируем пописание сущности */ RENT := TENT_MAKE(SNAME => SNAME, STYPE => STYPE, NNUMB => TENTS_NEXT_NUMB(RENTS => RENTS, SNAME => SNAME)); /* Добавляем её в коллекцию */ RENTS.EXTEND(); RENTS(RENTS.LAST) := RENT; end TENTS_APPEND; /* Удаление сущности из коллекции */ procedure TENTS_REMOVE ( RENTS in out nocopy TENTS, -- Изменяемая коллекция SID in varchar2 -- Идентификатор удялемой сущности ) is NIND PKG_STD.TNUMBER; -- Индекс сущности в коллекции begin NIND := TENTS_INDEX_BY_ID(RENTS => RENTS, SID => SID); if (NIND is not null) then RENTS.DELETE(NIND); end if; end TENTS_REMOVE; /* Установка координат сущности в коллекции */ procedure TENTS_POSITION_SET ( RENTS in out nocopy TENTS, -- Изменяемая коллекция SID in varchar2, -- Идентификатор сущности NX in number, -- Координата по оси абсцисс NY in number -- Координата по оси ординат ) is NIND PKG_STD.TNUMBER; -- Индекс сущности в коллекции begin NIND := TENTS_INDEX_BY_ID(RENTS => RENTS, SID => SID); if (NIND is not null) then RENTS(NIND).NX := NX; RENTS(NIND).NY := NY; end if; end TENTS_POSITION_SET; /* Сериализация коллекции сущностей */ procedure TENTS_TO_XML ( RENTS in TENTS -- Коллекция сущностей ) is begin /* Открываем описание сущностей */ PKG_XFAST.DOWN_NODE(SNAME => STAG_ENTS); /* Обходим сущности из коллекции */ if ((RENTS is not null) and (RENTS.COUNT > 0)) then for I in RENTS.FIRST .. RENTS.LAST loop begin /* Добавляем описание сущности */ TENT_TO_XML(RENT => RENTS(I)); exception when NO_DATA_FOUND then null; end; end loop; end if; /* Закрываем описание сущностей */ PKG_XFAST.UP(); end TENTS_TO_XML; /* Десериализация коллекции сущностей */ function TENTS_FROM_XML ( CXML in clob -- XML-описание коллекции сущностей ) return TENTS -- Коллекция сущностей is RRES TENTS; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа XNODES PKG_XPATH.TNODES; -- Буфер коллекции узлов документа begin /* Инициализируем результат */ RRES := TENTS(); /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считывание списка сущностей */ XNODES := PKG_XPATH.LIST_NODES(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_ENTS || '/' || STAG_ENT); /* Цикл по списку сущностей */ for I in 1 .. PKG_XPATH.COUNT_NODES(RNODES => XNODES) loop /* Считаем элемент по его номеру */ XNODE := PKG_XPATH.ITEM_NODE(RNODES => XNODES, INUMBER => I); /* Сериализуем и добавим его в коллекцию */ RRES.EXTEND(); RRES(RRES.LAST) := TENT_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => XNODE)); end loop; /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём результат */ return RRES; end TENTS_FROM_XML; /* Формирование идентификатора связи */ function TRL_ID_MAKE ( SSOURCE in varchar2, -- Источник STARGET in varchar2 -- Приёмник ) return varchar2 -- Сформированный идентификатор is begin /* Проверим параметры */ if (SSOURCE is null) then P_EXCEPTION(0, 'Не указан источник связи.'); end if; if (STARGET is null) then P_EXCEPTION(0, 'Не указан приёмник связи.'); end if; /* Соберем идентификатор */ return SSOURCE || '-' || STARGET; end TRL_ID_MAKE; /* Формирование описания связи */ function TRL_MAKE ( SID in varchar2 := null, -- Идентификатор (null - автоформирование) SSOURCE in varchar2, -- Источник STARGET in varchar2 -- Приёмник ) return TRL -- Описание связи is RRL TRL; -- Буфер для результата begin /* Собираем описание связи */ RRL.SID := COALESCE(SID, TRL_ID_MAKE(SSOURCE => SSOURCE, STARGET => STARGET)); RRL.SSOURCE := SSOURCE; RRL.STARGET := STARGET; /* Вернем полученное */ return RRL; end TRL_MAKE; /* Сериализация связи */ procedure TRL_TO_XML ( RRL in TRL -- Связь ) is begin /* Открываем описание связи */ PKG_XFAST.DOWN_NODE(SNAME => STAG_RL); /* Связь */ PKG_XFAST.ATTR(SNAME => SATTR_ID, SVALUE => RRL.SID); PKG_XFAST.ATTR(SNAME => SATTR_SOURCE, SVALUE => RRL.SSOURCE); PKG_XFAST.ATTR(SNAME => SATTR_TARGET, SVALUE => RRL.STARGET); /* Закрываем описание связи */ PKG_XFAST.UP(); end TRL_TO_XML; /* Десериализация связи */ function TRL_FROM_XML ( CXML in clob -- XML-описание связи ) return TRL -- Связь is RRES TRL; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа begin /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считаваем узел связи */ XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_RL); /* Получаем значения */ RRES.SID := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ID); RRES.SSOURCE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_SOURCE); RRES.STARGET := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TARGET); /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём результат */ return RRES; end TRL_FROM_XML; /* Поиск индекса связи по идентификатору */ function TRLS_INDEX_BY_ID ( RRLS in TRLS, -- Коллекция связей SID in varchar2 -- Искомый идентификатор ) return number -- Индекс найденной связи (null - если не найдено) is begin /* Обходим коллекцию */ if ((RRLS is not null) and (RRLS.COUNT > 0)) then for I in RRLS.FIRST .. RRLS.LAST loop begin /* Возвращаем найденный индекс */ if (RRLS(I).SID = SID) then return I; end if; exception when NO_DATA_FOUND then null; end; end loop; end if; /* Ничего не нашли */ return null; end TRLS_INDEX_BY_ID; /* Формирование коллекции связей по источнику/приёмнику */ function TRLS_LIST_BY_ST ( RRLS in TRLS, -- Коллекция связей SSOURCE_TARGET in varchar2, -- Идентификатор источника/приёмкника NLIST_TYPE in number -- Тип формирования коллекции (0 - по источнику, 1 - по приёмнику ) return TRLS -- Сформированная коллекция is RRES TRLS; -- Буфер для результата begin /* Инициализируем результат */ RRES := TRLS(); /* Обходим входную коллекцию */ if ((RRLS is not null) and (RRLS.COUNT > 0)) then for I in RRLS.FIRST .. RRLS.LAST loop begin /* Формируем выходную коллекцию */ if (((NLIST_TYPE = 0) and (RRLS(I).SSOURCE = SSOURCE_TARGET)) or ((NLIST_TYPE = 1) and (RRLS(I).STARGET = SSOURCE_TARGET))) then RRES.EXTEND(); RRES(RRES.LAST) := TRL_MAKE(SID => RRLS(I).SID, SSOURCE => RRLS(I).SSOURCE, STARGET => RRLS(I).STARGET); end if; exception when NO_DATA_FOUND then null; end; end loop; end if; /* Вернем результат */ return RRES; end TRLS_LIST_BY_ST; /* Добавление связи в коллекцию */ procedure TRLS_APPEND ( RRLS in out nocopy TRLS, -- Изменяемая коллекция SSOURCE in varchar2, -- Источник STARGET in varchar2 -- Приёмник ) is RRL TRL; -- Добавляемая связь begin /* Инициализируем коллекцию если необходимо */ if (RRLS is null) then RRLS := TRLS(); end if; /* Формируем пописание связи */ RRL := TRL_MAKE(SSOURCE => SSOURCE, STARGET => STARGET); /* Добавляем её в коллекцию */ RRLS.EXTEND(); RRLS(RRLS.LAST) := RRL; end TRLS_APPEND; /* Удаление связи из коллекции */ procedure TRLS_REMOVE ( RRLS in out nocopy TRLS, -- Изменяемая коллекция SID in varchar2 -- Идентификатор удялемой связи ) is NIND PKG_STD.TNUMBER; -- Индекс связи в коллекции begin NIND := TRLS_INDEX_BY_ID(RRLS => RRLS, SID => SID); if (NIND is not null) then RRLS.DELETE(NIND); end if; end TRLS_REMOVE; /* Подчистка коллекции связей по атрибуту */ procedure TRLS_CLEANUP_BY_ATTR ( RRLS in out nocopy TRLS, -- Изменяемая коллекция SATTR_ID in varchar2 -- Идентификатор атрибута ) is RRLS_TMP PKG_P8PANELS_QE_BASE.TRLS; -- Буфер для коллекции удаляемых связей begin /* Если атрибут есть в связях (как источник или как приёмник) */ for J in 0 .. 1 loop RRLS_TMP := TRLS_LIST_BY_ST(RRLS => RRLS, SSOURCE_TARGET => SATTR_ID, NLIST_TYPE => J); /* То связь должна быть удалена */ if ((RRLS_TMP is not null) and (RRLS_TMP.COUNT > 0)) then for K in RRLS_TMP.FIRST .. RRLS_TMP.LAST loop TRLS_REMOVE(RRLS => RRLS, SID => RRLS_TMP(K).SID); end loop; end if; end loop; end TRLS_CLEANUP_BY_ATTR; /* Сериализация коллекции связей */ procedure TRLS_TO_XML ( RRLS in TRLS -- Коллекция связей ) is begin /* Открываем описание связей */ PKG_XFAST.DOWN_NODE(SNAME => STAG_RLS); /* Обходим связи из коллекции */ if ((RRLS is not null) and (RRLS.COUNT > 0)) then for I in RRLS.FIRST .. RRLS.LAST loop begin /* Добавляем описание связи */ TRL_TO_XML(RRL => RRLS(I)); exception when NO_DATA_FOUND then null; end; end loop; end if; /* Закрываем описание связей */ PKG_XFAST.UP(); end TRLS_TO_XML; /* Десериализация коллекции связей */ function TRLS_FROM_XML ( CXML in clob -- XML-описание коллекции связей ) return TRLS -- Коллекция связей is RRES TRLS; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа XNODES PKG_XPATH.TNODES; -- Буфер коллекции узлов документа begin /* Инициализируем результат */ RRES := TRLS(); /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считывание списка связей */ XNODES := PKG_XPATH.LIST_NODES(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_RLS || '/' || STAG_RL); /* Цикл по списку связей */ for I in 1 .. PKG_XPATH.COUNT_NODES(RNODES => XNODES) loop /* Считаем элемент по его номеру */ XNODE := PKG_XPATH.ITEM_NODE(RNODES => XNODES, INUMBER => I); /* Сериализуем и добавим его в коллекцию */ RRES.EXTEND(); RRES(RRES.LAST) := TRL_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => XNODE)); end loop; /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём результат */ return RRES; end TRLS_FROM_XML; /* Считывание записи запроса */ function QUERY_GET ( NRN in number -- Рег. номер запроса ) return P8PNL_QE_QUERY%rowtype -- Запись запроса is RRES P8PNL_QE_QUERY%rowtype; -- Буфер для результата begin select T.* into RRES from P8PNL_QE_QUERY T where T.RN = NRN; return RRES; exception when NO_DATA_FOUND then PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end QUERY_GET; /* Получение признака возможности изменения запроса */ function QUERY_ACCESS_SIGN_MODIFY ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ) return number -- Признак возможности изменения запроса (0 - нет, 1 - да) is RQ P8PNL_QE_QUERY%rowtype; -- Проверяемая запись запроса begin /* Читаем запрос */ RQ := QUERY_GET(NRN => NRN); /* Менять можно только свой запрос */ if (RQ.AUTHOR = SUSER) then return 1; end if; /* Проверки не пройдены - менять нельзя */ return 0; end QUERY_ACCESS_SIGN_MODIFY; /* Проверка возможности изменения запроса */ procedure QUERY_ACCESS_MODIFY ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ) is begin /* Получим признак возможности измнения */ if (QUERY_ACCESS_SIGN_MODIFY(NRN => NRN, SUSER => SUSER) = 0) then /* Менять нельзя */ P_EXCEPTION(0, 'У Вас нет прав доступа для измнения запроса.'); end if; end QUERY_ACCESS_MODIFY; /* Получение признака возможности просмотра запроса */ function QUERY_ACCESS_SIGN_VIEW ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ) return number -- Признак возможности просмотра запроса (0 - нет, 1 - да) is RQ P8PNL_QE_QUERY%rowtype; -- Проверяемая запись запроса begin /* Читаем запрос */ RQ := QUERY_GET(NRN => NRN); /* Смотреть можно только свой или публичный запрос */ if ((RQ.PBL = 1) or (RQ.AUTHOR = SUSER)) then return 1; end if; /* Проверки не пройдены - нельзя смотреть */ return 0; end QUERY_ACCESS_SIGN_VIEW; /* Проверка возможности просмотра запроса */ procedure QUERY_ACCESS_VIEW ( NRN in number, -- Рег. номер запроса SUSER in varchar2 -- Имя пользователя ) is begin /* Получим признак возможности просмотра */ if (QUERY_ACCESS_SIGN_VIEW(NRN => NRN, SUSER => SUSER) = 0) then /* Смотреть нельзя */ P_EXCEPTION(0, 'У Вас нет прав доступа для просмотра запроса.'); end if; end QUERY_ACCESS_VIEW; /* Проверка атрибутов запроса */ procedure QUERY_CHECK ( SCODE in varchar2, -- Мнемокод SNAME in varchar2 -- Наименование ) is begin /* Мнемокод должен быть задан */ if (SCODE is null) then P_EXCEPTION(0, 'Не задан мнемокод запроса.'); end if; /* Наименование должно быть задано */ if (SNAME is null) then P_EXCEPTION(0, 'Не задано наименование запроса.'); end if; end QUERY_CHECK; /* Синхронизация даты изменения запроса с текущим временем */ procedure QUERY_CH_DATE_SYNC ( NRN in number -- Рег. номер запроса ) is begin /* Установим текущую дату изменения */ update P8PNL_QE_QUERY T set T.CH_DATE = sysdate where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; end QUERY_CH_DATE_SYNC; /* Добавление запроса */ procedure QUERY_INSERT ( SCODE in varchar2, -- Мнемокод SNAME in varchar2, -- Наименование NRN out number -- Рег. номер добавленного запроса ) is begin /* Проверим параметры */ QUERY_CHECK(SCODE => SCODE, SNAME => SNAME); /* Формируем рег. номер */ NRN := GEN_ID(); /* Добавляем данные */ insert into P8PNL_QE_QUERY (RN, CODE, name, AUTHOR, CH_DATE, READY, PBL) values (NRN, SCODE, SNAME, UTILIZER(), sysdate, 0, 0); end QUERY_INSERT; /* Исправление запроса */ procedure QUERY_UPDATE ( NRN in number, -- Рег. номер запроса SCODE in varchar2, -- Мнемокод SNAME in varchar2 -- Наименование ) is begin /* Проверим параметры */ QUERY_CHECK(SCODE => SCODE, SNAME => SNAME); /* Изменяем данные */ update P8PNL_QE_QUERY T set T.CODE = SCODE, T.NAME = SNAME where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; /* Обновим дату изменения запроса */ QUERY_CH_DATE_SYNC(NRN => NRN); end QUERY_UPDATE; /* Удаление запроса */ procedure QUERY_DELETE ( NRN in number -- Рег. номер запроса ) is begin /* Удаляем запись */ delete from P8PNL_QE_QUERY T where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; end QUERY_DELETE; /* Сериализация сущностей запроса */ function QUERY_ENTS_TO_XML ( RENTS in TENTS -- Коллекция сущностей ) return clob -- XML-описание is CRES clob; -- Буфер для результата begin /* Если сущности есть */ if ((RENTS is not null) and (RENTS.COUNT > 0)) then /* Начинаем формирование XML */ PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_); /* Добавляем сущности */ TENTS_TO_XML(RENTS => RENTS); /* Сериализуем */ CRES := PKG_XFAST.SERIALIZE_TO_CLOB(); /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); else CRES := null; end if; /* Возвращаем полученное */ return CRES; exception when others then /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end QUERY_ENTS_TO_XML; /* Десериализация сущностей запроса */ function QUERY_ENTS_FROM_XML ( CXML in clob -- XML-описание коллекции сущностей запроса ) return TENTS -- Коллекция сущностей is RENTS TENTS; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа begin /* Инициализируем результат */ RENTS := TENTS(); /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считываем узел сущностей */ XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_ENTS); /* Десериализуем его */ RENTS := TENTS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => XNODE)); /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём сформированное */ return RENTS; end QUERY_ENTS_FROM_XML; /* Сериализация связей запроса */ function QUERY_RLS_TO_XML ( RRLS in TRLS -- Коллекция связей ) return clob -- XML-описание is CRES clob; -- Буфер для результата begin /* Если связи есть */ if ((RRLS is not null) and (RRLS.COUNT > 0)) then /* Начинаем формирование XML */ PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_); /* Добавляем связи */ TRLS_TO_XML(RRLS => RRLS); /* Сериализуем */ CRES := PKG_XFAST.SERIALIZE_TO_CLOB(); /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); else CRES := null; end if; /* Возвращаем полученное */ return CRES; exception when others then /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end QUERY_RLS_TO_XML; /* Десериализация связей запроса */ function QUERY_RLS_FROM_XML ( CXML in clob -- XML-описание коллекции связей запроса ) return TRLS -- Коллекция связей is RRLS TRLS; -- Буфер для результата XDOC PKG_XPATH.TDOCUMENT; -- Документ XML XROOT PKG_XPATH.TNODE; -- Корень документа XML XNODE PKG_XPATH.TNODE; -- Буфер узла документа begin /* Инициализируем результат */ RRLS := TRLS(); /* Если данные есть */ if (CXML is not null) then begin /* Разбираем XML */ XDOC := PKG_XPATH.PARSE_FROM_CLOB(LCXML => CXML); /* Считываем корневой узел */ XROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT => XDOC); /* Считываем узел связей */ XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_RLS); /* Десериализуем его */ RRLS := TRLS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => XNODE)); /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); exception when others then /* Освободим документ */ PKG_XPATH.FREE(RDOCUMENT => XDOC); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end; end if; /* Вернём сформированное */ return RRLS; end QUERY_RLS_FROM_XML; /* Сериализация запроса */ function QUERY_TO_XML ( NRN in number -- Рег. номер запроса ) return clob -- XML-описание is RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса CRES clob; -- Буфер для сериализации begin /* Читаем запрос */ RQ := QUERY_GET(NRN => NRN); /* Начинаем формирование XML */ PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_, BALINE => true, BINDENT => true); /* Открываем корень */ PKG_XFAST.DOWN_NODE(SNAME => STAG_DATA); /* Параметры */ if (RQ.OPTS is not null) then null; end if; /* Сущности (можно использовать просто PKG_XFAST.VALUE_XML и сразу отдать готовый XML из RQ.ENTS, но это приводит к формированию некорректного документа с лишней ">" между группами) */ if (RQ.ENTS is not null) then TENTS_TO_XML(RENTS => QUERY_ENTS_FROM_XML(CXML => RQ.ENTS)); end if; /* Связи (можно использовать просто PKG_XFAST.VALUE_XML и сразу отдать готовый XML из RQ.RLS, но это приводит к формированию некорректного документа с лишней ">" между группами) */ if (RQ.RLS is not null) then TRLS_TO_XML(RRLS => QUERY_RLS_FROM_XML(CXML => RQ.RLS)); end if; /* Закрываем корень */ PKG_XFAST.UP(); /* Сериализуем */ CRES := PKG_XFAST.SERIALIZE_TO_CLOB(); /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Возвращаем результат */ return CRES; exception when others then /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end QUERY_TO_XML; /* Формирование списка запросов */ function QUERY_LIST_GET ( SUSER in varchar2 -- Имя пользователя ) return clob -- Список запросов is CRES clob; -- Буфер для сериализации begin /* Начинаем формирование XML */ PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_, BALINE => true, BINDENT => true); /* Открываем корень */ PKG_XFAST.DOWN_NODE(SNAME => STAG_DATA); /* Открываем список запросов */ PKG_XFAST.DOWN_NODE(SNAME => STAG_QUERIES); /* Обходим запросы - данного пользователя и публичные */ for C in (select T.RN NRN, T.CODE SCODE, T.NAME SNAME, UL.NAME SAUTHOR, TO_CHAR(T.CH_DATE, 'dd.mm.yyyy hh24:mi:ss') SCH_DATE, T.READY NREADY, T.PBL NPBL, QUERY_ACCESS_SIGN_MODIFY(T.RN, SUSER) NMODIFY from P8PNL_QE_QUERY T, USERLIST UL where T.AUTHOR = UL.AUTHID and QUERY_ACCESS_SIGN_VIEW(T.RN, SUSER) = 1 order by T.CODE) loop /* Открываем описание запроса */ PKG_XFAST.DOWN_NODE(SNAME => STAG_QUERY); /* Запрос */ PKG_XFAST.ATTR(SNAME => SATTR_RN, NVALUE => C.NRN); PKG_XFAST.ATTR(SNAME => SATTR_CODE, SVALUE => C.SCODE); PKG_XFAST.ATTR(SNAME => SATTR_NAME, SVALUE => C.SNAME); PKG_XFAST.ATTR(SNAME => SATTR_AUTHOR, SVALUE => C.SAUTHOR); PKG_XFAST.ATTR(SNAME => SATTR_CH_DATE, SVALUE => C.SCH_DATE); PKG_XFAST.ATTR(SNAME => SATTR_READY, NVALUE => C.NREADY); PKG_XFAST.ATTR(SNAME => SATTR_PBL, NVALUE => C.NPBL); PKG_XFAST.ATTR(SNAME => SATTR_MODIFY, NVALUE => C.NMODIFY); /* Закрываем описание запроса */ PKG_XFAST.UP(); end loop; /* Закрываем список запросов */ PKG_XFAST.UP(); /* Закрываем корень */ PKG_XFAST.UP(); /* Сериализуем */ CRES := PKG_XFAST.SERIALIZE_TO_CLOB(); /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Возвращаем результат */ return CRES; exception when others then /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end QUERY_LIST_GET; /* Получение описания запроса */ function QUERY_DESC_GET ( NRN in number -- Рег. номер запроса ) return clob -- XML-описание is begin /* Сериализуем запрос */ return QUERY_TO_XML(NRN => NRN); end QUERY_DESC_GET; /* Чтение сущностей запроса */ function QUERY_ENTS_GET ( CENTS in clob -- Сериализованное описание сущностей ) return TENTS -- Коллекция сущностей is begin /* Десериализуем */ return QUERY_ENTS_FROM_XML(CXML => CENTS); end QUERY_ENTS_GET; /* Запись сущностей запроса */ procedure QUERY_ENTS_SET ( NRN in number, -- Рег. номер запроса RENTS in TENTS -- Коллекция сущностей ) is CENTS clob; -- Буфер для сериализации begin /* Сериализуем полученную коллекцию сущностей */ CENTS := QUERY_ENTS_TO_XML(RENTS => RENTS); /* Сохраним её */ update P8PNL_QE_QUERY T set T.ENTS = CENTS where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; /* Обновим дату изменения запроса */ QUERY_CH_DATE_SYNC(NRN => NRN); end QUERY_ENTS_SET; /* Получение состава атрибутов сущности */ procedure QUERY_ENT_ATTRS_GET ( NRN in number, -- Рег. номер запроса SID in varchar2, -- Идентификатор сущности COUT out clob -- Сериализованное описание атрибутов сущности ) is RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса NENT_INDEX PKG_STD.TNUMBER; -- Индекс изменяемой сущности в коллекции RENTS TENTS; -- Коллекция существующих сущностей RENT TENT; -- Изменяемая сущность RATTRS TATTRS; -- Коллекция атрибутов изменяемой сущности begin /* Читаем запись запроса */ RQ := QUERY_GET(NRN => NRN); /* Читаем существующие сущности */ RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS); /* Читаем изменяемую сущность */ NENT_INDEX := TENTS_INDEX_BY_ID(RENTS => RENTS, SID => SID); if (NENT_INDEX is not null) then RENT := RENTS(NENT_INDEX); else P_EXCEPTION(0, 'Сущность с идентификатором "%s" не определена.', COALESCE(SID, '<НЕ УКАЗАН>')); end if; /* Получим полный набор атрибутов сущности */ RATTRS := TATTRS_MAKE(RENT => RENT); /* Начинаем формирование XML */ PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_, BALINE => true, BINDENT => true); /* Открываем корень */ PKG_XFAST.DOWN_NODE(SNAME => STAG_DATA); /* Формируем описание тарибутов */ TATTRS_TO_XML(RATTRS => RATTRS); /* Закрываем корень */ PKG_XFAST.UP(); /* Сериализуем */ COUT := PKG_XFAST.SERIALIZE_TO_CLOB(); /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); exception when others then /* Завершаем формирование XML */ PKG_XFAST.EPILOGUE(); /* Вернем ошибку */ PKG_STATE.DIAGNOSTICS_STACKED(); P_EXCEPTION(0, PKG_STATE.SQL_ERRM()); end QUERY_ENT_ATTRS_GET; /* Чтение связей запроса */ function QUERY_RLS_GET ( CRLS in clob -- Сериализованное описание связей ) return TRLS -- Коллекция связей is begin /* Десериализуем */ return QUERY_RLS_FROM_XML(CXML => CRLS); end QUERY_RLS_GET; /* Запись связей запроса */ procedure QUERY_RLS_SET ( NRN in number, -- Рег. номер запроса RRLS in TRLS -- Коллекция связей ) is CRLS clob; -- Буфер для сериализации begin /* Сериализуем полученную коллекцию связей */ CRLS := QUERY_RLS_TO_XML(RRLS => RRLS); /* Сохраним её */ update P8PNL_QE_QUERY T set T.RLS = CRLS where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; /* Обновим дату изменения запроса */ QUERY_CH_DATE_SYNC(NRN => NRN); end QUERY_RLS_SET; /* Установка признака "готовности" запроса */ procedure QUERY_READY_SET ( NRN in number, -- Рег. номер запроса NREADY in number -- Флаг готовности к использованию (0 - нет, 1 - да) ) is begin /* Проверим параметры */ if (NREADY is null) then P_EXCEPTION(0, 'Не задано значение признака готовности запроса к использованию.'); end if; if (NREADY not in (0, 1)) then P_EXCEPTION(0, 'Значение признака готовности запроса к использованию задано некорректно (ожидалось 0 или 1).'); end if; /* Установим флаг готовности к использованию */ update P8PNL_QE_QUERY T set T.READY = NREADY where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; /* Обновим дату изменения запроса */ QUERY_CH_DATE_SYNC(NRN => NRN); end QUERY_READY_SET; /* Установка признака "публичности" запроса */ procedure QUERY_PBL_SET ( NRN in number, -- Рег. номер запроса NPBL in number -- Флаг публичности (0 - приватный, 1 - публичный) ) is begin /* Проверим параметры */ if (NPBL is null) then P_EXCEPTION(0, 'Не задано значение признака публичности запроса.'); end if; if (NPBL not in (0, 1)) then P_EXCEPTION(0, 'Значение признака публичноти запроса задано некорректно (ожидалось 0 или 1).'); end if; /* Установим флаг публичности */ update P8PNL_QE_QUERY T set T.PBL = NPBL where T.RN = NRN; /* Контроль изменения данных */ if (sql%notfound) then PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); end if; /* Обновим дату изменения запроса */ QUERY_CH_DATE_SYNC(NRN => NRN); end QUERY_PBL_SET; end PKG_P8PANELS_QE_BASE; /