ЦИТК-979 - Редактор запросов - Поддержка подстановки отладочных значений аргументов в SQL-выражение
This commit is contained in:
parent
64145d7ac0
commit
1530bfa3bf
@ -18,14 +18,25 @@ import { InspectorQueryArguments } from "../inspector_query_args/inspector_query
|
||||
import { InspectorQueryConditions } from "../inspector_query_cond/inspector_query_cond"; //Управление условиями отбора запроса
|
||||
import { InspectorQueryEntities } from "../inspector_query_ents/inspector_query_ents"; //Управление сущностями запроса
|
||||
import { InspectorQueryRelations } from "../inspector_query_rls/inspector_query_rls"; //Управление связями запроса
|
||||
import { QueryArea } from "./query_area"; //Область запроса
|
||||
import { InspectorQueryArea } from "../inspector_query_area/inspector_query_area"; //Область SQL-выражения
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Инспектор свойств
|
||||
const Inspector = ({ query, entity, relation, entities = [], args = [], cond = null, qry = "", qryMsg = "", onOptionsChanged = null }) => {
|
||||
const Inspector = ({
|
||||
query,
|
||||
entity,
|
||||
relation,
|
||||
entities = [],
|
||||
args = [],
|
||||
cond = null,
|
||||
substArgsVals = 0,
|
||||
qry = "",
|
||||
qryMsg = "",
|
||||
onOptionsChanged = null
|
||||
}) => {
|
||||
//При изменении настроек запроса
|
||||
const handleOptionsChanged = () => onOptionsChanged && onOptionsChanged();
|
||||
|
||||
@ -44,7 +55,7 @@ const Inspector = ({ query, entity, relation, entities = [], args = [], cond = n
|
||||
<InspectorQueryRelations query={query} relation={relation} onOptionsChanged={handleOptionsChanged} />
|
||||
</>
|
||||
)}
|
||||
<QueryArea qry={qry} qryMsg={qryMsg} />
|
||||
<InspectorQueryArea query={query} substArgsVals={substArgsVals} qry={qry} qryMsg={qryMsg} onOptionsChanged={handleOptionsChanged} />
|
||||
</P8PEditorBox>
|
||||
);
|
||||
};
|
||||
@ -57,6 +68,7 @@ Inspector.propTypes = {
|
||||
entities: PropTypes.arrayOf(ENTITY_SHAPE),
|
||||
args: PropTypes.arrayOf(ARGUMENT_SHAPE),
|
||||
cond: PropTypes.string,
|
||||
substArgsVals: PropTypes.number,
|
||||
qry: PropTypes.string,
|
||||
qryMsg: PropTypes.string,
|
||||
onOptionsChanged: PropTypes.func
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - Редактор запросов
|
||||
Пользовательские хуки для работы с областью SQL-выражения
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import { useContext, useCallback } from "react"; //Классы React
|
||||
import { BackEndСtx } from "../../../../context/backend"; //Контекст взаимодействия с сервером
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Работа с областью SQL-выражения
|
||||
const useQuerySQLExpr = query => {
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
||||
//Установка флага сокрытия/отображения значений аргументов в SQL-выражении запроса
|
||||
const toggleSubstArgsVals = useCallback(async () => {
|
||||
await executeStored({ stored: "PKG_P8PANELS_QE.QUERY_OPT_SUBST_ARGS_VALS_TGL", args: { NRN: query }, loader: false });
|
||||
}, [query, executeStored]);
|
||||
|
||||
//Возвращаем интерфейс хука
|
||||
return { toggleSubstArgsVals };
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { useQuerySQLExpr };
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - Редактор запросов
|
||||
Область запроса
|
||||
Область SQL-выражения
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
@ -12,6 +12,7 @@ import PropTypes from "prop-types"; //Контроль свойств компо
|
||||
import { Fab, Icon, Drawer, IconButton, TextField, Stack, Box, Snackbar, Alert } from "@mui/material"; //Компоненты MUI
|
||||
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
|
||||
import { APP_STYLES } from "../../../../../app.styles"; //Общие стили приложения
|
||||
import { useQuerySQLExpr } from "./hooks"; //Пользовательские хуки для работы с SQL-выражением
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
@ -38,8 +39,8 @@ const SNACK_BAR_MESSAGE_INIT = { text: null, type: null };
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
//Область запроса
|
||||
const QueryArea = ({ qry = "", qryMsg = "" }) => {
|
||||
//Область SQL-выражения
|
||||
const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryMsg = "", onOptionsChanged }) => {
|
||||
//Собственное состояние - текст всплывающего сообщения
|
||||
const [snackBarMessage, setSnackBarMessage] = useState(SNACK_BAR_MESSAGE_INIT);
|
||||
|
||||
@ -49,6 +50,18 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
|
||||
//Собственное состояние - развёрнутость
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
//Работа с SQL-выражением
|
||||
const { toggleSubstArgsVals } = useQuerySQLExpr(query);
|
||||
|
||||
//Уведомление родителя об изменении свойств
|
||||
const notifyOptionsChanged = () => onOptionsChanged && onOptionsChanged();
|
||||
|
||||
//При нажатии на кнопку отображения/сокрытия значений аргументов в SQL-выражении запроса
|
||||
const handleToggleSubstArgsValsClick = async () => {
|
||||
await toggleSubstArgsVals();
|
||||
notifyOptionsChanged();
|
||||
};
|
||||
|
||||
//При нажатии на кнопку копирования текста запроса
|
||||
const handleCopyClick = async () => {
|
||||
try {
|
||||
@ -87,9 +100,17 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
|
||||
<Box p={2}>
|
||||
<Stack direction={"row"} justifyContent={"right"} spacing={2}>
|
||||
{qry && (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={handleToggleSubstArgsValsClick}
|
||||
title={substArgsVals === 1 ? "Скрыть значения аргументов" : "Отобразить значения аргументов"}
|
||||
>
|
||||
<Icon>{substArgsVals === 1 ? "code_off" : "code"}</Icon>
|
||||
</IconButton>
|
||||
<IconButton onClick={handleCopyClick} title={"Скопировать текст запроса"}>
|
||||
<Icon>content_copy</Icon>
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
<IconButton onClick={handleExpandClick} title={expanded ? "Свернуть" : "Развернуть"}>
|
||||
<Icon>{expanded ? "expand_more" : "expand_less"}</Icon>
|
||||
@ -139,14 +160,17 @@ const QueryArea = ({ qry = "", qryMsg = "" }) => {
|
||||
);
|
||||
};
|
||||
|
||||
//Контроль свойств компонента - Область запроса
|
||||
QueryArea.propTypes = {
|
||||
//Контроль свойств компонента - Область SQL-выражения
|
||||
InspectorQueryArea.propTypes = {
|
||||
query: PropTypes.number.isRequired,
|
||||
substArgsVals: PropTypes.number,
|
||||
qry: PropTypes.string,
|
||||
qryMsg: PropTypes.string
|
||||
qryMsg: PropTypes.string,
|
||||
onOptionsChanged: PropTypes.func
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { QueryArea };
|
||||
export { InspectorQueryArea };
|
||||
@ -139,7 +139,11 @@ const useQuery = query => {
|
||||
loader: true
|
||||
});
|
||||
setQueryDiagram(serverQueryData2QueryDiagram(data?.XENTS?.XENT || [], data?.XRLS?.XRL || []));
|
||||
setQueryOption({ args: data?.XOPT?.XARGS?.XARG || [], cond: data?.XOPT?.XCOND || null });
|
||||
setQueryOption({
|
||||
args: data?.XOPT?.XARGS?.XARG || [],
|
||||
cond: data?.XOPT?.XCOND || null,
|
||||
substArgsVals: data?.XOPT?.XSUBST_ARGS_VALS || 0
|
||||
});
|
||||
setQuerySQL({ qry: data?.XQRY, qryMsg: data?.XQRY_MSG });
|
||||
setInit(true);
|
||||
} finally {
|
||||
|
||||
@ -155,6 +155,12 @@ create or replace package PKG_P8PANELS_QE as
|
||||
SCOND in varchar2 -- Условия отбора
|
||||
);
|
||||
|
||||
/* Переключение флага подстановки значений аргументов запроса в SQL-выражение */
|
||||
procedure QUERY_OPT_SUBST_ARGS_VALS_TGL
|
||||
(
|
||||
NRN in number -- Рег. номер запроса
|
||||
);
|
||||
|
||||
end PKG_P8PANELS_QE;
|
||||
/
|
||||
create or replace package body PKG_P8PANELS_QE as
|
||||
@ -651,5 +657,32 @@ create or replace package body PKG_P8PANELS_QE as
|
||||
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
|
||||
end QUERY_OPT_COND_SET;
|
||||
|
||||
/* Переключение флага подстановки значений аргументов запроса в SQL-выражение */
|
||||
procedure QUERY_OPT_SUBST_ARGS_VALS_TGL
|
||||
(
|
||||
NRN in number -- Рег. номер запроса
|
||||
)
|
||||
is
|
||||
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
|
||||
ROPT PKG_P8PANELS_QE_BASE.TOPT; -- Настройка запроса
|
||||
begin
|
||||
/* Провим права доступа */
|
||||
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
|
||||
/* Читаем запись запроса */
|
||||
RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN);
|
||||
/* Читаем текущую настройку */
|
||||
ROPT := PKG_P8PANELS_QE_BASE.QUERY_OPT_GET(COPT => RQ.OPT);
|
||||
/* Установим новый флаг подстановки значений аргументов в запрос */
|
||||
if (ROPT.NSUBST_ARGS_VALS = 1) then
|
||||
ROPT.NSUBST_ARGS_VALS := 0;
|
||||
else
|
||||
ROPT.NSUBST_ARGS_VALS := 1;
|
||||
end if;
|
||||
/* Сохраняем обновленную настройку */
|
||||
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
|
||||
/* Переформируем SQL-выражение */
|
||||
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
|
||||
end QUERY_OPT_SUBST_ARGS_VALS_TGL;
|
||||
|
||||
end PKG_P8PANELS_QE;
|
||||
/
|
||||
|
||||
@ -17,7 +17,8 @@ create or replace package PKG_P8PANELS_QE_BASE as
|
||||
type TOPT is record
|
||||
(
|
||||
RARGS TARGS, -- Аргументы
|
||||
SCOND PKG_STD.TSTRING -- Условия отбора
|
||||
SCOND PKG_STD.TSTRING, -- Условия отбора
|
||||
NSUBST_ARGS_VALS PKG_STD.TNUMBER -- Флаг подстановки значений аргументов в запрос (1 - да, 0 - нет)
|
||||
);
|
||||
|
||||
/* Типы данных - Атрибут сущности */
|
||||
@ -365,6 +366,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
STAG_RL constant PKG_STD.TSTRING := 'XRL'; -- Связь
|
||||
STAG_OPT constant PKG_STD.TSTRING := 'XOPT'; -- Настройка запроса
|
||||
STAG_COND constant PKG_STD.TSTRING := 'XCOND'; -- Условия запроса
|
||||
STAG_SUBST_ARGS_VALS constant PKG_STD.TSTRING := 'XSUBST_ARGS_VALS'; -- Флаг подстановки значений аргументов в запрос
|
||||
STAG_QRY constant PKG_STD.TSTRING := 'XQRY'; -- SQL-выражение запроса
|
||||
STAG_QRY_MSG constant PKG_STD.TSTRING := 'XQRY_MSG'; -- Сообщение при формировании запроса
|
||||
|
||||
@ -770,6 +772,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
TARGS_TO_XML(RARGS => ROPT.RARGS);
|
||||
/* Условия отбора */
|
||||
PKG_XFAST.HERB(SNAME => STAG_COND, SVALUE => ROPT.SCOND);
|
||||
/* Флаг подстановки значений аргументов в запрос */
|
||||
PKG_XFAST.HERB(SNAME => STAG_SUBST_ARGS_VALS, NVALUE => ROPT.NSUBST_ARGS_VALS);
|
||||
/* Закрываем описание настройки */
|
||||
PKG_XFAST.UP();
|
||||
end TOPT_TO_XML;
|
||||
@ -798,6 +802,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
XNODE := PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XROOT, SPATTERN => '/' || STAG_OPT);
|
||||
/* Получаем значения */
|
||||
RRES.SCOND := PKG_XPATH.VALUE(RNODE => XNODE, SPATTERN => STAG_COND);
|
||||
RRES.NSUBST_ARGS_VALS := PKG_XPATH.VALUE_NUM(RNODE => XNODE, SPATTERN => STAG_SUBST_ARGS_VALS);
|
||||
RRES.RARGS := TARGS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XNODE,
|
||||
SPATTERN => STAG_ARGS)));
|
||||
/* Освободим документ */
|
||||
@ -2960,12 +2965,38 @@ create or replace package body PKG_P8PANELS_QE_BASE as
|
||||
if (ROPT.SCOND is not null) then
|
||||
PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'where ' || ROPT.SCOND);
|
||||
end if;
|
||||
if ((ROPT.NSUBST_ARGS_VALS = 1) and (ROPT.RARGS is not null) and (ROPT.RARGS.COUNT > 0)) then
|
||||
for I in ROPT.RARGS.FIRST .. ROPT.RARGS.LAST
|
||||
loop
|
||||
begin
|
||||
case
|
||||
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_STR then
|
||||
SQRY := PKG_SQL_BUILD.VAR_REPLACE_TO_STR(SSQL => SQRY,
|
||||
SNAME => ROPT.RARGS(I).SNAME,
|
||||
SVALUE => ROPT.RARGS(I).SVALUE);
|
||||
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_NUM then
|
||||
SQRY := PKG_SQL_BUILD.VAR_REPLACE_TO_NUM(SSQL => SQRY,
|
||||
SNAME => ROPT.RARGS(I).SNAME,
|
||||
NVALUE => TO_NUMBER(ROPT.RARGS(I).SVALUE));
|
||||
when ROPT.RARGS(I).NDATA_TYPE = PKG_STD.DATA_TYPE_DATE then
|
||||
SQRY := PKG_SQL_BUILD.VAR_REPLACE_TO_DATE(SSQL => SQRY,
|
||||
SNAME => ROPT.RARGS(I).SNAME,
|
||||
DVALUE => TO_DATE(ROPT.RARGS(I).SVALUE, 'yyyy-mm-dd'));
|
||||
else
|
||||
SQRY := PKG_SQL_BUILD.VAR_REPLACE_TO_ANY(SSQL => SQRY,
|
||||
SNAME => ROPT.RARGS(I).SNAME,
|
||||
SANY => ROPT.RARGS(I).SVALUE);
|
||||
end case;
|
||||
exception
|
||||
when others then
|
||||
ADD_QRY_MSG(SMESSAGE => 'Ошибка конвертации при подстановке значения "' || ROPT.RARGS(I).SVALUE ||
|
||||
'" в аргумент запроса "' || ROPT.RARGS(I).SNAME || '".',
|
||||
BCLEAR_QRY => false);
|
||||
end;
|
||||
end loop;
|
||||
end if;
|
||||
end BUILD_WHERE;
|
||||
begin
|
||||
/*
|
||||
TODO: owner="root" created="10.09.2025"
|
||||
text="Предусмотреть отладочные значения для аргументов запроса"
|
||||
*/
|
||||
/* Читаем описание запроса */
|
||||
RQ := QUERY_GET(NRN => NRN);
|
||||
/* Читаем сущности запроса */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user