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

This commit is contained in:
Mikhail Chechnev 2025-10-13 16:27:51 +03:00
parent db5bf1f72c
commit 63e3d3833e
2 changed files with 76 additions and 44 deletions

View File

@ -281,8 +281,6 @@ create or replace package body PKG_P8PANELS_QE as
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -295,8 +293,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор сущностей */
PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_ENT_ADD;
/* Удаление сущности из запроса */
@ -310,8 +307,6 @@ create or replace package body PKG_P8PANELS_QE as
RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей
RENT PKG_P8PANELS_QE_BASE.TENT; -- Удаляемая сущность
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -346,8 +341,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_ENT_REMOVE;
/* Установка координат сущности в редакторе диаграммы запроса */
@ -404,8 +398,6 @@ create or replace package body PKG_P8PANELS_QE as
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
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -453,8 +445,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_ENT_ATTRS_SET;
/* Добавление связи в запрос */
@ -467,8 +458,6 @@ create or replace package body PKG_P8PANELS_QE as
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -481,8 +470,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_RL_ADD;
/* Удаление связи из запроса */
@ -494,8 +482,6 @@ create or replace package body PKG_P8PANELS_QE as
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -508,8 +494,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_RL_REMOVE;
/* Установка признака обязательности связи */
@ -522,8 +507,6 @@ create or replace package body PKG_P8PANELS_QE as
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Читаем запись запроса */
RQ := PKG_P8PANELS_QE_BASE.QUERY_GET(NRN => NRN);
@ -534,8 +517,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленный набор связей */
PKG_P8PANELS_QE_BASE.QUERY_RLS_SET(NRN => RQ.RN, RRLS => RRLS);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_RL_MANDATORY_SET;
/* Добавление аргумента запроса */
@ -567,6 +549,8 @@ create or replace package body PKG_P8PANELS_QE as
SVALUE => SVALUE);
/* Сохраняем обновленную настройку */
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_ARG_ADD;
/* Изменение аргумента запроса */
@ -608,6 +592,8 @@ create or replace package body PKG_P8PANELS_QE as
SVALUE => SVALUE);
/* Сохраняем обновленную настройку */
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_ARG_EDIT;
/* Удаление аргумента запроса */
@ -637,6 +623,8 @@ create or replace package body PKG_P8PANELS_QE as
PKG_P8PANELS_QE_BASE.TARGS_REMOVE(RARGS => ROPT.RARGS, SNAME => SNAME);
/* Сохраняем обновленную настройку */
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_ARG_REMOVE;
/* Установка условий отбора запроса */
@ -648,8 +636,6 @@ create or replace package body PKG_P8PANELS_QE as
is
RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса
ROPT PKG_P8PANELS_QE_BASE.TOPT; -- Настройка запроса
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Провим права доступа */
PKG_P8PANELS_QE_BASE.QUERY_ACCESS_MODIFY(NRN => NRN, SUSER => UTILIZER());
@ -662,8 +648,7 @@ create or replace package body PKG_P8PANELS_QE as
/* Сохраняем обновленную настройку */
PKG_P8PANELS_QE_BASE.QUERY_OPT_SET(NRN => RQ.RN, ROPT => ROPT);
/* Переформируем SQL-выражение */
PKG_P8PANELS_QE_BASE.QUERY_SQL_BUILD(NRN => RQ.RN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_SET(NRN => RQ.RN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
PKG_P8PANELS_QE_BASE.QUERY_QRY_REFRESH(NRN => RQ.RN);
end QUERY_OPT_COND_SET;
end PKG_P8PANELS_QE;

View File

@ -329,12 +329,10 @@ create or replace package PKG_P8PANELS_QE_BASE as
ROPT in TOPT -- Настройка запроса
);
/* Запись SQL-выражения запроса */
procedure QUERY_QRY_SET
/* Обновление SQL-выражения запроса */
procedure QUERY_QRY_REFRESH
(
NRN in number, -- Рег. номер запроса
CQRY in clob, -- SQL-выражение
CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования)
NRN in number -- Рег. номер запроса
);
/* Формирование SQL запроса */
@ -2706,6 +2704,21 @@ create or replace package body PKG_P8PANELS_QE_BASE as
QUERY_CH_DATE_SYNC(NRN => NRN);
end QUERY_QRY_SET;
/* Обновление SQL-выражения запроса */
procedure QUERY_QRY_REFRESH
(
NRN in number -- Рег. номер запроса
)
is
SQRY PKG_STD.TLSTRING; -- SQL-выражение запроса
SQRY_MSG PKG_STD.TLSTRING; -- Сообщение при формировании SQL-выражения
begin
/* Сформируем SQL-выражение */
QUERY_SQL_BUILD(NRN => NRN, SQRY => SQRY, SQRY_MSG => SQRY_MSG);
/* Обновим его в запросе */
QUERY_QRY_SET(NRN => NRN, CQRY => SQRY, CQRY_MSG => SQRY_MSG);
end QUERY_QRY_REFRESH;
/* Формирование SQL запроса */
procedure QUERY_SQL_BUILD
(
@ -2720,7 +2733,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
ROPT TOPT; -- Настройка запроса
/* Кумулятивная установка сообщения формирования запроса */
procedure SET_MSG
procedure ADD_QRY_MSG
(
SMESSAGE in varchar2, -- Текст сообщения
BCLEAR_QRY in boolean := true -- Флаг очистки сформированного запроса
@ -2735,7 +2748,37 @@ create or replace package body PKG_P8PANELS_QE_BASE as
else
SQRY_MSG := SQRY_MSG || CHR(10) || CHR(13) || SMESSAGE;
end if;
end SET_MSG;
end ADD_QRY_MSG;
/* Проверка соответствия условий запроса набору его аргументов */
procedure CHECK_COND_ARGS
(
ROPT TOPT -- Настройка запроса
)
is
RCOND_VARS PKG_CONTVARLOC.TCONTAINER; -- Коллекция переменных условия запроса
SCOND_VAR PKG_STD.TSTRING; -- Текущая переменная условия запроса
begin
/* Извлечен переменные из условия запроса */
RCOND_VARS := PKG_SQL_BUILD.VAR_LIST(SSQL => ROPT.SCOND);
/* Если переменные в условии есть */
if (PKG_CONTVARLOC.COUNT_(RCONTAINER => RCOND_VARS) > 0) then
/* Обходим их */
SCOND_VAR := PKG_CONTVARLOC.FIRST_(RCONTAINER => RCOND_VARS);
while (SCOND_VAR is not null)
loop
/* Проверяем вхождение текущей переменной в состав аргументов запроса */
if (TARGS_INDEX_BY_NAME(RARGS => ROPT.RARGS, SNAME => SCOND_VAR) is null) then
/* В аргументах такой нет - добавляем предупреждение */
ADD_QRY_MSG(SMESSAGE => 'Переменная условия запроса "' || SCOND_VAR ||
'" отсутствует в составе его аргументов.',
BCLEAR_QRY => false);
end if;
/* Ищем следующу */
SCOND_VAR := PKG_CONTVARLOC.NEXT_(RCONTAINER => RCOND_VARS, SNAME => SCOND_VAR);
end loop;
end if;
end CHECK_COND_ARGS;
/* Поиск корневой (не имеет связей по выходу - т.е. нигде не является источником) сущности запроса */
procedure FIND_ROOT_ENT
@ -2898,7 +2941,7 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end if;
else
/* Корневую сущность не нашли */
SET_MSG(SMESSAGE => SMESSAGE, BCLEAR_QRY => false);
ADD_QRY_MSG(SMESSAGE => SMESSAGE, BCLEAR_QRY => false);
end if;
end BUILD_FROM;
@ -2916,12 +2959,14 @@ create or replace package body PKG_P8PANELS_QE_BASE as
end BUILD_WHERE;
begin
/*
TODO: owner="root" created="10.09.2025"
text="Предусмотреть отладочные значения для аргументов запроса"
TODO: owner="root" created="13.10.2025"
text="Контроль имен аргументов запроса: только латинские и фифры и подчеркивание, начинать только с буквы.
Принудительный APPERCASE
Контроль уникальности имени аргумента"
*/
/*
TODO: owner="root" created="11.09.2025"
text="Проверять соответствие условий отбора запроса набору его аргументов"
TODO: owner="root" created="10.09.2025"
text="Предусмотреть отладочные значения для аргументов запроса"
*/
/* Читаем описание запроса */
RQ := QUERY_GET(NRN => NRN);
@ -2929,18 +2974,20 @@ create or replace package body PKG_P8PANELS_QE_BASE as
RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS);
/* Нет сущностей - нет запроса */
if ((RENTS is null) or (RENTS.COUNT = 0)) then
SET_MSG(SMESSAGE => 'В запросе нет сущностей.');
ADD_QRY_MSG(SMESSAGE => 'В запросе нет сущностей.');
return;
end if;
/* Читаем связи запроса */
RRLS := QUERY_RLS_GET(CRLS => RQ.RLS);
/* Нельзя построить запрос, если есть несвязанные сущности */
if ((RENTS.COUNT > 1) and ((RRLS is null) or (RENTS.COUNT - 1 > RRLS.COUNT))) then
SET_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.');
ADD_QRY_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.');
return;
end if;
/* Читаем настройку запроса */
ROPT := QUERY_OPT_GET(COPT => RQ.OPT);
/* Проверяем параметры запроса */
CHECK_COND_ARGS(ROPT => ROPT);
/* Добавляем подсказку совместимости */
SQRY := PKG_SQL_BUILD.COMPATIBLE(SSQL => SQRY);
/* Собираем запрос - поля */
@ -2952,8 +2999,8 @@ create or replace package body PKG_P8PANELS_QE_BASE as
exception
when others then
PKG_STATE.DIAGNOSTICS_STACKED();
SET_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false);
ADD_QRY_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false);
end QUERY_SQL_BUILD;
end PKG_P8PANELS_QE_BASE;
/