P8-Panels/db/PKG_P8PANELS_QE_BASE.pck

1742 lines
77 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

create or replace package PKG_P8PANELS_QE_BASE as
/* Константы - Типы сущностей */
SENT_TYPE_TABLE constant PKG_STD.TSTRING := 'TABLE'; -- Таблица
SENT_TYPE_VIEW constant PKG_STD.TSTRING := 'VIEW'; -- Представление
/* Типы данных - Атрибут сущности */
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;
/* Поиск индекса сущности по идентификатору */
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 -- Координата по оси ординат
);
/* Формирование коллекции связей по источнику/приёмнику */
function TRLS_LIST_BY_ST
(
RRLS in TRLS, -- Коллекция связей
SSOURCE_TARGET in varchar2, -- Идентификатор источника/приёмкника
NLIST_TYPE in number -- Тип формирования коллекции (0 - по источнику, 1 - по приёмнику
) return TRLS; -- Сформированная коллекция
/* Добавление связи в коллекцию */
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 -- Идентификатор удялемой связи
);
/* Считывание записи запроса */
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
/* Константы - Теги для сериализации */
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_SHOW);
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)) 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;
/* Формирование идентификатора сущности */
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_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;
/