ЦИТК-979 - Формирование списка атрибутов сущности (сервер)

This commit is contained in:
Mikhail Chechnev 2025-08-08 19:09:59 +03:00
parent 6ff99591e2
commit 836a3db5e2
2 changed files with 240 additions and 29 deletions

View File

@ -59,6 +59,22 @@ create or replace package PKG_P8PANELS_QE as
NY in number -- Координата по оси ординат
);
/* Получение состава атрибутов сущности */
procedure QUERY_ENT_ATTRS_GET
(
NRN in number, -- Рег. номер запроса
SID in varchar2, -- Идентификатор сущности
COUT out clob -- Сериализованное описание атрибутов сущности
);
/* Установка состава атрибутов сущности */
procedure QUERY_ENT_ATTRS_SET
(
NRN in number, -- Рег. номер запроса
SID in varchar2, -- Идентификатор сущности
CATTRS in clob -- Сериализованное описание атрибутов сущности
);
/* Добавление связи в запрос */
procedure QUERY_RL_ADD
(
@ -265,6 +281,33 @@ create or replace package body PKG_P8PANELS_QE as
end if;
end QUERY_ENT_POSITION_SET;
/* Получение состава атрибутов сущности */
procedure QUERY_ENT_ATTRS_GET
(
NRN in number, -- Рег. номер запроса
SID in varchar2, -- Идентификатор сущности
COUT out clob -- Сериализованное описание атрибутов сущности
)
is
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
/* Сформируем описание атрибутов */
PKG_P8PANELS_QE_BASE.QUERY_ENT_ATTRS_GET(NRN => NRN, SID => SID, COUT => COUT);
end QUERY_ENT_ATTRS_GET;
/* Установка состава атрибутов сущности */
procedure QUERY_ENT_ATTRS_SET
(
NRN in number, -- Рег. номер запроса
SID in varchar2, -- Идентификатор сущности
CATTRS in clob -- Сериализованное описание атрибутов сущности
)
is
begin
null;
end QUERY_ENT_ATTRS_SET;
/* Добавление связи в запрос */
procedure QUERY_RL_ADD
(

View File

@ -10,7 +10,11 @@ create or replace package PKG_P8PANELS_QE_BASE as
SID PKG_STD.TSTRING, -- Уникальный идентификатор в запросе
SNAME PKG_STD.TSTRING, -- Имя
STITLE PKG_STD.TSTRING, -- Заголовок
NDATA_TYPE PKG_STD.TNUMBER -- Тип данных (см. константы PKG_STD.DATA_TYPE_*)
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 - нет)
);
/* Типы данных - Коллекция атрибутов сущности */
@ -177,6 +181,14 @@ create or replace package PKG_P8PANELS_QE_BASE as
RENTS in TENTS -- Коллекция сущностей
);
/* Получение состава атрибутов сущности */
procedure QUERY_ENT_ATTRS_GET
(
NRN in number, -- Рег. номер запроса
SID in varchar2, -- Идентификатор сущности
COUT out clob -- Сериализованное описание атрибутов сущности
);
/* Чтение связей запроса */
function QUERY_RLS_GET
(
@ -238,6 +250,10 @@ create or replace package body PKG_P8PANELS_QE_BASE as
SATTR_Y constant PKG_STD.TSTRING := 'y'; -- Координата по Y
SATTR_SOURCE constant PKG_STD.TSTRING := 'source'; -- Источник
SATTR_TARGET constant PKG_STD.TSTRING := 'target'; -- Приёмник
SATTR_AGG constant PKG_STD.TSTRING := 'agg'; -- Агрегатная функция
SATTR_ALIAS constant PKG_STD.TSTRING := 'alias'; -- Псевдоним
SATTR_USE constant PKG_STD.TSTRING := 'use'; -- Применение в запросе
SATTR_SHOW constant PKG_STD.TSTRING := 'show'; -- Отображение в запросе
/* Получение заголовка представления из метаданных */
function DMSCLVIEWS_TITLE_GET
@ -328,6 +344,10 @@ create or replace package body PKG_P8PANELS_QE_BASE as
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;
@ -356,6 +376,10 @@ create or replace package body PKG_P8PANELS_QE_BASE as
RRES.SNAME := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_NAME);
RRES.STITLE := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_TITLE);
RRES.NDATA_TYPE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_DATA_TYPE);
RRES.SAGG := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_AGG);
RRES.SALIAS := PKG_XPATH.ATTRIBUTE(RNODE => XNODE, SNAME => SATTR_ALIAS);
RRES.NUSE := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_SHOW);
RRES.NSHOW := PKG_XPATH.ATTRIBUTE_NUM(RNODE => XNODE, SNAME => SATTR_SHOW);
/* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC);
exception
@ -371,6 +395,119 @@ create or replace package body PKG_P8PANELS_QE_BASE as
return RRES;
end TATTR_FROM_XML;
/* Поиск индекса атрибута по имени */
function TATTRS_INDEX_BY_NAME
(
RATTRS in TATTRS, -- Коллекция атрибутов
SNAME in varchar2 -- Искомое имя
) return number -- Индекс найденного атрибута (null - если не найдено)
is
begin
/* Обходим коллекцию */
if ((RATTRS is not null) and (RATTRS.COUNT > 0)) then
for I in RATTRS.FIRST .. RATTRS.LAST
loop
begin
/* Возвращаем найденный индекс */
if (RATTRS(I).SNAME = SNAME) then
return I;
end if;
exception
when NO_DATA_FOUND then
null;
end;
end loop;
end if;
/* Ничего не нашли */
return null;
end TATTRS_INDEX_BY_NAME;
/* Формирование списка атрибутов сущности по типу и наименованию */
function TATTRS_MAKE
(
RENT in TENT, -- Родительская сущность
NCOUNT in number := null -- Количество атрибутов (null - все)
) return TATTRS -- Коллекция атрибутов сущности
is
RRES TATTRS; -- Буфер для результата
RVIEW_FIELDS PKG_OBJECT_DESC.TCOLUMNS; -- Коллекция описаний полей представления
RVIEW_FIELD PKG_OBJECT_DESC.TCOLUMN; -- Описание поля представления
NATTR_INDEX PKG_STD.TNUMBER; -- Индекс поля в коллекции атрибутов сущности
BINIT boolean := false; -- Признак инициализации атрибутов сущности
begin
/* Проверим корректность типа сущности */
if (RENT.STYPE not in (SENT_TYPE_TABLE, SENT_TYPE_VIEW)) then
P_EXCEPTION(0,
'Сущности типа "%s" не поддерживаются.',
COALESCE(RENT.STYPE, '<НЕ УКАЗАН>'));
end if;
/* Проверим, что у сущности задан идентификатор */
if (RENT.SID is null) then
P_EXCEPTION(0,
'Ошибка формирования атрибутов - не задан идентификатор сущности.');
end if;
/* Проверим, что у сущности задано имя */
if (RENT.SNAME is null) then
P_EXCEPTION(0,
'Ошибка формирования атрибутов - не задано имя сущности.');
end if;
/* Инициализируем результат */
RRES := TATTRS();
/* Установим флаг инициализации */
if ((RENT.RATTRS is null) or (RENT.RATTRS.COUNT = 0)) then
BINIT := true;
end if;
/* Если сущность это представление */
if (RENT.STYPE = SENT_TYPE_VIEW) then
/* Получим список полей представления */
RVIEW_FIELDS := PKG_OBJECT_DESC.DESC_SEL_COLUMNS(SSELECT_NAME => RENT.SNAME, BRAISE_ERROR => true);
/* Собираем атрибуты в ответ */
for I in 1 .. PKG_OBJECT_DESC.COUNT_COLUMNS(RCOLUMNS => RVIEW_FIELDS)
loop
/* Считываем очередное поле из коллекции описания полей представления */
RVIEW_FIELD := PKG_OBJECT_DESC.FETCH_COLUMN(RCOLUMNS => RVIEW_FIELDS, IINDEX => I);
/* Если поле поддерживаемого типа */
if (RVIEW_FIELD.DATA_TYPE in (PKG_STD.DATA_TYPE_STR(), PKG_STD.DATA_TYPE_NUM(), PKG_STD.DATA_TYPE_DATE())) then
/* Добавляем элемент в результирующую коллекцию */
RRES.EXTEND();
/* Ищем такой атрибут в родительской сущности */
NATTR_INDEX := TATTRS_INDEX_BY_NAME(RATTRS => RENT.RATTRS, SNAME => RVIEW_FIELD.COLUMN_NAME);
/* Если это поле уже есть в коллекции атрибутов родительской сущности */
if (NATTR_INDEX is not null) then
/* Возьмём элемент оттуда */
RRES(RRES.LAST) := RENT.RATTRS(NATTR_INDEX);
else
/* Такого элемента нет - берем из представления */
RRES(RRES.LAST).SID := TATTR_ID_MAKE(SENT_ID => RENT.SID, SNAME => RVIEW_FIELD.COLUMN_NAME);
RRES(RRES.LAST).SNAME := RVIEW_FIELD.COLUMN_NAME;
RRES(RRES.LAST).STITLE := DMSCLVIEWSATTRS_TITLE_GET(SVIEW_NAME => RENT.SNAME,
SATTR_NAME => RRES(RRES.LAST).SNAME);
RRES(RRES.LAST).NDATA_TYPE := RVIEW_FIELD.DATA_TYPE;
/* Если ранее в сущности вообще не было атрибутов - установим флаг применения в запросе (тогда атрибут будет отображен в диаграмме) */
if (BINIT) then
RRES(RRES.LAST).NUSE := 1;
RRES(RRES.LAST).NSHOW := 1;
else
RRES(RRES.LAST).NUSE := 0;
RRES(RRES.LAST).NSHOW := 0;
end if;
end if;
/* Ограничим объем коллекции если необходимо */
if (NCOUNT is not null) then
exit when RRES.LAST = NCOUNT;
end if;
end if;
end loop;
end if;
/* Если сущность это таблица */
if (RENT.STYPE = SENT_TYPE_TABLE) then
P_EXCEPTION(0,
'Поддержка формирования атрибутов для сущностей типа "Таблица" ещё не реализована.');
end if;
/* Возвращаем результат */
return RRES;
end TATTRS_MAKE;
/* Сериализация коллекции атрибутов сущности */
procedure TATTRS_TO_XML
(
@ -469,8 +606,6 @@ create or replace package body PKG_P8PANELS_QE_BASE as
is
RENT TENT; -- Буфер для результата
RVIEW PKG_OBJECT_DESC.TVIEW; -- Описание представления
RVIEW_FIELDS PKG_OBJECT_DESC.TCOLUMNS; -- Коллекция описаний полей представления
RVIEW_FIELD PKG_OBJECT_DESC.TCOLUMN; -- Описание поля представления
begin
/* Проверим корректность типа сущности */
if (STYPE not in (SENT_TYPE_TABLE, SENT_TYPE_VIEW)) then
@ -482,30 +617,13 @@ create or replace package body PKG_P8PANELS_QE_BASE as
if (STYPE = SENT_TYPE_VIEW) then
/* Получим описание представления */
RVIEW := PKG_OBJECT_DESC.DESC_VIEW(SVIEW_NAME => SNAME, BRAISE_ERROR => true);
/* Получим список полей представления */
RVIEW_FIELDS := PKG_OBJECT_DESC.DESC_SEL_COLUMNS(SSELECT_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();
/* Собираем атрибуты в ответ */
for I in 1 .. PKG_OBJECT_DESC.COUNT_COLUMNS(RCOLUMNS => RVIEW_FIELDS)
loop
/* По умолчанию - первые 10 */
exit when I > 10;
/* Считываем очередное поле из коллекции описания полей представления */
RVIEW_FIELD := PKG_OBJECT_DESC.FETCH_COLUMN(RCOLUMNS => RVIEW_FIELDS, IINDEX => I);
/* Формируем описание поля и добавляем в коллекцию атрибутов сущности */
RENT.RATTRS.EXTEND();
RENT.RATTRS(RENT.RATTRS.LAST).SID := TATTR_ID_MAKE(SENT_ID => RENT.SID, SNAME => RVIEW_FIELD.COLUMN_NAME);
RENT.RATTRS(RENT.RATTRS.LAST).SNAME := RVIEW_FIELD.COLUMN_NAME;
RENT.RATTRS(RENT.RATTRS.LAST).STITLE := DMSCLVIEWSATTRS_TITLE_GET(SVIEW_NAME => RENT.SNAME,
SATTR_NAME => RENT.RATTRS(RENT.RATTRS.LAST)
.SNAME);
RENT.RATTRS(RENT.RATTRS.LAST).NDATA_TYPE := RVIEW_FIELD.DATA_TYPE;
end loop;
/* Формируем набор атрибутов */
RENT.RATTRS := TATTRS_MAKE(RENT => RENT, NCOUNT => 10);
end if;
/* Если сущность это таблица */
if (STYPE = SENT_TYPE_TABLE) then
@ -1484,6 +1602,56 @@ create or replace package body PKG_P8PANELS_QE_BASE as
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
(