Сервис LegacyXml2Select
LegacyXml2Select – это сервис, наследующий , который предоставляет возможность парсить XML-запросы, сформированные в стиле «формальных выборок», и генерировать соответствующие SQL SELECT-запросы к документам в БД. Основное назначение – обеспечить обратную совместимость со старыми механизмами поиска.ServiceRequire
Сервис состоит из нескольких компонентов:
- LegacyXml2Select – фасад, предоставляющий внешние методы.
- LegacyXml2SelectDb – сервис‑помощник для доступа к базе данных (получение метаданных, выполнение функций).
- LegacyXml2SelectInnerPg – ядро парсинга XML и построения SQL.
- PropertyBuilder – построитель условий для свойств документов.
- MacroParser – парсер макросов (функции, литералы).
- SqlQuery / WhereCondition – утилиты для программного конструирования SQL-выражений и оптимизации WHERE-условий.
Все компоненты располагаются в одном модуле и экспортируются как единое целое.
Сервис LegacyXml2Select
Назначение: Принимает XML‑строку, параметры режима запроса и прав доступа, преобразует её в объект SqlQuery (или сразу в SQL‑строку) и возвращает результат.
Зависимости
-
QueriesHelper– обязательный (указан вrequirements), предоставляет доступ к выполнению запросов к PostgreSQL. -
LegacyXml2SelectDb– обязательный (добавляется как вложенный сервис в конструкторе).
Методы (запросы)
parseToObj({ session, xml, queryMode=0, permissions=1 })
Преобразует XML в объект SqlQuery (без построения финального SQL‑текста).
Параметры:
-
session(объект, опционально) – должен содержатьuserId, используется для фильтрации прав. -
xml(string) – XML‑строка запроса. -
queryMode(number, по умолчанию0) – режим запроса:-
0– полный запрос (выбирает поля документа), -
1– подсчёт количества (COUNT), -
2– только идентификаторы документов, -
3‑6– специальные режимы (логика меняется).
-
-
permissions(number, по умолчанию1) – уровень проверки прав доступа (-1– без проверки,1– стандартная).
Возвращает: экземпляр SqlQuery.
parseToSql({ session, xml, queryMode=0, permissions=1 })
Выполняет parseToObj, а затем вызывает sql.build(), возвращая готовый SQL‑запрос.
Параметры: те же, что у parseToObj.
Возвращает: строку SQL.
macroParse({ macro })
Парсит строку‑макрос в абстрактное синтаксическое дерево.
Параметры:
-
macro(string) – строка, содержащая вызов функции, литерал или идентификатор.
Возвращает: объект с полем tree – AST макроса (например, { type: 'function', value: 'NOW', args: [] }).
Формат XML‑запроса для LegacyXml2Select
Сервис LegacyXml2Select преобразует XML‑описание выборки документов в SQL‑запрос SELECT.
Корневой элемент — <query>, внутри которого обязательно присутствует элемент <formal>, задающий условия фильтрации.
1. Корневая структура
<?xml version="1.0"?>
<query>
<formal dockind_id="ID_ВИДА_ДОКУМЕНТА" [name="and|or"]>
<!-- набор условий -->
</formal>
</query>
Атрибуты <formal>:
| Атрибут | Обязательный | Тип | Описание |
|---|---|---|---|
dockind_id |
да | integer | Идентификатор вида документа (dockind_id) целевой таблицы |
name |
нет | and/or |
Логическая операция, объединяющая все условия верхнего уровня (по умолчанию and) |
2. Элементы внутри <formal> и <reference>
Допускаются следующие элементы (в любом порядке и в любых сочетаниях):
| Элемент | Назначение |
|---|---|
<reference> |
Ссылка на другой документ / тип документа (JOIN / EXISTS) |
<property> |
Условие на значение свойства документа |
<status> |
Фильтр по статусу (виду события) документа |
<operation> |
Логическая группа условий (AND / OR) |
<select> |
(Зарезервирован; влияет на логику outer join, но вывод не меняет) |
Все они могут вкладываться внутрь <reference> и <operation>.
3. Элемент <reference>
Описывает переход к связанному документу через свойство‑ссылку. Реализуется либо как EXISTS/NOT EXISTS, либо как JOIN (в зависимости от атрибута referencing и режима запроса).
<reference
docprop_id="ID_СВОЙСТВА_ССЫЛКИ"
referencing="join|is null"
dockind_id="ID_ЦЕЛЕВОГО_ВИДА"
[condition="l|nl|g|ng|e|ne"]
[count="целое_число"]
[valuevar="строка"]
[leftp="строка"]
[rightp="строка"]
>
<!-- вложенные reference, property, status, operation -->
</reference>
| Атрибут | Обязат. | Тип | Значения / Описание |
|---|---|---|---|
docprop_id |
да | integer | Идентификатор свойства‑ссылки (из model_documents.doc_kind_properties) |
referencing |
да | строка | join – обычная связь, проверяется существование связанного документа;is null – анти‑связь, условие NOT EXISTS (связанного документа нет) |
dockind_id |
да | integer | Идентификатор вида документа, на который ссылаемся |
condition |
нет | l,nl,g,ng,e,ne |
Условие сравнения количества связанных документов (используется вместе с count; реализовано частично – вызывает ошибку) |
count |
нет | integer | Ожидаемое количество документов для сравнения (см. condition) |
valuevar |
нет | строка | Зарезервировано; в текущей реализации не используется |
leftp |
нет | строка | Зарезервировано; не используется |
rightp |
нет | строка | Зарезервировано; не используется |
Логика работы:
- Если внутри
<reference>нет ни вложенных<reference>,<property>,<status>,<operation>, ни<select>, и режим запроса = 4–6, то такой элемент приreferencing="join"или внешнем соединении превращается в условие1=1. - В остальных случаях для
<reference>генерируется подзапросEXISTS(илиNOT EXISTSприreferencing="is null"), в котором проверяется наличие связанных документов и дополнительно накладываются вложенные условия (свойства, статусы, другие ссылки). - При
referencing="join"и режимах 4–6 (специальные режимы отчётов) возможен сценарий сOUTER JOIN, но детали определяются вложенными условиями.
4. Элемент <property>
Задаёт фильтр по значению конкретного свойства документа (или по служебному идентификатору).
<property
docprop_id="ID_СВОЙСТВА"
condition="код_операции"
[doc_prop_value="значение"]
[valuevar="макрос"]
[value="значение"]
[type="s|t|n|d|v"]
[kindtype="число"]
/>
| Атрибут | Обязат. | Тип | Описание / Возможные значения |
|---|---|---|---|
docprop_id |
да | integer | Идентификатор свойства документа. Особые значения:-2 – ID документа (прямая выборка по document_id);-4 – дата события (event_date);-5, -6 – пользователь, породивший событие (event_user);-7 – описание документа (doc_descr). Остальные числа – обычные свойства из doc_kind_properties |
condition |
да | строка | Код операции сравнения (см. таблицу ниже) |
doc_prop_value |
нет* | строка | Непосредственное значение для сравнения. Допускается использование макросов (см. раздел 6). *Обязательно, если только не используется IS NULL/IS NOT NULL. |
valuevar |
нет | строка | Ссылка на переменную или макрос; если задана и condition != 'DIRECT', подменяет собой doc_prop_value. |
value |
нет | строка | Альтернативное значение (например, для работы со словарями; приоритет ниже doc_prop_value). |
type |
нет | символ | Тип свойства (берётся из БД, если не указан):s – строка, t – текст, n – число, d – дата, v – ссылка на словарь и т.п. |
kindtype |
нет | integer | Подтип свойства (берётся из БД). Влияет на построение условия (например, 4 – иерархический словарь, 10 – мультизначное свойство). |
Коды операций (condition) и их SQL‑эквиваленты:
| Код | SQL оператор | Примечание |
|---|---|---|
e |
= или IN |
IN используется для свойств типа v, t и kindtype=4 (словарь) |
ne |
<> или NOT IN |
аналогично |
l |
< |
|
nl |
>= |
|
g |
> |
|
ng |
<= |
|
like |
LIKE |
|
not like |
NOT LIKE |
|
in |
IN |
Только для строковых типов (s, t), если kindtype != 4 |
d |
DIRECT |
Специальный режим: прямое присоединение таблицы свойств без EXISTS (используется для docprop_id=-2) |
is null |
IS NULL |
|
is not null |
IS NOT NULL |
|
min |
MIN |
(зарезервировано, используется в агрегациях) |
max |
MAX |
(зарезервировано) |
Особые docprop_id:
-
-2(DIRECT): фильтр по идентификаторам документов.-
doc_prop_value– список ID через запятую, например"10,20,30". -
valuevar– имя функции, возвращающей массив ID (вызывается черезXml2SelectDb.execFunc).
-
-
-4: фильтр по дате события (event_date). Дляcondition='<=...'значение автоматически корректируется на конец дня. -
-5,-6: фильтр по пользователю события (event_user). -
-7: фильтр по текстовому описанию (doc_descr). Для операторовLIKE/NOT LIKE– сравнение без учёта регистра.
5. Элемент <status>
Фильтрация по статусу (виду события) документа.
<status doceventkind_id="ID_СОБЫТИЯ" />
Может встречаться многократно. Каждый экземпляр задаёт одно значение doceventkind_id.
В SQL формируется условие:
dt_{level}.doceventkind_id IN (0, список_ID_событий)
Если список событий в XML совпадает с полным набором событий для данного вида документа (или полный набор пуст), условие не добавляется (чтобы не перегружать запрос избыточным перечислением).
6. Элемент <operation>
Группирует несколько условий с заданной логической связкой.
<operation name="and|or">
<!-- reference, property, status, другие operation -->
</operation>
-
name="and"– все вложенные условия объединяются черезAND. -
name="or"– черезOR. - Атрибут
nameможно опустить; тогда элемент становится прозрачным контейнером (вложенные условия просто передаются на уровень выше без добавления собственной группы).
7. Элемент <select> (зарезервирован)
Присутствует в коде, но не влияет на итоговый SQL. Его наличие/отсутствие используется только во внутренней логике определения, нужно ли создавать OUTER JOIN.
Пример:
<select />
В текущей реализации его содержимое игнорируется.
8. Подстановка макросов в значениях
В атрибутах doc_prop_value, valuevar, value (а также @_valuevar у <reference>) могут использоваться макросы.
Поддерживаются следующие макросы (регистр важен):
| Макрос | Подстановка |
|---|---|
@USERID |
ID текущего пользователя (documents.get_user_id) |
@USERNAME |
Полное имя пользователя (Фамилия Имя Отчество) |
@ROLEID |
ID текущей роли пользователя (documents.get_role_id) |
@ROLENAME |
Название роли |
@DEPARTID |
Идентификатор подразделения пользователя |
@DATE |
Текущая дата/время (SYSDATE); может комбинироваться с функциями: @DATE+1, @DATE-7 и т.п. |
GET_USER_FILIALS |
Вызов функции GET_USER_FILIALS (и другие подобные) |
NOW, TODAY, WORKDAY, MONTHDAY, *YEAR* |
Вызов соответствующей функции БД, возвращающей дату |
Макросы распознаются по точному совпадению (@USERID) или по вхождению в строку (например, TO_DATE('@DATE','DD.MM.YYYY') приводит к подстановке SYSDATE).
Если значение начинается с буквы и содержит скобки (например, my_func(1,2)), то оно рассматривается как вызов функции БД и выполняется через Xml2SelectDb.execFunc или execDate.
9. Примеры
Простейший запрос (получить все документы вида 10)
<query>
<formal dockind_id="10" />
</query>
Фильтр по свойствам и статусу
<query>
<formal dockind_id="10" name="and">
<property docprop_id="100" condition="e" doc_prop_value="Иванов"/>
<property docprop_id="101" condition="g" doc_prop_value="1000"/>
<status doceventkind_id="3"/>
<status doceventkind_id="5"/>
</formal>
</query>
Ссылка на связанный документ
<query>
<formal dockind_id="10">
<reference docprop_id="200" referencing="join" dockind_id="20">
<property docprop_id="201" condition="like" doc_prop_value="%утверждён%"/>
</reference>
</formal>
</query>
Анти‑ссылка (NOT EXISTS)
<reference docprop_id="200" referencing="is null" dockind_id="20"/>
Использование макроса
<property docprop_id="102" condition="e" doc_prop_value="@USERID"/>
Группировка условий с OR
<operation name="or">
<property docprop_id="100" condition="e" doc_prop_value="A"/>
<property docprop_id="100" condition="e" doc_prop_value="B"/>
</operation>
Выборка по списку ID
<property docprop_id="-2" condition="d" doc_prop_value="101,205,330"/>
или через функцию:
<property docprop_id="-2" condition="d" valuevar="my_package.get_docs(55)"/>