forked from CITKParus/P8-Panels
		
	
		
			
				
	
	
		
			2324 lines
		
	
	
		
			104 KiB
		
	
	
	
		
			SQL
		
	
	
	
	
	
			
		
		
	
	
			2324 lines
		
	
	
		
			104 KiB
		
	
	
	
		
			SQL
		
	
	
	
	
	
| create or replace package PKG_P8PANELS_QE_BASE as
 | ||
| 
 | ||
|   /* Типы данных - Аргумент */
 | ||
|   type TARG is record
 | ||
|   (
 | ||
|     SNAME                   PKG_STD.TSTRING, -- Имя
 | ||
|     STITLE                  PKG_STD.TSTRING, -- Заголовок
 | ||
|     NDATA_TYPE              PKG_STD.TNUMBER, -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
 | ||
|     NMANDATORY              PKG_STD.TNUMBER  -- Флаг обязательности (1 - да, 0 - нет)
 | ||
|   );
 | ||
|   
 | ||
|   /* Типы данных - Коллекция аргументов */
 | ||
|   type TARGS is table of TARG;
 | ||
|   
 | ||
|   /* Типы данных - Настройка запроса */
 | ||
|   type TOPT is record
 | ||
|   (
 | ||
|     RARGS                   TARGS,          -- Аргументы
 | ||
|     SCOND                   PKG_STD.TSTRING -- Условия отбора
 | ||
|   );
 | ||
| 
 | ||
|   /* Типы данных - Атрибут сущности */
 | ||
|   type TATTR is record
 | ||
|   (
 | ||
|     SID                     PKG_STD.TSTRING, -- Уникальный идентификатор в запросе
 | ||
|     SPARENT_ENTITY          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 TARGS_INDEX_BY_NAME
 | ||
|   (
 | ||
|     RARGS                   in TARGS,   -- Коллекция аргументов
 | ||
|     SNAME                   in varchar2 -- Искомое имя
 | ||
|   ) return                  number;     -- Индекс найденного аргумента (null - если не найдено)
 | ||
|   
 | ||
|   /* Добавление аргумента в коллекцию */
 | ||
|   procedure TARGS_ADD
 | ||
|   (
 | ||
|     RARGS                   in out nocopy TARGS, -- Изменяемая коллекция
 | ||
|     SNAME                   in varchar2,         -- Имя
 | ||
|     STITLE                  in varchar2,         -- Заголовок
 | ||
|     NDATA_TYPE              in number,           -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
 | ||
|     NMANDATORY              in number            -- Флаг обязательности (1 - да, 0 - нет)
 | ||
|   );
 | ||
|   
 | ||
|   /* Изменение аргумента в коллекции */
 | ||
|   procedure TARGS_EDIT
 | ||
|   (
 | ||
|     RARGS                   in out nocopy TARGS, -- Изменяемая коллекция
 | ||
|     NINDEX                  in number,           -- Индекс изменяемого аргумента
 | ||
|     SNAME                   in varchar2,         -- Имя
 | ||
|     STITLE                  in varchar2,         -- Заголовок
 | ||
|     NDATA_TYPE              in number,           -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
 | ||
|     NMANDATORY              in number            -- Флаг обязательности (1 - да, 0 - нет)
 | ||
|   );
 | ||
|   
 | ||
|   /* Удаление аргумента из коллекции */
 | ||
|   procedure TARGS_REMOVE
 | ||
|   (
 | ||
|     RARGS                   in out nocopy TARGS, -- Изменяемая коллекция
 | ||
|     SNAME                   in varchar2          -- Имя удаляемого аргумента
 | ||
|   );
 | ||
|   
 | ||
|   /* Поиск индекса сущности по идентификатору */
 | ||
|   function TENTS_INDEX_BY_ID
 | ||
|   (
 | ||
|     RENTS                   in TENTS,   -- Коллекция сущностей
 | ||
|     SID                     in varchar2 -- Искомый идентификатор
 | ||
|   ) return                  number;     -- Индекс найденной сущности (null - если не найдено)
 | ||
|   
 | ||
|   /* Добавление сущности в коллекцию */
 | ||
|   procedure TENTS_ADD
 | ||
|   (
 | ||
|     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_ADD
 | ||
|   (
 | ||
|     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 -- Имя пользователя
 | ||
|   );
 | ||
| 
 | ||
|   /* Формирование описания запроса */
 | ||
|   function QUERY
 | ||
|   (
 | ||
|     NRN                     in number   -- Рег. номер запроса
 | ||
|   ) return                  clob;       -- XML-описание
 | ||
| 
 | ||
|   /* Формирование списка запросов */
 | ||
|   function QUERY_LIST
 | ||
|   (
 | ||
|     SUSER                   in varchar2 -- Имя пользователя
 | ||
|   ) return                  clob;       -- Список запросов
 | ||
|  
 | ||
|   /* Добавление запроса */
 | ||
|   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_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 - публичный)
 | ||
|   );
 | ||
| 
 | ||
|   /* Чтение настройки запроса */
 | ||
|   function QUERY_OPT_GET
 | ||
|   (
 | ||
|     COPT                    in clob     -- Сериализованное описание настройки запроса
 | ||
|   ) return                  TOPT;       -- Настройка запроса
 | ||
| 
 | ||
|   /* Запись настройки запроса */
 | ||
|   procedure QUERY_OPT_SET
 | ||
|   (
 | ||
|     NRN                     in number,  -- Рег. номер запроса
 | ||
|     ROPT                    in TOPT     -- Настройка запроса
 | ||
|   );
 | ||
| 
 | ||
| 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_ARGS                 constant PKG_STD.TSTRING := 'XARGS';    -- Аргументы запроса
 | ||
|   STAG_ARG                  constant PKG_STD.TSTRING := 'XARG';     -- Аргумент запроса
 | ||
|   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_OPT                  constant PKG_STD.TSTRING := 'XOPT';     -- Настройка запроса
 | ||
|   STAG_COND                 constant PKG_STD.TSTRING := 'XCOND';    -- Условия запроса
 | ||
| 
 | ||
|   /* Константы - Атрибуты для сериализации */
 | ||
|   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_MANDATORY           constant PKG_STD.TSTRING := 'mandatory';    -- Обязательность
 | ||
|   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';         -- Отображение в запросе
 | ||
|   SATTR_PARENT_ENTITY       constant PKG_STD.TSTRING := 'parentEntity'; -- Идентификатор родительской сущности
 | ||
|   
 | ||
|   /* Константы - зарезервированные имена рагументов */
 | ||
|   SARG_NAME_PAGE            constant PKG_STD.TSTRING := 'NPAGE';      -- Номер страницы
 | ||
|   SARG_NAME_PAGE_SIZE       constant PKG_STD.TSTRING := 'NPAGE_SIZE'; -- Размер страницы (записей)
 | ||
|   
 | ||
|   /* Получение заголовка представления из метаданных */
 | ||
|   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 TARG_MAKE
 | ||
|   (
 | ||
|     SNAME                   in varchar2, -- Имя
 | ||
|     STITLE                  in varchar2, -- Заголовок
 | ||
|     NDATA_TYPE              in number,   -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
 | ||
|     NMANDATORY              in number    -- Флаг обязательности (1 - да, 0 - нет)
 | ||
|   ) return                  TARG         -- Описание аргумента
 | ||
|   is
 | ||
|     RARG                    TARG;        -- Буфер для результата
 | ||
|   begin
 | ||
|     /* Проверим имя */
 | ||
|     if (SNAME is null) then
 | ||
|       P_EXCEPTION(0, 'Имя аргумента не указано.');
 | ||
|     end if;
 | ||
|     for C in (select null from DUAL where not REGEXP_LIKE(SNAME, '^[A-z0-9_]+$'))
 | ||
|     loop
 | ||
|       P_EXCEPTION(0,
 | ||
|                   'Имя аргумента содержит недопустимые символы (разрешены латинские буквы, цифры и символ нижнего подчеркивания).');
 | ||
|     end loop;
 | ||
|     if (UPPER(SNAME) in (UPPER(SARG_NAME_PAGE), UPPER(SARG_NAME_PAGE_SIZE))) then
 | ||
|       P_EXCEPTION(0, 'Это имя аргумента зарезервировано Системой.');
 | ||
|     end if;
 | ||
|     /* Проверим заголовок */
 | ||
|     if (STITLE is null) then
 | ||
|       P_EXCEPTION(0, 'Не указан заголовок аргумента.');
 | ||
|     end if;
 | ||
|     /* Проверим корректность типа сущности */
 | ||
|     if (NDATA_TYPE is null) then
 | ||
|       P_EXCEPTION(0, 'Не указан тип данных аргумента.');
 | ||
|     end if;
 | ||
|     if (NDATA_TYPE not in (PKG_STD.DATA_TYPE_STR, PKG_STD.DATA_TYPE_NUM, PKG_STD.DATA_TYPE_DATE)) then
 | ||
|       P_EXCEPTION(0,
 | ||
|                   'Аргументы типа "%s" не поддерживаются.',
 | ||
|                   COALESCE(TO_CHAR(NDATA_TYPE), '<НЕ УКАЗАН>'));
 | ||
|     end if;
 | ||
|     /* Проверим корректность флага обязательности */
 | ||
|     if (NMANDATORY is null) then
 | ||
|       P_EXCEPTION(0, 'Не указан признак обязательности аргумента.');
 | ||
|     end if;
 | ||
|     if (NMANDATORY not in (0, 1)) then
 | ||
|       P_EXCEPTION(0,
 | ||
|                   'Некорректно указан признак обязательности аргумента.');
 | ||
|     end if;
 | ||
|     /* Собираем аргумент */
 | ||
|     RARG.SNAME      := UPPER(SNAME);
 | ||
|     RARG.STITLE     := STITLE;
 | ||
|     RARG.NDATA_TYPE := NDATA_TYPE;
 | ||
|     RARG.NMANDATORY := NMANDATORY;
 | ||
|     /* Вернем полученное */
 | ||
|     return RARG;
 | ||
|   end TARG_MAKE;
 | ||
|   
 | ||
|   /* Сериализация аргумента */
 | ||
|   procedure TARG_TO_XML
 | ||
|   (
 | ||
|     RARG                    in TARG     -- Аргумент
 | ||
|   )
 | ||
|   is    
 | ||
|   begin
 | ||
|     /* Открываем описание аргумента */
 | ||
|     PKG_XFAST.DOWN_NODE(SNAME => STAG_ARG);
 | ||
|     /* Аргумент */
 | ||
|     PKG_XFAST.ATTR(SNAME => SATTR_NAME, SVALUE => RARG.SNAME);
 | ||
|     PKG_XFAST.ATTR(SNAME => SATTR_TITLE, SVALUE => RARG.STITLE);
 | ||
|     PKG_XFAST.ATTR(SNAME => SATTR_DATA_TYPE, NVALUE => RARG.NDATA_TYPE);
 | ||
|     PKG_XFAST.ATTR(SNAME => SATTR_MANDATORY, NVALUE => RARG.NMANDATORY);
 | ||
|     /* Закрываем описание аргумента */
 | ||
|     PKG_XFAST.UP();
 | ||
|   end TARG_TO_XML;
 | ||
|   
 | ||
|   /* Десериализация аргумента */
 | ||
|   function TARG_FROM_XML
 | ||
|   (
 | ||
|     CXML                    in clob              -- XML-описание аргумента
 | ||
|   ) return                  TARG                 -- Аргумент
 | ||
|   is
 | ||
|     RRES                    TARG;                -- Буфер для результата
 | ||
|     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_ARG);
 | ||
|         /* Получаем значения */
 | ||
|         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.NMANDATORY := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_MANDATORY);
 | ||
|         /* Освободим документ */
 | ||
|         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 TARG_FROM_XML;
 | ||
|   
 | ||
|   /* Поиск индекса аргумента по имени */
 | ||
|   function TARGS_INDEX_BY_NAME
 | ||
|   (
 | ||
|     RARGS                   in TARGS,   -- Коллекция аргументов
 | ||
|     SNAME                   in varchar2 -- Искомое имя
 | ||
|   ) return                  number      -- Индекс найденного аргумента (null - если не найдено)
 | ||
|   is
 | ||
|   begin
 | ||
|     /* Обходим коллекцию */
 | ||
|     if ((RARGS is not null) and (RARGS.COUNT > 0)) then
 | ||
|       for I in RARGS.FIRST .. RARGS.LAST
 | ||
|       loop
 | ||
|         begin
 | ||
|           /* Возвращаем найденный индекс */
 | ||
|           if (RARGS(I).SNAME = SNAME) then
 | ||
|             return I;
 | ||
|           end if;
 | ||
|         exception
 | ||
|           when NO_DATA_FOUND then
 | ||
|             null;
 | ||
|         end;
 | ||
|       end loop;
 | ||
|     end if;
 | ||
|     /* Ничего не нашли */
 | ||
|     return null;
 | ||
|   end TARGS_INDEX_BY_NAME;
 | ||
|   
 | ||
|   /* Добавление аргумента в коллекцию */
 | ||
|   procedure TARGS_ADD
 | ||
|   (
 | ||
|     RARGS                   in out nocopy TARGS, -- Изменяемая коллекция
 | ||
|     SNAME                   in varchar2,         -- Имя
 | ||
|     STITLE                  in varchar2,         -- Заголовок
 | ||
|     NDATA_TYPE              in number,           -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
 | ||
|     NMANDATORY              in number            -- Флаг обязательности (1 - да, 0 - нет)
 | ||
|   )
 | ||
|   is
 | ||
|     RARG                    TARG;                -- Добавляемый аргумент
 | ||
|   begin
 | ||
|     /* Инициализируем коллекцию если необходимо */
 | ||
|     if (RARGS is null) then
 | ||
|       RARGS := TARGS();
 | ||
|     end if;
 | ||
|     /* Проверим уникальность имени */
 | ||
|     if ((SNAME is not null) and (TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => SNAME) is not null)) then
 | ||
|       P_EXCEPTION(0, 'Аргумент с именем "%s" уже существует.', SNAME);
 | ||
|     end if;
 | ||
|     /* Формируем аргумент */
 | ||
|     RARG := TARG_MAKE(SNAME => SNAME, STITLE => STITLE, NDATA_TYPE => NDATA_TYPE, NMANDATORY => NMANDATORY);
 | ||
|     /* Добавляем его в коллекцию */
 | ||
|     RARGS.EXTEND();
 | ||
|     RARGS(RARGS.LAST) := RARG;
 | ||
|   end TARGS_ADD;
 | ||
|   
 | ||
|   /* Изменение аргумента в коллекции */
 | ||
|   procedure TARGS_EDIT
 | ||
|   (
 | ||
|     RARGS                   in out nocopy TARGS, -- Изменяемая коллекция
 | ||
|     NINDEX                  in number,           -- Индекс изменяемого аргумента
 | ||
|     SNAME                   in varchar2,         -- Имя
 | ||
|     STITLE                  in varchar2,         -- Заголовок
 | ||
|     NDATA_TYPE              in number,           -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
 | ||
|     NMANDATORY              in number            -- Флаг обязательности (1 - да, 0 - нет)
 | ||
|   )
 | ||
|   is
 | ||
|     RARG                    TARG;                -- Добавляемый аргумент
 | ||
|   begin
 | ||
|     /* Проверим коллекцию */
 | ||
|     if ((RARGS is null) or (RARGS.COUNT = 0)) then
 | ||
|       P_EXCEPTION(0,
 | ||
|                   'Коллекция аргументов пуста. Изменение аргумента невозможно.');
 | ||
|     end if;
 | ||
|     /* Проверим индекс изменяемого аргумента */
 | ||
|     if (NINDEX is null) then
 | ||
|       P_EXCEPTION(0, 'Не указан индекс изменяемого аргумента.');
 | ||
|     end if;
 | ||
|     /* Формируем аргумент */
 | ||
|     RARG := TARG_MAKE(SNAME => SNAME, STITLE => STITLE, NDATA_TYPE => NDATA_TYPE, NMANDATORY => NMANDATORY);
 | ||
|     /* Обновляем аргумент в коллекции */
 | ||
|     begin
 | ||
|       RARGS(NINDEX) := RARG;
 | ||
|     exception
 | ||
|       when others then
 | ||
|         P_EXCEPTION(0, 'Изменяемый аргумент отсутствует в коллекции.');
 | ||
|     end;
 | ||
|   end TARGS_EDIT;
 | ||
|   
 | ||
|   /* Удаление аргумента из коллекции */
 | ||
|   procedure TARGS_REMOVE
 | ||
|   (
 | ||
|     RARGS                   in out nocopy TARGS, -- Изменяемая коллекция
 | ||
|     SNAME                   in varchar2          -- Имя удаляемого аргумента
 | ||
|   )
 | ||
|   is
 | ||
|     NIND                    PKG_STD.TNUMBER;     -- Индекс аргумента коллекции
 | ||
|   begin
 | ||
|     /* Найдем индекс аргумента в коллекции */
 | ||
|     NIND := TARGS_INDEX_BY_NAME(RARGS => RARGS, SNAME => SNAME);
 | ||
|     /* Удалим его, если нашли */
 | ||
|     if (NIND is not null) then
 | ||
|       RARGS.DELETE(NIND);
 | ||
|     end if;
 | ||
|   end TARGS_REMOVE;  
 | ||
|   
 | ||
|   /* Сериализация коллекции аргументов */
 | ||
|   procedure TARGS_TO_XML
 | ||
|   (
 | ||
|     RARGS                   in TARGS    -- Коллекция аргументов
 | ||
|   )
 | ||
|   is
 | ||
|   begin
 | ||
|     /* Открываем описание аргументов */
 | ||
|     PKG_XFAST.DOWN_NODE(SNAME => STAG_ARGS);
 | ||
|     /* Обходим аргументы из коллекции */
 | ||
|     if ((RARGS is not null) and (RARGS.COUNT > 0)) then
 | ||
|       for I in RARGS.FIRST .. RARGS.LAST
 | ||
|       loop
 | ||
|         begin
 | ||
|           /* Добавляем описание аргумента */
 | ||
|           TARG_TO_XML(RARG => RARGS(I));
 | ||
|         exception
 | ||
|           when NO_DATA_FOUND then
 | ||
|             null;
 | ||
|         end;
 | ||
|       end loop;
 | ||
|     end if;
 | ||
|     /* Закрываем описание аргумента */
 | ||
|     PKG_XFAST.UP();
 | ||
|   end TARGS_TO_XML;
 | ||
|   
 | ||
|   /* Десериализация коллекции аргументов */
 | ||
|   function TARGS_FROM_XML
 | ||
|   (
 | ||
|     CXML                    in clob              -- XML-описание коллекции аргументов
 | ||
|   ) return                  TARGS                -- Коллекция аргументов
 | ||
|   is
 | ||
|     RRES                    TARGS;               -- Буфер для результата
 | ||
|     XDOC                    PKG_XPATH.TDOCUMENT; -- Документ XML
 | ||
|     XROOT                   PKG_XPATH.TNODE;     -- Корень документа XML
 | ||
|     XNODE                   PKG_XPATH.TNODE;     -- Буфер узла документа
 | ||
|     XNODES                  PKG_XPATH.TNODES;    -- Буфер коллекции узлов документа
 | ||
|   begin
 | ||
|     /* Инициализируем результат */
 | ||
|     RRES := TARGS();
 | ||
|     /* Если данные есть */
 | ||
|     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_ARGS || '/' || STAG_ARG);
 | ||
|         /* Цикл по списку аргументов */
 | ||
|         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) := TARG_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 TARGS_FROM_XML;
 | ||
|   
 | ||
|   /* Сериализация настройки */
 | ||
|   procedure TOPT_TO_XML
 | ||
|   (
 | ||
|     ROPT                    in TOPT     -- Настройка
 | ||
|   )
 | ||
|   is    
 | ||
|   begin
 | ||
|     /* Открываем описание настройки */
 | ||
|     PKG_XFAST.DOWN_NODE(SNAME => STAG_OPT);
 | ||
|     /* Аргументы */
 | ||
|     TARGS_TO_XML(RARGS => ROPT.RARGS);
 | ||
|     /* Условия отбора */
 | ||
|     PKG_XFAST.HERB(SNAME => STAG_COND, SVALUE => ROPT.SCOND);
 | ||
|     /* Закрываем описание настройки */
 | ||
|     PKG_XFAST.UP();
 | ||
|   end TOPT_TO_XML;
 | ||
|   
 | ||
|   /* Десериализация настройки */
 | ||
|   function TOPT_FROM_XML
 | ||
|   (
 | ||
|     CXML                    in clob              -- XML-описание настройки
 | ||
|   ) return                  TOPT                 -- Настройка
 | ||
|   is
 | ||
|     RRES                    TOPT;                -- Буфер для результата
 | ||
|     XDOC                    PKG_XPATH.TDOCUMENT; -- Документ XML
 | ||
|     XROOT                   PKG_XPATH.TNODE;     -- Корень документа XML
 | ||
|     XNODE                   PKG_XPATH.TNODE;     -- Буфер узла документа
 | ||
|   begin
 | ||
|     /* Инициализируем настройку */
 | ||
|     RRES.RARGS := TARGS();
 | ||
|     /* Если данные есть */
 | ||
|     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_OPT);
 | ||
|         /* Получаем значения */
 | ||
|         RRES.SCOND := PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => STAG_COND);
 | ||
|         RRES.RARGS := TARGS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XNODE,
 | ||
|                                                                                                         SPATTERN     => STAG_ARGS)));
 | ||
|         /* Освободим документ */
 | ||
|         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 TOPT_FROM_XML;
 | ||
|   
 | ||
|   /* Формирование идентификатора атрибута сущности */
 | ||
|   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_PARENT_ENTITY, SVALUE => RATTR.SPARENT_ENTITY);
 | ||
|     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.SPARENT_ENTITY := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_PARENT_ENTITY);
 | ||
|         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 is null) then
 | ||
|       P_EXCEPTION(0, 'Не указан тип сущности.');
 | ||
|     end if;
 | ||
|     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).SPARENT_ENTITY := RENT.SID;
 | ||
|             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 || '</' || STAG_ATTRS || '>';
 | ||
|     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 is null) then
 | ||
|       P_EXCEPTION(0, 'Не указан тип сущности.');
 | ||
|     end if;
 | ||
|     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_ADD
 | ||
|   (
 | ||
|     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_ADD;
 | ||
|   
 | ||
|   /* Удаление сущности из коллекции */
 | ||
|   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_ADD
 | ||
|   (
 | ||
|     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_ADD;
 | ||
|   
 | ||
|   /* Удаление связи из коллекции */
 | ||
|   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;
 | ||
|   
 | ||
|   /* Сериализация сущностей запроса */
 | ||
|   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_OPT_TO_XML
 | ||
|   (
 | ||
|     ROPT                    in TOPT     -- Настройка
 | ||
|   ) return                  clob        -- XML-описание
 | ||
|   is
 | ||
|     CRES                    clob;       -- Буфер для результата
 | ||
|   begin
 | ||
|     /* Начинаем формирование XML */
 | ||
|     PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_);
 | ||
|     /* Формируем XML настройки */
 | ||
|     TOPT_TO_XML(ROPT => ROPT);
 | ||
|     /* Сериализуем */
 | ||
|     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_OPT_TO_XML;
 | ||
|   
 | ||
|   /* Десериализация настройки запроса */
 | ||
|   function QUERY_OPT_FROM_XML
 | ||
|   (
 | ||
|     CXML                    in clob              -- XML-описание настройки запроса
 | ||
|   ) return                  TOPT                 -- Настройка
 | ||
|   is
 | ||
|     ROPT                    TOPT;                -- Буфер для результата
 | ||
|     XDOC                    PKG_XPATH.TDOCUMENT; -- Документ XML
 | ||
|     XROOT                   PKG_XPATH.TNODE;     -- Корень документа XML
 | ||
|     XNODE                   PKG_XPATH.TNODE;     -- Буфер узла документа
 | ||
|   begin
 | ||
|     /* Инициализируем результат */
 | ||
|     ROPT.RARGS := TARGS();
 | ||
|     /* Если данные есть */
 | ||
|     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_OPT);
 | ||
|         /* Десериализуем его */
 | ||
|         ROPT := TOPT_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 ROPT;
 | ||
|   end QUERY_OPT_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.OPT is not null) then
 | ||
|       TOPT_TO_XML(ROPT => QUERY_OPT_FROM_XML(CXML => RQ.OPT));
 | ||
|     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
 | ||
|   (
 | ||
|     NRN                     in number   -- Рег. номер запроса
 | ||
|   ) return                  clob        -- XML-описание
 | ||
|   is
 | ||
|   begin
 | ||
|     /* Сериализуем запрос */
 | ||
|     return QUERY_TO_XML(NRN => NRN);
 | ||
|   end QUERY;
 | ||
|   
 | ||
|   /* Формирование списка запросов */
 | ||
|   function QUERY_LIST
 | ||
|   (
 | ||
|     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;
 | ||
|   
 | ||
|   /* Добавление запроса */
 | ||
|   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_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;
 | ||
| 
 | ||
|   /* Чтение настройки запроса */
 | ||
|   function QUERY_OPT_GET
 | ||
|   (
 | ||
|     COPT                    in clob     -- Сериализованное описание настройки запроса
 | ||
|   ) return                  TOPT        -- Настройка запроса
 | ||
|   is
 | ||
|   begin
 | ||
|     /* Десериализуем */
 | ||
|     return QUERY_OPT_FROM_XML(CXML => COPT);
 | ||
|   end QUERY_OPT_GET;
 | ||
|   
 | ||
|   /* Запись настройки запроса */
 | ||
|   procedure QUERY_OPT_SET
 | ||
|   (
 | ||
|     NRN                     in number,  -- Рег. номер запроса
 | ||
|     ROPT                    in TOPT     -- Настройка запроса
 | ||
|   )
 | ||
|   is
 | ||
|     COPT                    clob;       -- Буфер для сериализации
 | ||
|   begin
 | ||
|     /* Сериализуем настройку */
 | ||
|     COPT := QUERY_OPT_TO_XML(ROPT => ROPT);
 | ||
|     /* Сохраним её */
 | ||
|     update P8PNL_QE_QUERY T set T.OPT = COPT 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_OPT_SET;
 | ||
|   
 | ||
| end PKG_P8PANELS_QE_BASE;
 | ||
| /
 |