diff --git a/db/PKG_P8PANELS_QE.pck b/db/PKG_P8PANELS_QE.pck index dca717c..6fb9d72 100644 --- a/db/PKG_P8PANELS_QE.pck +++ b/db/PKG_P8PANELS_QE.pck @@ -72,7 +72,7 @@ create or replace package PKG_P8PANELS_QE as ( NRN in number, -- Рег. номер запроса SID in varchar2, -- Идентификатор сущности - CATTRS in clob -- Сериализованное описание атрибутов сущности + CATTRS in clob -- Сериализованное описание атрибутов сущности (BASE64 XML) ); /* Добавление связи в запрос */ @@ -208,7 +208,6 @@ create or replace package body PKG_P8PANELS_QE as RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей RENT PKG_P8PANELS_QE_BASE.TENT; -- Удаляемая сущность RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей - RRLS_TMP PKG_P8PANELS_QE_BASE.TRLS; -- Буфер для коллекции удаляемых связей begin /* Провим права доступа */ PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); @@ -234,20 +233,8 @@ create or replace package body PKG_P8PANELS_QE as if ((RENT.RATTRS is not null) and (RENT.RATTRS.COUNT > 0)) then for I in RENT.RATTRS.FIRST .. RENT.RATTRS.LAST loop - /* Если атрибут есть в связях (как источник или как приёмник) */ - for J in 0 .. 1 - loop - RRLS_TMP := PKG_P8PANELS_QE_BASE.TRLS_LIST_BY_ST(RRLS => RRLS, - SSOURCE_TARGET => RENT.RATTRS(I).SID, - 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 - PKG_P8PANELS_QE_BASE.TRLS_REMOVE(RRLS => RRLS, SID => RRLS_TMP(K).SID); - end loop; - end if; - end loop; + /* Удаляем связи в которых он задействован */ + PKG_P8PANELS_QE_BASE.TRLS_CLEANUP_BY_ATTR(RRLS => RRLS, SATTR_ID => RENT.RATTRS(I).SID); end loop; end if; /* Сохраняем обновленный набор сущностей */ @@ -299,13 +286,57 @@ create or replace package body PKG_P8PANELS_QE as /* Установка состава атрибутов сущности */ procedure QUERY_ENT_ATTRS_SET ( - NRN in number, -- Рег. номер запроса - SID in varchar2, -- Идентификатор сущности - CATTRS in clob -- Сериализованное описание атрибутов сущности + NRN in number, -- Рег. номер запроса + SID in varchar2, -- Идентификатор сущности + CATTRS in clob -- Сериализованное описание атрибутов сущности (BASE64 XML) ) is + RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса + RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей + NENT_INDEX PKG_STD.TNUMBER; -- Индекс изменяемой сущности + RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов + RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей begin - null; + /* Провим права доступа */ + PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER()); + /* Читаем запись запроса */ + RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN); + /* Читаем существующие сущности */ + RENTS := PKG_P8PANELS_QE_BASE.QUERY_ENTS_GET(CENTS => RQ.ENTS); + /* Читаем свзяи */ + RRLS := PKG_P8PANELS_QE_BASE.QUERY_RLS_GET(CRLS => RQ.RLS); + /* Находим изменяемую сущность */ + NENT_INDEX := PKG_P8PANELS_QE_BASE.TENTS_INDEX_BY_ID(RENTS => RENTS, SID => SID); + if (NENT_INDEX is null) then + P_EXCEPTION(0, + 'Сущность с идентификатором "%s" в запросе "%s" не определена.', + COALESCE(SID, '<НЕ УКАЗАН>'), + TO_CHAR(NRN)); + end if; + /* Десериализуем новый набор атрибутов */ + RATTRS := PKG_P8PANELS_QE_BASE.TATTRS_FROM_XML_BASE64(CXML => CATTRS, + SCHARSET => PKG_CHARSET.CHARSET_UTF_(), + BADD_ROOT => true); + /* Сбросим текущие атрибуты сущности */ + RENTS(NENT_INDEX).RATTRS := PKG_P8PANELS_QE_BASE.TATTRS(); + /* Наполним полученными и зачистим связи */ + if (RATTRS is not null) and (RATTRS.COUNT > 0) then + for I in RATTRS.FIRST .. RATTRS.LAST + loop + /* Если атрибут используется - кладём в обновленную коллекцию атрибутов сущности */ + if (RATTRS(I).NUSE = 1) then + RENTS(NENT_INDEX).RATTRS.EXTEND(); + RENTS(NENT_INDEX).RATTRS(RENTS(NENT_INDEX).RATTRS.LAST) := RATTRS(I); + else + /* Атрибут не используется - необходимо очистись связи в которых он задействован */ + PKG_P8PANELS_QE_BASE.TRLS_CLEANUP_BY_ATTR(RRLS => RRLS, SATTR_ID => RATTRS(I).SID); + end if; + end loop; + end if; + /* Сохраняем обновленный набор сущностей */ + PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS); + /* Сохраняем обновленный набор связей */ + PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS); end QUERY_ENT_ATTRS_SET; /* Добавление связи в запрос */ diff --git a/db/PKG_P8PANELS_QE_BASE.pck b/db/PKG_P8PANELS_QE_BASE.pck index bb7b051..3108a63 100644 --- a/db/PKG_P8PANELS_QE_BASE.pck +++ b/db/PKG_P8PANELS_QE_BASE.pck @@ -1,9 +1,5 @@ create or replace package PKG_P8PANELS_QE_BASE as - /* Константы - Типы сущностей */ - SENT_TYPE_TABLE constant PKG_STD.TSTRING := 'TABLE'; -- Таблица - SENT_TYPE_VIEW constant PKG_STD.TSTRING := 'VIEW'; -- Представление - /* Типы данных - Атрибут сущности */ type TATTR is record ( @@ -46,6 +42,14 @@ create or replace package PKG_P8PANELS_QE_BASE as /* Типы данных - Коллекция отношений */ type TRLS is table of TRL; + /* Десериализация коллекции атрибутов сущности (из BASE64) */ + function TATTRS_FROM_XML_BASE64 + ( + CXML in clob, -- XML-описание коллекции атрибутов сущности (BASE64) + SCHARSET in varchar2, -- Кодировка, в которой XML-данные были упакованы в BASE64 + BADD_ROOT in boolean := false -- Флаг необходимости добавления корневого тэга (false - нет, true - да) + ) return TATTRS; -- Коллекция атрибутов сущности + /* Поиск индекса сущности по идентификатору */ function TENTS_INDEX_BY_ID ( @@ -77,14 +81,6 @@ create or replace package PKG_P8PANELS_QE_BASE as NY in number -- Координата по оси ординат ); - /* Формирование коллекции связей по источнику/приёмнику */ - function TRLS_LIST_BY_ST - ( - RRLS in TRLS, -- Коллекция связей - SSOURCE_TARGET in varchar2, -- Идентификатор источника/приёмкника - NLIST_TYPE in number -- Тип формирования коллекции (0 - по источнику, 1 - по приёмнику - ) return TRLS; -- Сформированная коллекция - /* Добавление связи в коллекцию */ procedure TRLS_APPEND ( @@ -100,6 +96,13 @@ create or replace package PKG_P8PANELS_QE_BASE as SID in varchar2 -- Идентификатор удялемой связи ); + /* Подчистка коллекции связей по атрибуту */ + procedure TRLS_CLEANUP_BY_ATTR + ( + RRLS in out nocopy TRLS, -- Изменяемая коллекция + SATTR_ID in varchar2 -- Идентификатор атрибута + ); + /* Считывание записи запроса */ function QUERY_GET ( @@ -220,6 +223,10 @@ 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'; -- Запросы @@ -378,7 +385,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as RRES.NDATA_TYPE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_DATA_TYPE); RRES.SAGG := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_AGG); RRES.SALIAS := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ALIAS); - RRES.NUSE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_SHOW); + RRES.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); @@ -453,8 +460,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as end if; /* Инициализируем результат */ RRES := TATTRS(); - /* Установим флаг инициализации */ - if ((RENT.RATTRS is null) or (RENT.RATTRS.COUNT = 0)) then + /* Установим флаг инициализации - в сущности нет атрибутов и нас просили ограничить количество */ + if (((RENT.RATTRS is null) or (RENT.RATTRS.COUNT = 0)) and (NCOUNT is not null)) then BINIT := true; end if; /* Если сущность это представление */ @@ -483,14 +490,14 @@ create or replace package body PKG_P8PANELS_QE_BASE as 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; end if; /* Ограничим объем коллекции если необходимо */ if (NCOUNT is not null) then @@ -576,6 +583,26 @@ create or replace package body PKG_P8PANELS_QE_BASE as return RRES; end TATTRS_FROM_XML; + /* Десериализация коллекции атрибутов сущности (из BASE64) */ + function TATTRS_FROM_XML_BASE64 + ( + CXML in clob, -- XML-описание коллекции атрибутов сущности (BASE64) + SCHARSET in varchar2, -- Кодировка, в которой XML-данные были упакованы в BASE64 + BADD_ROOT in boolean := false -- Флаг необходимости добавления корневого тэга (false - нет, true - да) + ) return TATTRS -- Коллекция атрибутов сущности + is + CTMP clob; -- Буфер для преобразований + begin + /* Избавимся от BASE64 */ + CTMP := BLOB2CLOB(LBDATA => BASE64_DECODE(LCSRCE => CXML), SCHARSET => SCHARSET); + /* Если надо - добавим корень */ + if (BADD_ROOT) then + CTMP := '<' || STAG_ATTRS || '>' || CTMP || ''; + end if; + /* Десериализуем */ + return TATTRS_FROM_XML(CXML => CTMP); + end TATTRS_FROM_XML_BASE64; + /* Формирование идентификатора сущности */ function TENT_ID_MAKE ( @@ -1063,6 +1090,29 @@ create or replace package body PKG_P8PANELS_QE_BASE as 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 (