ЦИТК-979 - Редактор условия запроса - раздельное хранение канонического SQL-выражения и выражения с подстановками

This commit is contained in:
Mikhail Chechnev 2025-10-14 19:21:18 +03:00
parent 6efbb8508c
commit d446fd96ab
5 changed files with 65 additions and 35 deletions

View File

@ -34,6 +34,7 @@ const Inspector = ({
cond = null,
substArgsVals = 0,
qry = "",
qryBnd = "",
qryMsg = "",
onOptionsChanged = null
}) => {
@ -55,7 +56,7 @@ const Inspector = ({
<InspectorQueryRelations query={query} relation={relation} onOptionsChanged={handleOptionsChanged} />
</>
)}
<InspectorQueryArea query={query} substArgsVals={substArgsVals} qry={qry} qryMsg={qryMsg} onOptionsChanged={handleOptionsChanged} />
<InspectorQueryArea query={query} substArgsVals={substArgsVals} qry={qry} qryBnd={qryBnd} qryMsg={qryMsg} />
</P8PEditorBox>
);
};
@ -70,6 +71,7 @@ Inspector.propTypes = {
cond: PropTypes.string,
substArgsVals: PropTypes.number,
qry: PropTypes.string,
qryBnd: PropTypes.string,
qryMsg: PropTypes.string,
onOptionsChanged: PropTypes.func
};

View File

@ -7,7 +7,7 @@
//Подключение библиотек
//---------------------
import React, { useState } from "react"; //Классы React
import React, { useState, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Fab, Icon, Drawer, IconButton, TextField, Stack, Box, Snackbar, Alert } from "@mui/material"; //Компоненты MUI
import { BUTTONS } from "../../../../../app.text"; //Общие текстовые ресурсы приложения
@ -40,7 +40,10 @@ const SNACK_BAR_MESSAGE_INIT = { text: null, type: null };
//-----------
//Область SQL-выражения
const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryMsg = "", onOptionsChanged }) => {
const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryBnd = "", qryMsg = "" }) => {
//Собственное состояние - отображение запроса с подстановками
const [showQryBnd, setShowQryBnd] = useState(substArgsVals);
//Собственное состояние - текст всплывающего сообщения
const [snackBarMessage, setSnackBarMessage] = useState(SNACK_BAR_MESSAGE_INIT);
@ -53,13 +56,10 @@ const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryMsg = "", o
//Работа с SQL-выражением
const { toggleSubstArgsVals } = useQuerySQLExpr(query);
//Уведомление родителя об изменении свойств
const notifyOptionsChanged = () => onOptionsChanged && onOptionsChanged();
//При нажатии на кнопку отображения/сокрытия значений аргументов в SQL-выражении запроса
const handleToggleSubstArgsValsClick = async () => {
await toggleSubstArgsVals();
notifyOptionsChanged();
setShowQryBnd(showQryBnd === 1 ? 0 : 1);
};
//При нажатии на кнопку копирования текста запроса
@ -87,6 +87,13 @@ const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryMsg = "", o
//Расчет размеров тектовых полей
const [qryRows, qryMsgRows] = expanded ? [15, 6] : [5, 3];
//Расчет параметров отображения запроса
const [dispQry, qryViewTitle, qryViewIcon] =
showQryBnd === 0 ? [qry, "Отобразить значения аргументов", "code"] : [qryBnd, "Скрыть значения аргументов", "code_off"];
//При изменении состояние отображения подстановок в запросе
useEffect(() => setShowQryBnd(substArgsVals), [substArgsVals]);
//Генерация содержимого
return (
<>
@ -101,11 +108,8 @@ const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryMsg = "", o
<Stack direction={"row"} justifyContent={"right"} spacing={2}>
{qry && (
<>
<IconButton
onClick={handleToggleSubstArgsValsClick}
title={substArgsVals === 1 ? "Скрыть значения аргументов" : "Отобразить значения аргументов"}
>
<Icon>{substArgsVals === 1 ? "code_off" : "code"}</Icon>
<IconButton onClick={handleToggleSubstArgsValsClick} title={qryViewTitle}>
<Icon>{qryViewIcon}</Icon>
</IconButton>
<IconButton onClick={handleCopyClick} title={"Скопировать текст запроса"}>
<Icon>content_copy</Icon>
@ -120,12 +124,12 @@ const InspectorQueryArea = ({ query, substArgsVals = 0, qry = "", qryMsg = "", o
</IconButton>
</Stack>
<Stack direction={"column"} spacing={2}>
{qry && (
{dispQry && (
<TextField
label={"Текст запроса"}
multiline
fullWidth
value={qry}
value={dispQry}
minRows={qryRows}
maxRows={qryRows}
variant={"standard"}
@ -165,8 +169,8 @@ InspectorQueryArea.propTypes = {
query: PropTypes.number.isRequired,
substArgsVals: PropTypes.number,
qry: PropTypes.string,
qryMsg: PropTypes.string,
onOptionsChanged: PropTypes.func
qryBnd: PropTypes.string,
qryMsg: PropTypes.string
};
//----------------

View File

@ -144,7 +144,7 @@ const useQuery = query => {
cond: data?.XOPT?.XCOND || null,
substArgsVals: data?.XOPT?.XSUBST_ARGS_VALS || 0
});
setQuerySQL({ qry: data?.XQRY, qryMsg: data?.XQRY_MSG });
setQuerySQL({ qry: data?.XQRY, qryBnd: data?.XQRY_BND, qryMsg: data?.XQRY_MSG });
setInit(true);
} finally {
setRefresh(false);

View File

@ -15,6 +15,7 @@ create table P8PNL_QE_QUERY
ENTS clob, -- Сущности запроса
RLS clob, -- Отношения сущностей запроса
QRY clob, -- Запрос (SQL выражение)
QRY_BND clob, -- Запрос (SQL выражение) с подставленными значениями аргументов
QRY_MSG clob, -- Сообщение при формировании запроса (предупреждения и ошибки формирования)
constraint C_P8PNL_QE_QUERY_RN_PK primary key (RN),
constraint C_P8PNL_QE_QUERY_CODE_NB check (rtrim(CODE) is not null),

View File

@ -341,6 +341,7 @@ create or replace package PKG_P8PANELS_QE_BASE as
(
NRN in number, -- Рег. номер запроса
SQRY out varchar2, -- SQL-выражение
SQRY_BND out varchar2, -- SQL-выражение с подставленными значениями аргументов
SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
);
@ -368,6 +369,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
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_BND constant PKG_STD.TSTRING := 'XQRY_BND'; -- SQL-выражение запроса с подстановками
STAG_QRY_MSG constant PKG_STD.TSTRING := 'XQRY_MSG'; -- Сообщение при формировании запроса
/* Константы - Атрибуты для сериализации */
@ -2341,6 +2343,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end if;
/* SQL-выражение */
PKG_XFAST.HERB(SNAME => STAG_QRY, LCVALUE => RQ.QRY);
/* SQL-выражение с подстановками */
PKG_XFAST.HERB(SNAME => STAG_QRY_BND, LCVALUE => RQ.QRY_BND);
/* Сообщение при формировании SQL-выражения */
PKG_XFAST.HERB(SNAME => STAG_QRY_MSG, LCVALUE => RQ.QRY_MSG);
/* Закрываем корень */
@ -2696,6 +2700,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
(
NRN in number, -- Рег. номер запроса
CQRY in clob, -- SQL-выражение
CQRY_BND in clob, -- SQL-выражение с подставленными значениями аргументов
CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
)
is
@ -2703,6 +2708,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
/* Сохраним её */
update P8PNL_QE_QUERY T
set T.QRY = CQRY,
T.QRY_BND = CQRY_BND,
T.QRY_MSG = CQRY_MSG
where T.RN = NRN;
/* Контроль изменения данных */
@ -2720,12 +2726,13 @@ create or replace package body PKG_P8PANELS_QE_BASE as
)
is
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_BND PKG_STD.TLSTRING; -- SQL-выражение запроса с подстановками
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Сформируем SQL-выражение */
QUERY_SQL_BUILD(NRN => NRN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
QUERY_SQL_BUILD(NRN => NRN, SQRY => SQRY, SQRY_BND => SQRY_BND, SQRY_MSG => SQRY_MSG);
/* Обновим его в запросе */
QUERY_QRY_SET(NRN => NRN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
QUERY_QRY_SET(NRN => NRN, CQRY => SQRY, CQRY_BND => SQRY_BND, CQRY_MSG => SQRY_MSG);
end QUERY_QRY_REFRESH;
/* Формирование SQL запроса */
@ -2733,6 +2740,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
(
NRN in number, -- Рег. номер запроса
SQRY out varchar2, -- SQL-выражение
SQRY_BND out varchar2, -- SQL-выражение с подставленными значениями аргументов
SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
)
is
@ -2750,7 +2758,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
is
begin
if (BCLEAR_QRY) then
SQRY := null;
SQRY := null;
SQRY_BND := null;
end if;
if (SQRY_MSG is null) then
SQRY_MSG := SMESSAGE;
@ -2964,28 +2973,40 @@ create or replace package body PKG_P8PANELS_QE_BASE as
begin
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
end if;
end BUILD_WHERE;
/* Подстановка отладочных значений в SQL-выражение */
procedure BOUND
(
ROPT TOPT, -- Настройка запроса
SQRY in varchar2, -- Сформированное SQL-выражение
SQRY_BND out varchar2 -- SQL-выражение с подстановками
)
is
begin
SQRY_BND := SQRY;
if ((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);
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_STR(SSQL => SQRY_BND,
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));
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_NUM(SSQL => SQRY_BND,
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'));
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_DATE(SSQL => SQRY_BND,
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);
SQRY_BND := PKG_SQL_BUILD.VAR_REPLACE_TO_ANY(SSQL => SQRY_BND,
SNAME => ROPT.RARGS(I).SNAME,
SANY => ROPT.RARGS(I).SVALUE);
end case;
exception
when others then
@ -2995,7 +3016,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end;
end loop;
end if;
end BUILD_WHERE;
end BOUND;
begin
/* Читаем описание запроса */
RQ := QUERY_GET(NRN => NRN);
@ -3025,6 +3046,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
BUILD_FROM(RENTS => RENTS, RRLS => RRLS, SQRY => SQRY);
/* Собираем запрос - условия */
BUILD_WHERE(ROPT => ROPT, SQRY => SQRY);
/* Сделаем подстановки */
BOUND(ROPT => ROPT, SQRY => SQRY, SQRY_BND => SQRY_BND);
exception
when others then
PKG_STATE.DIAGNOSTICS_STACKED();