forked from CITKParus/P8-Panels
ЦИТК-979 - Диалог настройки атрибута, ввод и контроль псевдонима атрибутов сущностей, короткие псевдонимы сущностей
This commit is contained in:
parent
0767a12fa6
commit
6a6e58e88e
@ -15,7 +15,8 @@ export const TITLES = {
|
||||
DEFAULT_PANELS_GROUP: "Без привязки к группе", //Заголовок группы панелей по умолчанию
|
||||
DATA_SOURCE_CONFIG: "Настройка источника данных", //Заголовок для настройки источника данных
|
||||
INSERT: "Добавление", //Заголовок для диалогов/форм добавления
|
||||
UPDATE: "Исправление" //Заголовок для диалогов/форм исправления
|
||||
UPDATE: "Исправление", //Заголовок для диалогов/форм исправления
|
||||
CONFIG: "Настройка" //Заголовок для диалога настройки
|
||||
};
|
||||
|
||||
//Текст
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - Редактор запросов
|
||||
Компонент: Диалог настройки атрибута сущности
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React from "react"; //Классы React
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
import { P8PDialog } from "../../../../components/p8p_dialog"; //Типовой диалог
|
||||
import { TITLES } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
|
||||
import { DATA_TYPE } from "../../common"; //Общие константы редактора
|
||||
import { ATTRIBUTE_SHAPE } from "../attribute/attribute"; //Описание атрибута
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Диалог добавления/исправления аргумента запроса
|
||||
const AttrSetupDialog = ({ attr, onOk, onCancel }) => {
|
||||
//Достанем необходимое из атрибута
|
||||
const { name, title, dataType, alias } = attr;
|
||||
|
||||
//Нажатие на кнопку "Ok"
|
||||
const handleOk = values => onOk && onOk({ ...values });
|
||||
|
||||
//Нажатие на кнопку "Отмена"
|
||||
const handleCancel = () => onCancel && onCancel();
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<P8PDialog
|
||||
title={`${TITLES.CONFIG} атрибута "${title}"`}
|
||||
inputs={[
|
||||
{ name: "name", value: name, label: "Имя", disabled: true },
|
||||
{ name: "title", value: title, label: "Наименование", disabled: true },
|
||||
{
|
||||
name: "dataType",
|
||||
value: dataType,
|
||||
label: "Тип данных",
|
||||
list: [
|
||||
{ name: "Строка", value: DATA_TYPE.STR },
|
||||
{ name: "Число", value: DATA_TYPE.NUMB },
|
||||
{ name: "Дата", value: DATA_TYPE.DATE }
|
||||
],
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
name: "alias",
|
||||
value: alias,
|
||||
label: "Псевдоним"
|
||||
}
|
||||
]}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств - Диалог настройки атрибута сущности
|
||||
AttrSetupDialog.propTypes = {
|
||||
attr: ATTRIBUTE_SHAPE.isRequired,
|
||||
onOk: PropTypes.func,
|
||||
onCancel: PropTypes.func
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { AttrSetupDialog };
|
||||
@ -30,7 +30,7 @@ const STYLES = {
|
||||
//-----------
|
||||
|
||||
//Список атрибутов сущности
|
||||
const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
||||
const AttrsList = ({ attrs = [], onSelect = null, onShow = null, onSetup = null } = {}) => {
|
||||
//При выборе элемента списка
|
||||
const handleSelectClick = attr => {
|
||||
onSelect && onSelect(attr);
|
||||
@ -42,6 +42,12 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
||||
onShow && onShow(attr);
|
||||
};
|
||||
|
||||
//При нажатии на кнопку настройки атрибута
|
||||
const handleSetupClick = (e, attr) => {
|
||||
e.stopPropagation();
|
||||
onSetup && onSetup(attr);
|
||||
};
|
||||
|
||||
//Формирование представления
|
||||
return (
|
||||
<List sx={STYLES.LIST}>
|
||||
@ -60,7 +66,7 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
||||
secondaryTypographyProps={{ component: "div" }}
|
||||
secondary={
|
||||
<Stack direction={"column"}>
|
||||
<Typography variant={"caption"}>{`${attr.alias || attr.name}`}</Typography>
|
||||
<Typography variant={"caption"}>{`${attr.name}${attr.alias ? ` (${attr.alias})` : ""}`}</Typography>
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
@ -68,6 +74,9 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
||||
<IconButton onClick={e => handleShowClick(e, attr)} title={showTitle}>
|
||||
<Icon>{showIcon}</Icon>
|
||||
</IconButton>
|
||||
<IconButton onClick={e => handleSetupClick(e, attr)} title={"Настроить"}>
|
||||
<Icon>settings</Icon>
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
@ -81,7 +90,8 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
||||
AttrsList.propTypes = {
|
||||
attrs: PropTypes.arrayOf(ATTRIBUTE_SHAPE),
|
||||
onSelect: PropTypes.func,
|
||||
onShow: PropTypes.func
|
||||
onShow: PropTypes.func,
|
||||
onSetup: PropTypes.func
|
||||
};
|
||||
|
||||
//----------------
|
||||
|
||||
@ -13,6 +13,7 @@ import { Box, TextField, InputAdornment, Icon, IconButton } from "@mui/material"
|
||||
import { P8PDialog, P8P_DIALOG_WIDTH } from "../../../../components/p8p_dialog"; //Типовой диалог
|
||||
import { P8PComponentInlineMessage } from "../../../../components/editors/p8p_component_inline_message"; //Типовое встраиваемое сообщение
|
||||
import { AttrsList } from "./attrs_list"; //Список атрибутов сущности
|
||||
import { AttrSetupDialog } from "./attr_setup_dialog"; //Диалог настройки атрибута
|
||||
import { useEntityAttrs } from "./hooks"; //Хуки диалога настройки атрибутов сущности
|
||||
|
||||
//---------
|
||||
@ -36,6 +37,9 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
||||
//Собственное состояние - список атрибутов
|
||||
const [attrs, setAttrs] = useState([]);
|
||||
|
||||
//Собственное состояние - настраиваемый атрибут
|
||||
const [setupAttr, setSetupAttr] = useState(null);
|
||||
|
||||
//Хук для взаимодействия с сервером
|
||||
const [srvAttrs, saveAttrs] = useEntityAttrs(query, id);
|
||||
|
||||
@ -64,6 +68,21 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
||||
}))
|
||||
);
|
||||
|
||||
//Настройка атрибута
|
||||
const handleAttrSetup = attr => setSetupAttr({ ...attr });
|
||||
|
||||
//При закрытии диалога настройки атрибута по "ОК"
|
||||
const handleAttrSetupOk = values => {
|
||||
setAttrs(
|
||||
attrs.map(a => ({
|
||||
...(a.id === setupAttr.id ? { ...a, use: 1, alias: values.alias } : a)
|
||||
}))
|
||||
);
|
||||
setSetupAttr(null);
|
||||
};
|
||||
|
||||
const handleAttrSetupCancel = () => setSetupAttr(null);
|
||||
|
||||
//При изменении значения фильтра
|
||||
const handleFilterChange = e => setFilter(e.target.value);
|
||||
|
||||
@ -87,6 +106,7 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<P8PDialog title={`Атрибуты сущности "${title}"`} width={P8P_DIALOG_WIDTH.SM} fullWidth onOk={handleOk} onCancel={handleCancel}>
|
||||
{setupAttr && <AttrSetupDialog attr={setupAttr} onOk={handleAttrSetupOk} onCancel={handleAttrSetupCancel} />}
|
||||
<TextField
|
||||
margin={"normal"}
|
||||
variant={"standard"}
|
||||
@ -110,7 +130,9 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
||||
}}
|
||||
/>
|
||||
<Box sx={STYLES.LIST_CONTAINER} justifyContent={"center"} alignItems={"center"} display={"flex"}>
|
||||
{displayAttrsList === true && <AttrsList attrs={filteredAttrs} filter={filter} onSelect={handleAttrSelect} onShow={handleAttrShow} />}
|
||||
{displayAttrsList === true && (
|
||||
<AttrsList attrs={filteredAttrs} filter={filter} onSelect={handleAttrSelect} onShow={handleAttrShow} onSetup={handleAttrSetup} />
|
||||
)}
|
||||
{displayAttrsList === false && (
|
||||
<P8PComponentInlineMessage
|
||||
name={"Нет данных, соответствующих фильтру"}
|
||||
|
||||
@ -395,6 +395,7 @@ create or replace package body PKG_P8PANELS_QE as
|
||||
NENT_INDEX PKG_STD.TNUMBER; -- Индекс изменяемой сущности
|
||||
RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов
|
||||
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
|
||||
SCHECK_MSG PKG_STD.TLSTRING; -- Сообщение при проверке атрибутов
|
||||
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
|
||||
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
|
||||
begin
|
||||
@ -434,6 +435,11 @@ create or replace package body PKG_P8PANELS_QE as
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
/* Проверим, что новый набор атрибутов сущности корректен */
|
||||
PKG_P8PANELS_QE_BASE.TATTRS_CHECK(RATTRS => RENTS(NENT_INDEX).RATTRS, SCHECK_MSG => SCHECK_MSG);
|
||||
if (SCHECK_MSG is not null) then
|
||||
P_EXCEPTION(0, SCHECK_MSG);
|
||||
end if;
|
||||
/* Сохраняем обновленный набор сущностей */
|
||||
PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS);
|
||||
/* Сохраняем обновленный набор связей */
|
||||
|
||||
@ -69,6 +69,13 @@ create or replace package PKG_P8PANELS_QE_BASE as
|
||||
SVIEW_NAME in varchar2 -- Имя представления
|
||||
) return varchar2; -- Заголовок представления из метаданных
|
||||
|
||||
/* Поиск индекса атрибута по псевдониму */
|
||||
function TATTRS_INDEX_BY_ALIAS
|
||||
(
|
||||
RATTRS in TATTRS, -- Коллекция атрибутов
|
||||
SALIAS in varchar2 -- Искомый псевдоним
|
||||
) return number; -- Индекс найденного атрибута (null - если не найдено)
|
||||
|
||||
/* Десериализация коллекции атрибутов сущности (из BASE64) */
|
||||
function TATTRS_FROM_XML_BASE64
|
||||
(
|
||||
@ -77,6 +84,13 @@ create or replace package PKG_P8PANELS_QE_BASE as
|
||||
BADD_ROOT in boolean := false -- Флаг необходимости добавления корневого тэга (false - нет, true - да)
|
||||
) return TATTRS; -- Коллекция атрибутов сущности
|
||||
|
||||
/* Проверка корректности атрибутов сущности */
|
||||
procedure TATTRS_CHECK
|
||||
(
|
||||
RATTRS in TATTRS, -- Коллекция атрибутов сущности
|
||||
SCHECK_MSG out varchar2 -- Сообщения проверки (null - ошибок нет)
|
||||
);
|
||||
|
||||
/* Поиск индекса аргумента по имени */
|
||||
function TARGS_INDEX_BY_NAME
|
||||
(
|
||||
@ -809,6 +823,36 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
return SENT_ID || '.' || SNAME;
|
||||
end TATTR_ID_MAKE;
|
||||
|
||||
/* Формирование псевдонима атрибута сущности */
|
||||
function TATTR_ALIAS_MAKE
|
||||
(
|
||||
SENT_ID in varchar2, -- Уникальный идентификатор родительской сущности
|
||||
RATTRS in TATTRS, -- Коллекция уже существующих атрибутов
|
||||
NINDEX in number -- Индекс элемента, для которого формируется псевдоним
|
||||
) return varchar2 -- Сформированный идентификатор
|
||||
is
|
||||
SRES PKG_STD.TSTRING; -- Буфер для результата
|
||||
NCNT PKG_STD.TNUMBER := 0; -- Текущая попытка
|
||||
NMAX_CNT PKG_STD.TNUMBER := 1000; -- Предельное количество попыток
|
||||
NATTR_INDEX PKG_STD.TNUMBER := 0; -- Индекс поля в коллекции атрибутов сущности, при проверке уникальности псевдонима
|
||||
begin
|
||||
/* Подбираем псевдоним */
|
||||
while ((NATTR_INDEX is not null) and (NCNT < NMAX_CNT))
|
||||
loop
|
||||
SRES := SENT_ID || TO_CHAR(NINDEX + NCNT);
|
||||
NATTR_INDEX := TATTRS_INDEX_BY_ALIAS(RATTRS => RATTRS, SALIAS => SRES);
|
||||
NCNT := NCNT + 1;
|
||||
end loop;
|
||||
/* Если так и не смогли сформировать уникальный псевдоним */
|
||||
if ((NATTR_INDEX is not null) and (NCNT >= NMAX_CNT)) then
|
||||
P_EXCEPTION(0,
|
||||
'Не удалось сформировать уникальный псевдоним для атрибута сущности "%s".',
|
||||
SENT_ID);
|
||||
end if;
|
||||
/* Вернём полученный псевдоним */
|
||||
return SRES;
|
||||
end TATTR_ALIAS_MAKE;
|
||||
|
||||
/* Сериализация атрибута сущности */
|
||||
procedure TATTR_TO_XML
|
||||
(
|
||||
@ -929,6 +973,61 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Ничего не нашли */
|
||||
return null;
|
||||
end TATTRS_INDEX_BY_NAME;
|
||||
|
||||
/* Поиск индекса атрибута по псевдониму */
|
||||
function TATTRS_INDEX_BY_ALIAS
|
||||
(
|
||||
RATTRS in TATTRS, -- Коллекция атрибутов
|
||||
SALIAS 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).SALIAS = SALIAS) then
|
||||
return I;
|
||||
end if;
|
||||
exception
|
||||
when NO_DATA_FOUND then
|
||||
null;
|
||||
end;
|
||||
end loop;
|
||||
end if;
|
||||
/* Ничего не нашли */
|
||||
return null;
|
||||
end TATTRS_INDEX_BY_ALIAS;
|
||||
|
||||
/* Подсчет количества атрибутов по псевдониму */
|
||||
function TATTRS_COUNT_BY_ALIAS
|
||||
(
|
||||
RATTRS in TATTRS, -- Коллекция атрибутов
|
||||
SALIAS in varchar2 -- Искомый псевдоним
|
||||
) return number -- Количество найденных атрибутов
|
||||
is
|
||||
NRES PKG_STD.TNUMBER := 0; --Буфер для расчета
|
||||
begin
|
||||
/* Обходим коллекцию */
|
||||
if ((RATTRS is not null) and (RATTRS.COUNT > 0)) then
|
||||
for I in RATTRS.FIRST .. RATTRS.LAST
|
||||
loop
|
||||
begin
|
||||
/* Увеличиваем счетчик, если наш клиент */
|
||||
if (RATTRS(I).SALIAS = SALIAS) then
|
||||
NRES := NRES + 1;
|
||||
end if;
|
||||
exception
|
||||
when NO_DATA_FOUND then
|
||||
null;
|
||||
end;
|
||||
end loop;
|
||||
end if;
|
||||
/* Вернем количество найденных */
|
||||
return NRES;
|
||||
end TATTRS_COUNT_BY_ALIAS;
|
||||
|
||||
/* Формирование списка атрибутов сущности */
|
||||
function TATTRS_MAKE
|
||||
@ -995,6 +1094,7 @@ 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;
|
||||
RRES(RRES.LAST).SALIAS := TATTR_ALIAS_MAKE(SENT_ID => RENT.SID, RATTRS => RRES, NINDEX => RRES.LAST);
|
||||
/* Если это инициализиция сущности - установим флаг применения в запросе (тогда атрибут будет отображен в диаграмме) */
|
||||
if (BINIT) then
|
||||
RRES(RRES.LAST).NUSE := 1;
|
||||
@ -1108,24 +1208,61 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
return TATTRS_FROM_XML(CXML => CTMP);
|
||||
end TATTRS_FROM_XML_BASE64;
|
||||
|
||||
/* Проверка корректности атрибутов сущности */
|
||||
procedure TATTRS_CHECK
|
||||
(
|
||||
RATTRS in TATTRS, -- Коллекция атрибутов сущности
|
||||
SCHECK_MSG out varchar2 -- Сообщения проверки (null - ошибок нет)
|
||||
)
|
||||
is
|
||||
begin
|
||||
/* Обходим коллекцию */
|
||||
if ((RATTRS is not null) and (RATTRS.COUNT > 0)) then
|
||||
for I in RATTRS.FIRST .. RATTRS.LAST
|
||||
loop
|
||||
/* Псевдоним должен быть задан */
|
||||
if (RATTRS(I).SALIAS is null) then
|
||||
SCHECK_MSG := SCHECK_MSG || 'Для атрибута "' || RATTRS(I).SNAME || '" не задан псевдоним; ';
|
||||
else
|
||||
/* А если задан - должен соответствовать по длине */
|
||||
if (LENGTH(RATTRS(I).SALIAS) > 30) then
|
||||
SCHECK_MSG := SCHECK_MSG || 'Длина псевдонима атрибута "' || RATTRS(I).SNAME ||
|
||||
'" превышает максимально допустимую (30 символов); ';
|
||||
end if;
|
||||
/* Набору символов */
|
||||
if (INSTR(RATTRS(I).SALIAS, '"') <> 0) then
|
||||
SCHECK_MSG := SCHECK_MSG || 'Псевдоним атрибута "' || RATTRS(I).SNAME ||
|
||||
'" содержит недопустимые символы; ';
|
||||
end if;
|
||||
/* Быть уникальным */
|
||||
if (TATTRS_COUNT_BY_ALIAS(RATTRS => RATTRS, SALIAS => RATTRS(I).SALIAS) > 1) then
|
||||
SCHECK_MSG := SCHECK_MSG || 'Нарушение уникальности псевдонима атрибута "' || RATTRS(I).SNAME || '"; ';
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
if (SCHECK_MSG is not null) then
|
||||
SCHECK_MSG := RTRIM(SCHECK_MSG, '; ');
|
||||
end if;
|
||||
end TATTRS_CHECK;
|
||||
|
||||
/* Формирование идентификатора сущности */
|
||||
function TENT_ID_MAKE
|
||||
(
|
||||
SNAME in varchar2, -- Имя сущности
|
||||
STYPE in varchar2, -- Тип (см. константы SENT_TYPE_*)
|
||||
NNUMB in number -- Номер сущности в запросе
|
||||
) return varchar2 -- Сформированный идентификатор
|
||||
is
|
||||
begin
|
||||
/* Проверим параметры */
|
||||
if (SNAME is null) then
|
||||
P_EXCEPTION(0, 'Не указано имя сущности.');
|
||||
if (STYPE is null) then
|
||||
P_EXCEPTION(0, 'Не указан тип сущности.');
|
||||
end if;
|
||||
if (NNUMB is null) then
|
||||
P_EXCEPTION(0, 'Не указан номер сущности в запросе.');
|
||||
end if;
|
||||
/* Соберем идентификатор */
|
||||
if (NNUMB is null) then
|
||||
return SNAME;
|
||||
else
|
||||
return SNAME || TO_CHAR(NNUMB);
|
||||
end if;
|
||||
return SUBSTR(STYPE, 1, 1) || TO_CHAR(NNUMB);
|
||||
end TENT_ID_MAKE;
|
||||
|
||||
/* Формирование описания сущности */
|
||||
@ -1154,7 +1291,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Получим описание представления */
|
||||
RVIEW := PKG_OBJECT_DESC.DESC_VIEW(SVIEW_NAME => SNAME, BRAISE_ERROR => true);
|
||||
/* Собираем заголовок сущности */
|
||||
RENT.SID := TENT_ID_MAKE(SNAME => RVIEW.VIEW_NAME, NNUMB => NNUMB);
|
||||
RENT.SID := TENT_ID_MAKE(STYPE => STYPE, NNUMB => NNUMB);
|
||||
RENT.SNAME := RVIEW.VIEW_NAME;
|
||||
RENT.STITLE := DMSCLVIEWS_TITLE_GET(SVIEW_NAME => RENT.SNAME);
|
||||
RENT.STYPE := SENT_TYPE_VIEW;
|
||||
@ -1306,13 +1443,13 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
function TENTS_NEXT_NUMB
|
||||
(
|
||||
RENTS in TENTS, -- Коллекция сущностей
|
||||
SNAME in varchar2 -- Имя
|
||||
STYPE in varchar2 -- Тип (см. константы SENT_TYPE_*)
|
||||
) 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)
|
||||
while (TENTS_INDEX_BY_ID(RENTS => RENTS, SID => TENT_ID_MAKE(STYPE => STYPE, NNUMB => NNUMB)) is not null)
|
||||
loop
|
||||
NNUMB := NNUMB + 1;
|
||||
end loop;
|
||||
@ -1338,7 +1475,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Формируем пописание сущности */
|
||||
RENT := TENT_MAKE(SNAME => SNAME,
|
||||
STYPE => STYPE,
|
||||
NNUMB => TENTS_NEXT_NUMB(RENTS => RENTS, SNAME => SNAME),
|
||||
NNUMB => TENTS_NEXT_NUMB(RENTS => RENTS, STYPE => STYPE),
|
||||
NINIT_ATTRS => NINIT_ATTRS);
|
||||
/* Добавляем её в коллекцию */
|
||||
RENTS.EXTEND();
|
||||
@ -2580,6 +2717,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Если сущность одна - то она и главная */
|
||||
if (RENTS.COUNT = 1) then
|
||||
RENT := RENTS(RENTS.FIRST);
|
||||
return;
|
||||
end if;
|
||||
/* Обходим все сущности */
|
||||
for E in RENTS.FIRST .. RENTS.LAST
|
||||
@ -2590,13 +2728,15 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
for A in RENTS(E).RATTRS.FIRST .. RENTS(E).RATTRS.LAST
|
||||
loop
|
||||
/* Обойдем связи и поищем атрибут среди источников */
|
||||
for R in RRLS.FIRST .. RRLS.LAST
|
||||
loop
|
||||
if (RRLS(R).SSOURCE = RENTS(E).RATTRS(A).SID) then
|
||||
BFOUND := true;
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
if ((RRLS is not null) and (RRLS.COUNT > 0)) then
|
||||
for R in RRLS.FIRST .. RRLS.LAST
|
||||
loop
|
||||
if (RRLS(R).SSOURCE = RENTS(E).RATTRS(A).SID) then
|
||||
BFOUND := true;
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
/* Если хоть один атрибут сущности есть среди источников - дальше можно атрибуты этой сущности не рассматривать */
|
||||
exit when BFOUND = true;
|
||||
end loop;
|
||||
@ -2621,12 +2761,14 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Формирование части "select" */
|
||||
procedure BUILD_SELECT
|
||||
(
|
||||
RENTS TENTS, -- Сущности запроса
|
||||
SQRY in out varchar2 -- Буфер для запроса
|
||||
RENTS TENTS, -- Сущности запроса
|
||||
SQRY in out varchar2 -- Буфер для запроса
|
||||
)
|
||||
is
|
||||
SFIELD PKG_STD.TSTRING; -- Буфер для поля запроса
|
||||
SFIELD PKG_STD.TSTRING; -- Буфер для поля запроса
|
||||
BFOUND boolean := false; -- Флаг наличия визуализируемых атрибутов
|
||||
begin
|
||||
/* Формируем */
|
||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'select ');
|
||||
for I in RENTS.FIRST .. RENTS.LAST
|
||||
loop
|
||||
@ -2634,15 +2776,24 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
for J in RENTS(I).RATTRS.FIRST .. RENTS(I).RATTRS.LAST
|
||||
loop
|
||||
if (RENTS(I).RATTRS(J).NSHOW = 1) then
|
||||
SFIELD := RENTS(I).RATTRS(J).SID || ' ' || RENTS(I).RATTRS(J).SNAME || I || J;
|
||||
if (not ((I = RENTS.LAST) and (J = RENTS(I).RATTRS.LAST))) then
|
||||
SFIELD := SFIELD || ', ';
|
||||
if (RENTS(I).RATTRS(J).SALIAS is null) then
|
||||
P_EXCEPTION(0,
|
||||
'Для атрибута ("%s") не задан севдоним.',
|
||||
RENTS(I).RATTRS(J).SID);
|
||||
end if;
|
||||
SFIELD := RENTS(I).RATTRS(J).SID || ' "' || RENTS(I).RATTRS(J).SALIAS || '", ';
|
||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => SFIELD);
|
||||
BFOUND := true;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end loop;
|
||||
SQRY := RTRIM(SQRY, ', ');
|
||||
/* Если не нашли ни одного атрибута */
|
||||
if (not BFOUND) then
|
||||
P_EXCEPTION(0,
|
||||
'Для запроса не определено ни одного визуализируемого атрибута.');
|
||||
end if;
|
||||
end BUILD_SELECT;
|
||||
|
||||
/* Формирование иерархии связей в секции "from" */
|
||||
@ -2701,7 +2852,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'from ');
|
||||
STABLE := RENT_ROOT.SNAME || ' ' || RENT_ROOT.SID;
|
||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => STABLE);
|
||||
if (RRLS.COUNT > 0) then
|
||||
if ((RRLS is not null) and (RRLS.COUNT > 0)) then
|
||||
BUILD_FROM_HIER(RENT_START => RENT_ROOT, RENTS => RENTS, RRLS => RRLS, SQRY => SQRY);
|
||||
end if;
|
||||
else
|
||||
@ -2723,10 +2874,6 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
end if;
|
||||
end BUILD_WHERE;
|
||||
begin
|
||||
/*
|
||||
TODO: owner="root" created="09.09.2025"
|
||||
text="Контроль длины псевдонима таблицы и поля (максимум 30 символов)"
|
||||
*/
|
||||
/*
|
||||
TODO: owner="root" created="10.09.2025"
|
||||
text="Предусмотреть связям признак ""обязательность""
|
||||
@ -2746,14 +2893,14 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Читаем сущности запроса */
|
||||
RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS);
|
||||
/* Нет сущностей - нет запроса */
|
||||
if ((RENTS is null) and (RENTS.COUNT = 0)) then
|
||||
if ((RENTS is null) or (RENTS.COUNT = 0)) then
|
||||
SET_MSG(SMESSAGE => 'В запросе нет сущностей.');
|
||||
return;
|
||||
end if;
|
||||
/* Читаем связи запроса */
|
||||
RRLS := QUERY_RLS_GET(CRLS => RQ.RLS);
|
||||
/* Нельзя построить запрос, если есть несвязанные сущности */
|
||||
if ((RENTS.COUNT > 1) and (RENTS.COUNT - 1 > RRLS.COUNT)) then
|
||||
if ((RENTS.COUNT > 1) and ((RRLS is null) or (RENTS.COUNT - 1 > RRLS.COUNT))) then
|
||||
SET_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.');
|
||||
return;
|
||||
end if;
|
||||
@ -2766,7 +2913,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
/* Собираем запрос - таблицы и связи */
|
||||
BUILD_FROM(RENTS => RENTS, RRLS => RRLS, SQRY => SQRY);
|
||||
/* Собираем запрос - условия */
|
||||
BUILD_WHERE(ROPT => ROPT, SQRY => SQRY);
|
||||
BUILD_WHERE(ROPT => ROPT, SQRY => SQRY);
|
||||
exception
|
||||
when others then
|
||||
PKG_STATE.DIAGNOSTICS_STACKED();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user