diff --git a/app/panels/query_editor/components/inspector/inspector.js b/app/panels/query_editor/components/inspector/inspector.js
index 34d5124..04932c2 100644
--- a/app/panels/query_editor/components/inspector/inspector.js
+++ b/app/panels/query_editor/components/inspector/inspector.js
@@ -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
>
)}
-
+
);
};
@@ -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
diff --git a/app/panels/query_editor/components/inspector_query_area/hooks.js b/app/panels/query_editor/components/inspector_query_area/hooks.js
new file mode 100644
index 0000000..79dc68b
--- /dev/null
+++ b/app/panels/query_editor/components/inspector_query_area/hooks.js
@@ -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 };
diff --git a/app/panels/query_editor/components/inspector/query_area.js b/app/panels/query_editor/components/inspector_query_area/inspector_query_area.js
similarity index 75%
rename from app/panels/query_editor/components/inspector/query_area.js
rename to app/panels/query_editor/components/inspector_query_area/inspector_query_area.js
index 6db3b9d..eeaa004 100644
--- a/app/panels/query_editor/components/inspector/query_area.js
+++ b/app/panels/query_editor/components/inspector_query_area/inspector_query_area.js
@@ -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 = "" }) => {
{qry && (
-
- content_copy
-
+ <>
+
+ {substArgsVals === 1 ? "code_off" : "code"}
+
+
+ content_copy
+
+ >
)}
{expanded ? "expand_more" : "expand_less"}
@@ -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 };
diff --git a/app/panels/query_editor/hooks.js b/app/panels/query_editor/hooks.js
index 4d89f21..38d83c4 100644
--- a/app/panels/query_editor/hooks.js
+++ b/app/panels/query_editor/hooks.js
@@ -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 {
diff --git a/db/PKG_P8PANELS_QE.pck b/db/PKG_P8PANELS_QE.pck
index 88d0a23..2ed0b15 100644
--- a/db/PKG_P8PANELS_QE.pck
+++ b/db/PKG_P8PANELS_QE.pck
@@ -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;
/
diff --git a/db/PKG_P8PANELS_QE_BASE.pck b/db/PKG_P8PANELS_QE_BASE.pck
index d1aaf98..c1b5e10 100644
--- a/db/PKG_P8PANELS_QE_BASE.pck
+++ b/db/PKG_P8PANELS_QE_BASE.pck
@@ -16,8 +16,9 @@ create or replace package PKG_P8PANELS_QE_BASE as
/* Типы данных - Настройка запроса */
type TOPT is record
(
- RARGS TARGS, -- Аргументы
- SCOND PKG_STD.TSTRING -- Условия отбора
+ RARGS TARGS, -- Аргументы
+ SCOND PKG_STD.TSTRING, -- Условия отбора
+ NSUBST_ARGS_VALS PKG_STD.TNUMBER -- Флаг подстановки значений аргументов в запрос (1 - да, 0 - нет)
);
/* Типы данных - Атрибут сущности */
@@ -352,21 +353,22 @@ create or replace package body PKG_P8PANELS_QE_BASE as
SENT_TYPE_VIEW constant PKG_STD.TSTRING := 'VIEW'; -- Представление
/* Константы - Теги для сериализации */
- STAG_DATA constant PKG_STD.TSTRING := 'XDATA'; -- Данные
- STAG_QUERIES constant PKG_STD.TSTRING := 'XQUERIES'; -- Запросы
- STAG_QUERY constant PKG_STD.TSTRING := 'XQUERY'; -- Запрос
- STAG_ARGS constant PKG_STD.TSTRING := 'XARGS'; -- Аргументы запроса
- STAG_ARG constant PKG_STD.TSTRING := 'XARG'; -- Аргумент запроса
- STAG_ATTRS constant PKG_STD.TSTRING := 'XATTRS'; -- Атрибуты сущности
- STAG_ATTR constant PKG_STD.TSTRING := 'XATTR'; -- Атрибут сущности
- STAG_ENTS constant PKG_STD.TSTRING := 'XENTS'; -- Сущности
- STAG_ENT constant PKG_STD.TSTRING := 'XENT'; -- Сущность
- STAG_RLS constant PKG_STD.TSTRING := 'XRLS'; -- Связи
- STAG_RL constant PKG_STD.TSTRING := 'XRL'; -- Связь
- STAG_OPT constant PKG_STD.TSTRING := 'XOPT'; -- Настройка запроса
- STAG_COND constant PKG_STD.TSTRING := 'XCOND'; -- Условия запроса
- STAG_QRY constant PKG_STD.TSTRING := 'XQRY'; -- SQL-выражение запроса
- STAG_QRY_MSG constant PKG_STD.TSTRING := 'XQRY_MSG'; -- Сообщение при формировании запроса
+ STAG_DATA constant PKG_STD.TSTRING := 'XDATA'; -- Данные
+ STAG_QUERIES constant PKG_STD.TSTRING := 'XQUERIES'; -- Запросы
+ STAG_QUERY constant PKG_STD.TSTRING := 'XQUERY'; -- Запрос
+ STAG_ARGS constant PKG_STD.TSTRING := 'XARGS'; -- Аргументы запроса
+ STAG_ARG constant PKG_STD.TSTRING := 'XARG'; -- Аргумент запроса
+ STAG_ATTRS constant PKG_STD.TSTRING := 'XATTRS'; -- Атрибуты сущности
+ STAG_ATTR constant PKG_STD.TSTRING := 'XATTR'; -- Атрибут сущности
+ STAG_ENTS constant PKG_STD.TSTRING := 'XENTS'; -- Сущности
+ STAG_ENT constant PKG_STD.TSTRING := 'XENT'; -- Сущность
+ STAG_RLS constant PKG_STD.TSTRING := 'XRLS'; -- Связи
+ 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'; -- Сообщение при формировании запроса
/* Константы - Атрибуты для сериализации */
SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор
@@ -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;
@@ -797,9 +801,10 @@ 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.RARGS := TARGS_FROM_XML(CXML => PKG_XPATH.SERIALIZE_TO_CLOB(RNODE => PKG_XPATH.SINGLE_NODE(RPARENT_NODE => XNODE,
- SPATTERN => STAG_ARGS)));
+ 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)));
/* Освободим документ */
PKG_XPATH.FREE(RDOCUMENT => XDOC);
exception
@@ -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);
/* Читаем сущности запроса */