Керування логічними операторами у критеріях пошуку
🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію. |
1. Загальний опис
У цій статті буде розглянута реалізація можливості моделювальника керувати яким логічним оператором, OR чи AND, будуть об’єднуватись параметри пошуку та в якому порядку вони будуть визначатися.
2. Актори та ролі користувачів
-
Розробник регламенту
3. Загальні принципи та положення
-
Поведінка і контракт існуючих критеріїв пошуку не змінюється.
-
Зберігається зворотня сумісність конфігурації критеріїв пошуку.
4. Функціональні сценарії
-
Налаштування критеріїв пошуку
-
Генерація сервісів критеріїв пошуку
5. Поточна реалізація
У критеріях пошуку ви можете задавати поля, за якими відбуватиметься пошук, через атрибут searchType
тегу ext:column
.
Наприклад, для критерію пошуку визначеного наступним чином
<changeSet author="registry owner" id="create SC">
<ext:createSearchCondition name="dictionary">
<ext:table name="dict" alias="d">
<ext:column name="name" searchType="startsWith" />
<ext:column name="live" searchType="equal" />
<ext:column name="id" searchType="equal" />
<ext:column name="description"/>
</ext:table>
</ext:createSearchCondition>
</changeSet>
при визові, за умови що передані всі параметри, буде сформовано наступний рядок пошуку який об’єднає всі параметри оператором AND
name like '$1%' AND live = $2 AND id = $3
За контрактом API критеріїв пошуку, параметри пошуку є необов’язковими, тому якщо параметр не переданий він не потрапляє до рядка пошуку. Наприклад, якщо не переданий параметр id
, то рядок пошуку сформується без нього
name like '$1%' AND live = $2
В будь якому разі всі параметри об’єднуються оператором AND
, та моделювальник регламенту не має можливості це змінити.
6. Цільовий дизайн
6.1. Схема та модуль розширення тегів Liquibase
В схемі розширених тегів до дозволених дочірніх елементів тегу ext:table
з типом tableSearchConditionType
(той що використовується для саме таблиць, а не однойменний тег що використовується в CTE і має інший тип) додається елемент ext:logicOperator
нового типу tableLogicOperatorType
. Він має один обов’язковий атрибут type
- тип логічного оператору or
чи and
, та може вміщувати елементи ext:column
та ext:logicOperator
тобто сам себе.
<xsd:complexType name="tableLogicOperatorType">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="column" type="columnSearchConditionType" maxOccurs="unbounded"/>
<xsd:element name="logicOperator" type="tableLogicOperatorType" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="type" type="logicOperatorType" use="required"/>
</xsd:complexType>
....
<xsd:complexType name="tableSearchConditionType">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="column" type="columnSearchConditionType" maxOccurs="unbounded"/>
<xsd:element name="function" type="functionType" maxOccurs="unbounded"/>
<xsd:element name="logicOperator" type="tableLogicOperatorType" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="alias" type="xsd:string" use="optional"/>
</xsd:complexType>
В модуль розширення тегів Liquibase додається можливість запису всіє, необхідної для генерації сервісу, інформації про теги ext:logicOperator
в таблицю метаданих ddm_liquibase_metadata
, при обробці тегу createSearchCondition.
Розміщення тегів ext:column
без атрибуту searchType
всередині тегу ext:logicOperator
забороняється.
6.2. Сервіс генератор
Тег ext:logicOperator
керує тим, умови по яким колонкам беруться в дужки та який оператор використовується для поєднання цих умов у дужках. Тобто відкриття тегу еквівалентно відкриттю дужки та закриття тегу закриттю дужки в результуючему запиті до БД, а атрибут type
вказує на те який логічний оператор використовувати.
При реалізації алгоритму потрібно мати на увазі наступні правила:
-
Умови пошуку першого рівня
ext:table
об’єднуються операторомand
, так само як і до змін. -
Між різними таблицями умови пошуку об’єднуються оператором
and
. -
Якщо при виклику не передано умови для жодної з колонок що знаходяться всередині елементу
ext:logicOperator
то він не обробляється.
Наприклад при визові наступного критерію пошуку
<changeSet author="registry owner" id="create SC registration_equal_laboratory_id_solution">
<ext:createSearchCondition name="registration_equal_laboratory_id_solution">
<ext:table name="registration" alias="r">
<ext:column name="registration_id" />
<ext:column name="registration_no" searchType="equal"/>
<ext:column name="created_date" />
<ext:logicOperator type="or">
<ext:column name="solution_date" searchType="equal" />
<ext:column name="laboratory_id" searchType="equal" />
<ext:logicOperator type="and">
<ext:column name="name" searchType="equal" />
<ext:column name="surname" searchType="equal" />
</ext:logicOperator>
</ext:logicOperator>
</ext:table>
<ext:table name="solution_type" alias="s">
<ext:logicOperator type="or">
<ext:column name="name" alias="solution_name" searchType="equal" />
<ext:column name="constant_code" alias="solution_code" searchType="equal" />
</ext:logicOperator>
</ext:table>
<ext:join type="inner">
<ext:left alias="r">
<ext:column name="solution_type_id" />
</ext:left>
<ext:right alias="s">
<ext:column name="solution_type_id" />
</ext:right>
</ext:join>
</ext:createSearchCondition>
</changeSet>
повинен генеруватись такий рядок пошуку, за умови що передані всі параметри:
-- <ext:table name="registration" alias="r">
-- <ext:column name="registration_id" />
-- <ext:column name="created_date" />
registration_no=$0 -- <ext:column name="registration_no" searchType="equal"/>
AND
( -- <ext:logicOperator type="or">
solution_date=$1 -- <ext:column name="solution_date" searchType="equal" />
OR
laboratory_id=$2 -- <ext:column name="laboratory_id" searchType="equal" />
OR
( -- <ext:logicOperator type="and">
firstname=$3 -- <ext:column name="firstname" searchType="equal" />
AND
surname=$4 -- <ext:column name="surname" searchType="equal" />
) -- </ext:logicOperator>
) -- </ext:logicOperator>
-- </ext:table>
AND
-- <ext:table name="solution_type" alias="s">
( -- <ext:logicOperator type="or">
name=$5 -- <ext:column name="name" alias="solution_name" searchType="equal" />
OR
constant_code=$6 -- <ext:column name="constant_code" alias="solution_code" searchType="equal" />
) -- </ext:logicOperator>
-- </ext:table>
6.3. Компоненти системи та їх призначення в рамках дизайну рішення
У даному розділі наведено перелік компонент системи, які задіяні або потребують змін/створення в рамках реалізації функціональних вимог згідно з технічним дизайном рішення.
Компонент | Службова назва | Призначення / Суть змін |
---|---|---|
Сервіс Генератор |
service-generation-utility |
Генерація Java-проектів для сервісів |
Схема розширених тегів Liquibase |
liquibase-ext-schema |
Валідація схеми |
Модуль розширення тегів Liquibase |
liquibase-ddm-ext |
Обробка розширених тегів на етапі розгортання регламенту |
7. Моделювання регламенту реєстру
7.1. Моделювання критеріїв пошуку
Адміністратору регламенту надається можливість керувати яким логічним оператором, OR чи AND, будуть об’єднуватись параметри пошуку та в якому порядку вони будуть визначатися.
<changeSet author="registry owner" id="create or/and SC">
<ext:createSearchCondition name="dictionary">
<ext:table name="dict" alias="d">
<ext:logicOperator type="or">
<ext:logicOperator type="and">
<ext:column name="name" searchType="startsWith" />
<ext:column name="live" searchType="equal" />
</ext:logicOperator>
<ext:column name="id" searchType="equal" />
</ext:logicOperator>
<ext:column name="description"/>
</ext:table>
</ext:createSearchCondition>
</changeSet>
7.2. Валідація регламенту реєстру
В рамках реалізації рішення, буде розширена xml схема розширених тегів liquibase по якій проходить валідація.
8. Високорівневий план розробки
8.2. План розробки
-
Розширення схеми розширених тегів Liquibase.
-
Розширення модуля розширення тегів Liquibase.
-
Розширення сервіс генератору.
-
Розробка інструкцій для розробника регламенту та референтних прикладів.