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: "Без привязки к группе", //Заголовок группы панелей по умолчанию
|
DEFAULT_PANELS_GROUP: "Без привязки к группе", //Заголовок группы панелей по умолчанию
|
||||||
DATA_SOURCE_CONFIG: "Настройка источника данных", //Заголовок для настройки источника данных
|
DATA_SOURCE_CONFIG: "Настройка источника данных", //Заголовок для настройки источника данных
|
||||||
INSERT: "Добавление", //Заголовок для диалогов/форм добавления
|
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 => {
|
const handleSelectClick = attr => {
|
||||||
onSelect && onSelect(attr);
|
onSelect && onSelect(attr);
|
||||||
@ -42,6 +42,12 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
|||||||
onShow && onShow(attr);
|
onShow && onShow(attr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//При нажатии на кнопку настройки атрибута
|
||||||
|
const handleSetupClick = (e, attr) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onSetup && onSetup(attr);
|
||||||
|
};
|
||||||
|
|
||||||
//Формирование представления
|
//Формирование представления
|
||||||
return (
|
return (
|
||||||
<List sx={STYLES.LIST}>
|
<List sx={STYLES.LIST}>
|
||||||
@ -60,7 +66,7 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
|||||||
secondaryTypographyProps={{ component: "div" }}
|
secondaryTypographyProps={{ component: "div" }}
|
||||||
secondary={
|
secondary={
|
||||||
<Stack direction={"column"}>
|
<Stack direction={"column"}>
|
||||||
<Typography variant={"caption"}>{`${attr.alias || attr.name}`}</Typography>
|
<Typography variant={"caption"}>{`${attr.name}${attr.alias ? ` (${attr.alias})` : ""}`}</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -68,6 +74,9 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
|||||||
<IconButton onClick={e => handleShowClick(e, attr)} title={showTitle}>
|
<IconButton onClick={e => handleShowClick(e, attr)} title={showTitle}>
|
||||||
<Icon>{showIcon}</Icon>
|
<Icon>{showIcon}</Icon>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
<IconButton onClick={e => handleSetupClick(e, attr)} title={"Настроить"}>
|
||||||
|
<Icon>settings</Icon>
|
||||||
|
</IconButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
@ -81,7 +90,8 @@ const AttrsList = ({ attrs = [], onSelect = null, onShow = null } = {}) => {
|
|||||||
AttrsList.propTypes = {
|
AttrsList.propTypes = {
|
||||||
attrs: PropTypes.arrayOf(ATTRIBUTE_SHAPE),
|
attrs: PropTypes.arrayOf(ATTRIBUTE_SHAPE),
|
||||||
onSelect: PropTypes.func,
|
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 { P8PDialog, P8P_DIALOG_WIDTH } from "../../../../components/p8p_dialog"; //Типовой диалог
|
||||||
import { P8PComponentInlineMessage } from "../../../../components/editors/p8p_component_inline_message"; //Типовое встраиваемое сообщение
|
import { P8PComponentInlineMessage } from "../../../../components/editors/p8p_component_inline_message"; //Типовое встраиваемое сообщение
|
||||||
import { AttrsList } from "./attrs_list"; //Список атрибутов сущности
|
import { AttrsList } from "./attrs_list"; //Список атрибутов сущности
|
||||||
|
import { AttrSetupDialog } from "./attr_setup_dialog"; //Диалог настройки атрибута
|
||||||
import { useEntityAttrs } from "./hooks"; //Хуки диалога настройки атрибутов сущности
|
import { useEntityAttrs } from "./hooks"; //Хуки диалога настройки атрибутов сущности
|
||||||
|
|
||||||
//---------
|
//---------
|
||||||
@ -36,6 +37,9 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
|||||||
//Собственное состояние - список атрибутов
|
//Собственное состояние - список атрибутов
|
||||||
const [attrs, setAttrs] = useState([]);
|
const [attrs, setAttrs] = useState([]);
|
||||||
|
|
||||||
|
//Собственное состояние - настраиваемый атрибут
|
||||||
|
const [setupAttr, setSetupAttr] = useState(null);
|
||||||
|
|
||||||
//Хук для взаимодействия с сервером
|
//Хук для взаимодействия с сервером
|
||||||
const [srvAttrs, saveAttrs] = useEntityAttrs(query, id);
|
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);
|
const handleFilterChange = e => setFilter(e.target.value);
|
||||||
|
|
||||||
@ -87,6 +106,7 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
|||||||
//Генерация содержимого
|
//Генерация содержимого
|
||||||
return (
|
return (
|
||||||
<P8PDialog title={`Атрибуты сущности "${title}"`} width={P8P_DIALOG_WIDTH.SM} fullWidth onOk={handleOk} onCancel={handleCancel}>
|
<P8PDialog title={`Атрибуты сущности "${title}"`} width={P8P_DIALOG_WIDTH.SM} fullWidth onOk={handleOk} onCancel={handleCancel}>
|
||||||
|
{setupAttr && <AttrSetupDialog attr={setupAttr} onOk={handleAttrSetupOk} onCancel={handleAttrSetupCancel} />}
|
||||||
<TextField
|
<TextField
|
||||||
margin={"normal"}
|
margin={"normal"}
|
||||||
variant={"standard"}
|
variant={"standard"}
|
||||||
@ -110,7 +130,9 @@ const EntityAttrsDialog = ({ query, id, title, onOk, onCancel }) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Box sx={STYLES.LIST_CONTAINER} justifyContent={"center"} alignItems={"center"} display={"flex"}>
|
<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 && (
|
{displayAttrsList === false && (
|
||||||
<P8PComponentInlineMessage
|
<P8PComponentInlineMessage
|
||||||
name={"Нет данных, соответствующих фильтру"}
|
name={"Нет данных, соответствующих фильтру"}
|
||||||
|
|||||||
@ -395,6 +395,7 @@ create or replace package body PKG_P8PANELS_QE as
|
|||||||
NENT_INDEX PKG_STD.TNUMBER; -- Индекс изменяемой сущности
|
NENT_INDEX PKG_STD.TNUMBER; -- Индекс изменяемой сущности
|
||||||
RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов
|
RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов
|
||||||
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
|
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
|
||||||
|
SCHECK_MSG PKG_STD.TLSTRING; -- Сообщение при проверке атрибутов
|
||||||
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
|
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
|
||||||
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
|
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
|
||||||
begin
|
begin
|
||||||
@ -434,6 +435,11 @@ create or replace package body PKG_P8PANELS_QE as
|
|||||||
end if;
|
end if;
|
||||||
end loop;
|
end loop;
|
||||||
end if;
|
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);
|
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 -- Имя представления
|
SVIEW_NAME in varchar2 -- Имя представления
|
||||||
) return varchar2; -- Заголовок представления из метаданных
|
) return varchar2; -- Заголовок представления из метаданных
|
||||||
|
|
||||||
|
/* Поиск индекса атрибута по псевдониму */
|
||||||
|
function TATTRS_INDEX_BY_ALIAS
|
||||||
|
(
|
||||||
|
RATTRS in TATTRS, -- Коллекция атрибутов
|
||||||
|
SALIAS in varchar2 -- Искомый псевдоним
|
||||||
|
) return number; -- Индекс найденного атрибута (null - если не найдено)
|
||||||
|
|
||||||
/* Десериализация коллекции атрибутов сущности (из BASE64) */
|
/* Десериализация коллекции атрибутов сущности (из BASE64) */
|
||||||
function TATTRS_FROM_XML_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 - да)
|
BADD_ROOT in boolean := false -- Флаг необходимости добавления корневого тэга (false - нет, true - да)
|
||||||
) return TATTRS; -- Коллекция атрибутов сущности
|
) return TATTRS; -- Коллекция атрибутов сущности
|
||||||
|
|
||||||
|
/* Проверка корректности атрибутов сущности */
|
||||||
|
procedure TATTRS_CHECK
|
||||||
|
(
|
||||||
|
RATTRS in TATTRS, -- Коллекция атрибутов сущности
|
||||||
|
SCHECK_MSG out varchar2 -- Сообщения проверки (null - ошибок нет)
|
||||||
|
);
|
||||||
|
|
||||||
/* Поиск индекса аргумента по имени */
|
/* Поиск индекса аргумента по имени */
|
||||||
function TARGS_INDEX_BY_NAME
|
function TARGS_INDEX_BY_NAME
|
||||||
(
|
(
|
||||||
@ -809,6 +823,36 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
return SENT_ID || '.' || SNAME;
|
return SENT_ID || '.' || SNAME;
|
||||||
end TATTR_ID_MAKE;
|
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
|
procedure TATTR_TO_XML
|
||||||
(
|
(
|
||||||
@ -929,6 +973,61 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
/* Ничего не нашли */
|
/* Ничего не нашли */
|
||||||
return null;
|
return null;
|
||||||
end TATTRS_INDEX_BY_NAME;
|
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
|
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,
|
RRES(RRES.LAST).STITLE := DMSCLVIEWSATTRS_TITLE_GET(SVIEW_NAME => RENT.SNAME,
|
||||||
SATTR_NAME => RRES(RRES.LAST).SNAME);
|
SATTR_NAME => RRES(RRES.LAST).SNAME);
|
||||||
RRES(RRES.LAST).NDATA_TYPE := RVIEW_FIELD.DATA_TYPE;
|
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
|
if (BINIT) then
|
||||||
RRES(RRES.LAST).NUSE := 1;
|
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);
|
return TATTRS_FROM_XML(CXML => CTMP);
|
||||||
end TATTRS_FROM_XML_BASE64;
|
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
|
function TENT_ID_MAKE
|
||||||
(
|
(
|
||||||
SNAME in varchar2, -- Имя сущности
|
STYPE in varchar2, -- Тип (см. константы SENT_TYPE_*)
|
||||||
NNUMB in number -- Номер сущности в запросе
|
NNUMB in number -- Номер сущности в запросе
|
||||||
) return varchar2 -- Сформированный идентификатор
|
) return varchar2 -- Сформированный идентификатор
|
||||||
is
|
is
|
||||||
begin
|
begin
|
||||||
/* Проверим параметры */
|
/* Проверим параметры */
|
||||||
if (SNAME is null) then
|
if (STYPE is null) then
|
||||||
P_EXCEPTION(0, 'Не указано имя сущности.');
|
P_EXCEPTION(0, 'Не указан тип сущности.');
|
||||||
|
end if;
|
||||||
|
if (NNUMB is null) then
|
||||||
|
P_EXCEPTION(0, 'Не указан номер сущности в запросе.');
|
||||||
end if;
|
end if;
|
||||||
/* Соберем идентификатор */
|
/* Соберем идентификатор */
|
||||||
if (NNUMB is null) then
|
return SUBSTR(STYPE, 1, 1) || TO_CHAR(NNUMB);
|
||||||
return SNAME;
|
|
||||||
else
|
|
||||||
return SNAME || TO_CHAR(NNUMB);
|
|
||||||
end if;
|
|
||||||
end TENT_ID_MAKE;
|
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);
|
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.SNAME := RVIEW.VIEW_NAME;
|
||||||
RENT.STITLE := DMSCLVIEWS_TITLE_GET(SVIEW_NAME => RENT.SNAME);
|
RENT.STITLE := DMSCLVIEWS_TITLE_GET(SVIEW_NAME => RENT.SNAME);
|
||||||
RENT.STYPE := SENT_TYPE_VIEW;
|
RENT.STYPE := SENT_TYPE_VIEW;
|
||||||
@ -1306,13 +1443,13 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
function TENTS_NEXT_NUMB
|
function TENTS_NEXT_NUMB
|
||||||
(
|
(
|
||||||
RENTS in TENTS, -- Коллекция сущностей
|
RENTS in TENTS, -- Коллекция сущностей
|
||||||
SNAME in varchar2 -- Имя
|
STYPE in varchar2 -- Тип (см. константы SENT_TYPE_*)
|
||||||
) return number -- Номер сущности в коллекции
|
) return number -- Номер сущности в коллекции
|
||||||
is
|
is
|
||||||
NNUMB PKG_STD.TNUMBER := 0; -- Буфер для результата
|
NNUMB PKG_STD.TNUMBER := 0; -- Буфер для результата
|
||||||
begin
|
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
|
loop
|
||||||
NNUMB := NNUMB + 1;
|
NNUMB := NNUMB + 1;
|
||||||
end loop;
|
end loop;
|
||||||
@ -1338,7 +1475,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
/* Формируем пописание сущности */
|
/* Формируем пописание сущности */
|
||||||
RENT := TENT_MAKE(SNAME => SNAME,
|
RENT := TENT_MAKE(SNAME => SNAME,
|
||||||
STYPE => STYPE,
|
STYPE => STYPE,
|
||||||
NNUMB => TENTS_NEXT_NUMB(RENTS => RENTS, SNAME => SNAME),
|
NNUMB => TENTS_NEXT_NUMB(RENTS => RENTS, STYPE => STYPE),
|
||||||
NINIT_ATTRS => NINIT_ATTRS);
|
NINIT_ATTRS => NINIT_ATTRS);
|
||||||
/* Добавляем её в коллекцию */
|
/* Добавляем её в коллекцию */
|
||||||
RENTS.EXTEND();
|
RENTS.EXTEND();
|
||||||
@ -2580,6 +2717,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
/* Если сущность одна - то она и главная */
|
/* Если сущность одна - то она и главная */
|
||||||
if (RENTS.COUNT = 1) then
|
if (RENTS.COUNT = 1) then
|
||||||
RENT := RENTS(RENTS.FIRST);
|
RENT := RENTS(RENTS.FIRST);
|
||||||
|
return;
|
||||||
end if;
|
end if;
|
||||||
/* Обходим все сущности */
|
/* Обходим все сущности */
|
||||||
for E in RENTS.FIRST .. RENTS.LAST
|
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
|
for A in RENTS(E).RATTRS.FIRST .. RENTS(E).RATTRS.LAST
|
||||||
loop
|
loop
|
||||||
/* Обойдем связи и поищем атрибут среди источников */
|
/* Обойдем связи и поищем атрибут среди источников */
|
||||||
for R in RRLS.FIRST .. RRLS.LAST
|
if ((RRLS is not null) and (RRLS.COUNT > 0)) then
|
||||||
loop
|
for R in RRLS.FIRST .. RRLS.LAST
|
||||||
if (RRLS(R).SSOURCE = RENTS(E).RATTRS(A).SID) then
|
loop
|
||||||
BFOUND := true;
|
if (RRLS(R).SSOURCE = RENTS(E).RATTRS(A).SID) then
|
||||||
exit;
|
BFOUND := true;
|
||||||
end if;
|
exit;
|
||||||
end loop;
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
/* Если хоть один атрибут сущности есть среди источников - дальше можно атрибуты этой сущности не рассматривать */
|
/* Если хоть один атрибут сущности есть среди источников - дальше можно атрибуты этой сущности не рассматривать */
|
||||||
exit when BFOUND = true;
|
exit when BFOUND = true;
|
||||||
end loop;
|
end loop;
|
||||||
@ -2621,12 +2761,14 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
/* Формирование части "select" */
|
/* Формирование части "select" */
|
||||||
procedure BUILD_SELECT
|
procedure BUILD_SELECT
|
||||||
(
|
(
|
||||||
RENTS TENTS, -- Сущности запроса
|
RENTS TENTS, -- Сущности запроса
|
||||||
SQRY in out varchar2 -- Буфер для запроса
|
SQRY in out varchar2 -- Буфер для запроса
|
||||||
)
|
)
|
||||||
is
|
is
|
||||||
SFIELD PKG_STD.TSTRING; -- Буфер для поля запроса
|
SFIELD PKG_STD.TSTRING; -- Буфер для поля запроса
|
||||||
|
BFOUND boolean := false; -- Флаг наличия визуализируемых атрибутов
|
||||||
begin
|
begin
|
||||||
|
/* Формируем */
|
||||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'select ');
|
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'select ');
|
||||||
for I in RENTS.FIRST .. RENTS.LAST
|
for I in RENTS.FIRST .. RENTS.LAST
|
||||||
loop
|
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
|
for J in RENTS(I).RATTRS.FIRST .. RENTS(I).RATTRS.LAST
|
||||||
loop
|
loop
|
||||||
if (RENTS(I).RATTRS(J).NSHOW = 1) then
|
if (RENTS(I).RATTRS(J).NSHOW = 1) then
|
||||||
SFIELD := RENTS(I).RATTRS(J).SID || ' ' || RENTS(I).RATTRS(J).SNAME || I || J;
|
if (RENTS(I).RATTRS(J).SALIAS is null) then
|
||||||
if (not ((I = RENTS.LAST) and (J = RENTS(I).RATTRS.LAST))) then
|
P_EXCEPTION(0,
|
||||||
SFIELD := SFIELD || ', ';
|
'Для атрибута ("%s") не задан севдоним.',
|
||||||
|
RENTS(I).RATTRS(J).SID);
|
||||||
end if;
|
end if;
|
||||||
|
SFIELD := RENTS(I).RATTRS(J).SID || ' "' || RENTS(I).RATTRS(J).SALIAS || '", ';
|
||||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => SFIELD);
|
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => SFIELD);
|
||||||
|
BFOUND := true;
|
||||||
end if;
|
end if;
|
||||||
end loop;
|
end loop;
|
||||||
end if;
|
end if;
|
||||||
end loop;
|
end loop;
|
||||||
|
SQRY := RTRIM(SQRY, ', ');
|
||||||
|
/* Если не нашли ни одного атрибута */
|
||||||
|
if (not BFOUND) then
|
||||||
|
P_EXCEPTION(0,
|
||||||
|
'Для запроса не определено ни одного визуализируемого атрибута.');
|
||||||
|
end if;
|
||||||
end BUILD_SELECT;
|
end BUILD_SELECT;
|
||||||
|
|
||||||
/* Формирование иерархии связей в секции "from" */
|
/* Формирование иерархии связей в секции "from" */
|
||||||
@ -2701,7 +2852,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'from ');
|
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'from ');
|
||||||
STABLE := RENT_ROOT.SNAME || ' ' || RENT_ROOT.SID;
|
STABLE := RENT_ROOT.SNAME || ' ' || RENT_ROOT.SID;
|
||||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => STABLE);
|
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);
|
BUILD_FROM_HIER(RENT_START => RENT_ROOT, RENTS => RENTS, RRLS => RRLS, SQRY => SQRY);
|
||||||
end if;
|
end if;
|
||||||
else
|
else
|
||||||
@ -2723,10 +2874,6 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
end if;
|
end if;
|
||||||
end BUILD_WHERE;
|
end BUILD_WHERE;
|
||||||
begin
|
begin
|
||||||
/*
|
|
||||||
TODO: owner="root" created="09.09.2025"
|
|
||||||
text="Контроль длины псевдонима таблицы и поля (максимум 30 символов)"
|
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
TODO: owner="root" created="10.09.2025"
|
TODO: owner="root" created="10.09.2025"
|
||||||
text="Предусмотреть связям признак ""обязательность""
|
text="Предусмотреть связям признак ""обязательность""
|
||||||
@ -2746,14 +2893,14 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
|||||||
/* Читаем сущности запроса */
|
/* Читаем сущности запроса */
|
||||||
RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS);
|
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 => 'В запросе нет сущностей.');
|
SET_MSG(SMESSAGE => 'В запросе нет сущностей.');
|
||||||
return;
|
return;
|
||||||
end if;
|
end if;
|
||||||
/* Читаем связи запроса */
|
/* Читаем связи запроса */
|
||||||
RRLS := QUERY_RLS_GET(CRLS => RQ.RLS);
|
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 => 'В запросе есть несвязанные сущности.');
|
SET_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.');
|
||||||
return;
|
return;
|
||||||
end if;
|
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_FROM(RENTS => RENTS, RRLS => RRLS, SQRY => SQRY);
|
||||||
/* Собираем запрос - условия */
|
/* Собираем запрос - условия */
|
||||||
BUILD_WHERE(ROPT => ROPT, SQRY => SQRY);
|
BUILD_WHERE(ROPT => ROPT, SQRY => SQRY);
|
||||||
exception
|
exception
|
||||||
when others then
|
when others then
|
||||||
PKG_STATE.DIAGNOSTICS_STACKED();
|
PKG_STATE.DIAGNOSTICS_STACKED();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user