diff --git a/db/P8PNL_QE_QUERY.sql b/db/P8PNL_QE_QUERY.sql index 0eacf2c..8f4b204 100644 --- a/db/P8PNL_QE_QUERY.sql +++ b/db/P8PNL_QE_QUERY.sql @@ -14,7 +14,8 @@ create table P8PNL_QE_QUERY OPT clob, -- Настройка запроса ENTS clob, -- Сущности запроса RLS clob, -- Отношения сущностей запроса - QRY clob, -- Запрос + QRY 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), constraint C_P8PNL_QE_QUERY_NAME_NB check (rtrim(NAME) is not null), diff --git a/db/PKG_P8PANELS_QE.pck b/db/PKG_P8PANELS_QE.pck index d4a0fc3..da806b1 100644 --- a/db/PKG_P8PANELS_QE.pck +++ b/db/PKG_P8PANELS_QE.pck @@ -271,6 +271,8 @@ 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()); @@ -282,6 +284,9 @@ create or replace package body PKG_P8PANELS_QE as PKG_P8PANELS_QE_BASE.TENTS_ADD(RENTS => RENTS, SNAME => SNAME, STYPE => STYPE); /* Сохраняем обновленный набор сущностей */ 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); end QUERY_ENT_ADD; /* Удаление сущности из запроса */ @@ -295,6 +300,8 @@ 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()); @@ -328,6 +335,9 @@ create or replace package body PKG_P8PANELS_QE as PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS); /* Сохраняем обновленный набор связей */ 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); end QUERY_ENT_REMOVE; /* Установка координат сущности в редакторе диаграммы запроса */ @@ -382,7 +392,9 @@ create or replace package body PKG_P8PANELS_QE as RENTS PKG_P8PANELS_QE_BASE.TENTS; -- Коллекция существующих сущностей NENT_INDEX PKG_STD.TNUMBER; -- Индекс изменяемой сущности RATTRS PKG_P8PANELS_QE_BASE.TATTRS; -- Коллекция полученных атриубтов - RRLS PKG_P8PANELS_QE_BASE.TRLS; -- Коллекция существующих связей + 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()); @@ -424,6 +436,9 @@ create or replace package body PKG_P8PANELS_QE as PKG_P8PANELS_QE_BASE.QUERY_ENTS_SET(NRN => RQ.RN, RENTS => RENTS); /* Сохраняем обновленный набор связей */ 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); end QUERY_ENT_ATTRS_SET; /* Добавление связи в запрос */ @@ -436,6 +451,8 @@ 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()); @@ -447,6 +464,9 @@ create or replace package body PKG_P8PANELS_QE as PKG_P8PANELS_QE_BASE.TRLS_ADD(RRLS => RRLS, SSOURCE => SSOURCE, STARGET => STARGET); /* Сохраняем обновленный набор связей */ 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); end QUERY_RL_ADD; /* Удаление связи из запроса */ @@ -458,6 +478,8 @@ 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()); @@ -469,6 +491,9 @@ create or replace package body PKG_P8PANELS_QE as PKG_P8PANELS_QE_BASE.TRLS_REMOVE(RRLS => RRLS, SID => SID); /* Сохраняем обновленный набор связей */ 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); end QUERY_RL_REMOVE; /* Добавление аргумента запроса */ @@ -577,6 +602,8 @@ 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()); @@ -588,6 +615,9 @@ create or replace package body PKG_P8PANELS_QE as ROPT.SCOND := SCOND; /* Сохраняем обновленную настройку */ 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); end QUERY_OPT_COND_SET; end PKG_P8PANELS_QE; diff --git a/db/PKG_P8PANELS_QE_BASE.pck b/db/PKG_P8PANELS_QE_BASE.pck index 514784e..68f4609 100644 --- a/db/PKG_P8PANELS_QE_BASE.pck +++ b/db/PKG_P8PANELS_QE_BASE.pck @@ -301,6 +301,22 @@ create or replace package PKG_P8PANELS_QE_BASE as NRN in number, -- Рег. номер запроса ROPT in TOPT -- Настройка запроса ); + + /* Запись SQL-выражения запроса */ + procedure QUERY_QRY_SET + ( + NRN in number, -- Рег. номер запроса + CQRY in clob, -- SQL-выражение + CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) + ); + + /* Формирование SQL запроса */ + procedure QUERY_SQL_BUILD + ( + NRN in number, -- Рег. номер запроса + SQRY out varchar2, -- SQL-выражение + SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) + ); end PKG_P8PANELS_QE_BASE; / @@ -324,6 +340,8 @@ 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_QRY constant PKG_STD.TSTRING := 'XQRY'; -- SQL-выражение запроса + STAG_QRY_MSG constant PKG_STD.TSTRING := 'XQRY_MSG'; -- Сообщение при формировании запроса /* Константы - Атрибуты для сериализации */ SATTR_ID constant PKG_STD.TSTRING := 'id'; -- Идентификатор @@ -839,6 +857,33 @@ create or replace package body PKG_P8PANELS_QE_BASE as /* Вернём результат */ return RRES; end TATTR_FROM_XML; + + /* Поиск индекса атрибута по идентификатору */ + function TATTRS_INDEX_BY_ID + ( + RATTRS in TATTRS, -- Коллекция атрибутов + SID 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).SID = SID) then + return I; + end if; + exception + when NO_DATA_FOUND then + null; + end; + end loop; + end if; + /* Ничего не нашли */ + return null; + end TATTRS_INDEX_BY_ID; /* Поиск индекса атрибута по имени */ function TATTRS_INDEX_BY_NAME @@ -1212,6 +1257,33 @@ create or replace package body PKG_P8PANELS_QE_BASE as return null; end TENTS_INDEX_BY_ID; + /* Поиск индекса сущности по идентификатору атрибута */ + function TENTS_INDEX_BY_ATTR_ID + ( + RENTS in TENTS, -- Коллекция сущностей + SATTR_ID in varchar2 -- Искомый идентификатор атрибута + ) return number -- Индекс найденной сущности (null - если не найдено) + is + begin + /* Обходим коллекцию */ + if ((RENTS is not null) and (RENTS.COUNT > 0)) then + for I in RENTS.FIRST .. RENTS.LAST + loop + begin + /* Возвращаем найденный индекс */ + if (TATTRS_INDEX_BY_ID(RATTRS => RENTS(I).RATTRS, SID => SATTR_ID) is not null) then + return I; + end if; + exception + when NO_DATA_FOUND then + null; + end; + end loop; + end if; + /* Ничего не нашли */ + return null; + end TENTS_INDEX_BY_ATTR_ID; + /* Поиск номера сущности в коллекции */ function TENTS_NEXT_NUMB ( @@ -2071,6 +2143,10 @@ create or replace package body PKG_P8PANELS_QE_BASE as if (RQ.RLS is not null) then TRLS_TO_XML(RRLS => QUERY_RLS_FROM_XML(CXML => RQ.RLS)); end if; + /* SQL-выражение */ + PKG_XFAST.HERB(SNAME => STAG_QRY, LCVALUE => RQ.QRY); + /* Сообщение при формировании SQL-выражения */ + PKG_XFAST.HERB(SNAME => STAG_QRY_MSG, LCVALUE => RQ.QRY_MSG); /* Закрываем корень */ PKG_XFAST.UP(); /* Сериализуем */ @@ -2419,5 +2495,265 @@ create or replace package body PKG_P8PANELS_QE_BASE as QUERY_CH_DATE_SYNC(NRN => NRN); end QUERY_OPT_SET; + /* Запись SQL-выражения запроса */ + procedure QUERY_QRY_SET + ( + NRN in number, -- Рег. номер запроса + CQRY in clob, -- SQL-выражение + CQRY_MSG in clob -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) + ) + is + begin + /* Сохраним её */ + update P8PNL_QE_QUERY T + set T.QRY = CQRY, + T.QRY_MSG = CQRY_MSG + where T.RN = NRN; + /* Контроль изменения данных */ + if (sql%notfound) then + PKG_MSG.RECORD_NOT_FOUND(NDOCUMENT => NRN, SUNIT_TABLE => 'P8PNL_QE_QUERY'); + end if; + /* Обновим дату изменения запроса */ + QUERY_CH_DATE_SYNC(NRN => NRN); + end QUERY_QRY_SET; + + /* Формирование SQL запроса */ + procedure QUERY_SQL_BUILD + ( + NRN in number, -- Рег. номер запроса + SQRY out varchar2, -- SQL-выражение + SQRY_MSG out varchar2 -- Сообщение при формировании SQL-выражения (предупреждения и ошибки формирования) + ) + is + RQ P8PNL_QE_QUERY%rowtype; -- Запись запроса + RENTS TENTS; -- Сущности запроса + RRLS TRLS; -- Связи запроса + ROPT TOPT; -- Настройка запроса + + /* Кумулятивная установка сообщения формирования запроса */ + procedure SET_MSG + ( + SMESSAGE in varchar2, -- Текст сообщения + BCLEAR_QRY in boolean := true -- Флаг очистки сформированного запроса + ) + is + begin + if (BCLEAR_QRY) then + SQRY := null; + end if; + if (SQRY_MSG is null) then + SQRY_MSG := SMESSAGE; + else + SQRY_MSG := SQRY_MSG || CHR(10) || CHR(13) || SMESSAGE; + end if; + end SET_MSG; + + /* Поиск корневой (не имеет связей по выходу - т.е. нигде не является источником) сущности запроса */ + procedure FIND_ROOT_ENT + ( + RENTS TENTS, -- Сущности запроса + RRLS TRLS, -- Связи запроса + RENT out TENT, -- Найденная корневая сущность + SMESSAGE out varchar2 -- Сообщение от алгоритма поиска + ) + is + BFOUND boolean; -- Флаг наличия атрибута сущности в составе источникв связей запроса + begin + /* Если сущность одна - то она и главная */ + if (RENTS.COUNT = 1) then + RENT := RENTS(RENTS.FIRST); + end if; + /* Обходим все сущности */ + for E in RENTS.FIRST .. RENTS.LAST + loop + /* Сброс флага наличия атрибутов в источниках связей */ + BFOUND := false; + /* Обходим атрибуты сущности */ + for A in RENTS(E).RATTRS.FIRST .. RENTS(E).RATTRS.LAST + loop + /* Обойдем связи и поищем атрибут среди источников */ + for R in RRLS.FIRST .. RRLS.LAST + loop + if (RRLS(R).SSOURCE = RENTS(E).RATTRS(A).SID) then + BFOUND := true; + exit; + end if; + end loop; + /* Если хоть один атрибут сущности есть среди источников - дальше можно атрибуты этой сущности не рассматривать */ + exit when BFOUND = true; + end loop; + /* Если ни один из атрибутов не был источником - сущность наш клиент */ + if (not BFOUND) then + /* Если мы ещё не находили корневую сущность ранее */ + if (RENT.SID is null) then + RENT := RENTS(E); + else + /* Ранее была найдена корневая сущность */ + SMESSAGE := 'В запросе более одной корневой (без выходных связей) сущности.'; + return; + end if; + end if; + end loop; + /* Проверим, что хоть что-то нашли */ + if (RENT.SID is null) then + SMESSAGE := 'В запросе нет корневой (без выходных связей) сущности.'; + end if; + end FIND_ROOT_ENT; + + /* Формирование части "select" */ + procedure BUILD_SELECT + ( + RENTS TENTS, -- Сущности запроса + SQRY in out varchar2 -- Буфер для запроса + ) + is + SFIELD PKG_STD.TSTRING; -- Буфер для поля запроса + begin + PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'select '); + for I in RENTS.FIRST .. RENTS.LAST + loop + if ((RENTS(I).RATTRS is not null) and (RENTS(I).RATTRS.COUNT > 0)) then + for J in RENTS(I).RATTRS.FIRST .. RENTS(I).RATTRS.LAST + loop + if (RENTS(I).RATTRS(J).NSHOW = 1) then + SFIELD := RENTS(I).RATTRS(J).SID || ' ' || RENTS(I).RATTRS(J).SNAME || I || J; + if (not ((I = RENTS.LAST) and (J = RENTS(I).RATTRS.LAST))) then + SFIELD := SFIELD || ', '; + end if; + PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => SFIELD); + end if; + end loop; + end if; + end loop; + end BUILD_SELECT; + + /* Формирование иерархии связей в секции "from" */ + procedure BUILD_FROM_HIER + ( + RENT_START TENT, -- Начало ветки + RENTS TENTS, -- Сущности запроса + RRLS TRLS, -- Связи запроса + SQRY in out varchar2 -- Буфер для запроса + ) + is + NENT_SRC PKG_STD.TNUMBER; -- Индекс сущности-источника связи + STABLE PKG_STD.TSTRING; -- Буфер для таблицы запроса + begin + /* Обходим связи */ + for I in RRLS.FIRST .. RRLS.LAST + loop + /* Если это связь, в которой приёмником является стартовая сущность */ + if (TATTRS_INDEX_BY_ID(RATTRS => RENT_START.RATTRS, SID => RRLS(I).STARGET) is not null) then + /* Найдем сущность-источник связи по атрибуту-источнику связи */ + NENT_SRC := TENTS_INDEX_BY_ATTR_ID(RENTS => RENTS, SATTR_ID => RRLS(I).SSOURCE); + if (NENT_SRC is null) then + P_EXCEPTION(0, + 'Для связи "%s - %s" не удалось определить сущность-источник.', + RRLS (I) + .SSOURCE, + RRLS (I) + .STARGET); + end if; + /* Соберем выражение и добавим его в запрос */ + STABLE := 'left join ' || RENTS(NENT_SRC).SNAME || ' ' || RENTS(NENT_SRC).SID || ' on ' || RRLS(I).STARGET || + ' = ' || RRLS(I).SSOURCE; + PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => STABLE); + /* Добавим связи сущности-источника */ + BUILD_FROM_HIER(RENT_START => RENTS(NENT_SRC), RENTS => RENTS, RRLS => RRLS, SQRY => SQRY); + end if; + end loop; + end BUILD_FROM_HIER; + + /* Формирование части "from" */ + procedure BUILD_FROM + ( + RENTS TENTS, -- Сущности запроса + RRLS TRLS, -- Связи запроса + SQRY in out varchar2 -- Буфер для запроса + ) + is + RENT_ROOT TENT; -- Корневая сущность запроса + STABLE PKG_STD.TSTRING; -- Буфер для таблицы запроса + SMESSAGE PKG_STD.TSTRING; -- Буфер для сообщений + begin + /* Определяем корневую сущность запроса */ + FIND_ROOT_ENT(RENTS => RENTS, RRLS => RRLS, RENT => RENT_ROOT, SMESSAGE => SMESSAGE); + /* Продолжаем только если корневую успешно определили */ + if ((RENT_ROOT.SID is not null) and (SMESSAGE is null)) then + PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'from '); + STABLE := RENT_ROOT.SNAME || ' ' || RENT_ROOT.SID; + PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => STABLE); + if (RRLS.COUNT > 0) then + BUILD_FROM_HIER(RENT_START => RENT_ROOT, RENTS => RENTS, RRLS => RRLS, SQRY => SQRY); + end if; + else + /* Корневую сущность не нашли */ + SET_MSG(SMESSAGE => SMESSAGE, BCLEAR_QRY => false); + end if; + end BUILD_FROM; + + /* Формирование части "where" */ + procedure BUILD_WHERE + ( + ROPT TOPT, -- Настройка запроса + SQRY in out varchar2 -- Буфер для запроса + ) + is + begin + if (ROPT.SCOND is not null) then + PKG_SQL_BUILD.APPEND(SSQL => SQRY, SELEMENT1 => 'where ' || ROPT.SCOND); + end if; + end BUILD_WHERE; + begin + /* + TODO: owner="root" created="09.09.2025" + text="Контроль длины псевдонима таблицы и поля (максимум 30 символов)" + */ + /* + TODO: owner="root" created="10.09.2025" + text="Предусмотреть связям признак ""обязательность"" + с ним - join + без него - left join" + */ + /* + TODO: owner="root" created="10.09.2025" + text="Предусмотреть отладочные значения для аргументов запроса" + */ + /* + TODO: owner="root" created="11.09.2025" + text="Проверять соответствие условий отбора запроса набору его аргументов" + */ + /* Читаем описание запроса */ + RQ := QUERY_GET(NRN => NRN); + /* Читаем сущности запроса */ + RENTS := QUERY_ENTS_GET(CENTS => RQ.ENTS); + /* Нет сущностей - нет запроса */ + if ((RENTS is null) and (RENTS.COUNT = 0)) then + SET_MSG(SMESSAGE => 'В запросе нет сущностей.'); + return; + end if; + /* Читаем связи запроса */ + RRLS := QUERY_RLS_GET(CRLS => RQ.RLS); + /* Нельзя построить запрос, если есть несвязанные сущности */ + if ((RENTS.COUNT > 1) and (RENTS.COUNT - 1 > RRLS.COUNT)) then + SET_MSG(SMESSAGE => 'В запросе есть несвязанные сущности.'); + return; + end if; + /* Читаем настройку запроса */ + ROPT := QUERY_OPT_GET(COPT => RQ.OPT); + /* Добавляем подсказку совместимости */ + SQRY := PKG_SQL_BUILD.COMPATIBLE(SSQL => SQRY); + /* Собираем запрос - поля */ + BUILD_SELECT(RENTS => RENTS, SQRY => SQRY); + /* Собираем запрос - таблицы и связи */ + BUILD_FROM(RENTS => RENTS, RRLS => RRLS, SQRY => SQRY); + /* Собираем запрос - условия */ + BUILD_WHERE(ROPT => ROPT, SQRY => SQRY); + exception + when others then + PKG_STATE.DIAGNOSTICS_STACKED(); + SET_MSG(SMESSAGE => PKG_STATE.SQL_ERRM(), BCLEAR_QRY => false); + end QUERY_SQL_BUILD; + end PKG_P8PANELS_QE_BASE; /