Логика работы универсального фильтра#
В документации описано, как универсальный фильтр определяет доступные поля, формирует условия фильтрации и генерирует SQL-выражения.
Общая схема работы#
EntityAvi — это мастер-выборка, от которой наследуются другие выборки. Операция универсального фильтра находится в EntityAvi, поэтому она доступна на всех выборках.
Фильтрация реализована через объекты Scala-классов, которые формируются и хранятся в памяти. Настройки фильтра сохраняются в базе данных в виде JSON.
Управление фильтрацией выполняется через объект fltManager. Каждый экземпляр отображения создает собственный экземпляр менеджера фильтра.
По умолчанию фильтрация доступна:
по атрибутам выборки;
по атрибутам класса, определяемого через Avi-функцию
thisApi();по коллекциям класса, добавленным из ODM или из вкладки Коллекции универсального фильтра в карточке класса.
Сохраненная настройка фильтра не обновляется автоматически при изменении свойств атрибутов. Она использует состояние атрибутов на момент их добавления. Для изменения поведения атрибута необходимо удалить его из фильтра и добавить заново.
Связь выборки и класса#
Контекст фильтрации определяется через функцию thisApi(), которая связывает выборку с классом.
За счет этого фильтр получает доступ к:
атрибутам класса;
характеристикам;
коллекциям.
Связь атрибута выборки и атрибута класса#
Атрибуты выборки сопоставляются с атрибутами класса по системному имени.
Если у выборки указан класс, то:
атрибут выборки связывается с атрибутом класса с тем же именем;
метаданные объединяются (тип редактора, ссылочность и т.д.).
Тип редактора определяется следующим образом:
для атрибутов выборки — как указано в выборке;
для атрибутов класса:
если задан в ODM — используется он;
иначе определяется по типу данных.
Особенности редакторов:
выпадающие списки — редактор с тремя точками;
даты — интерфейс Фильтрации по периоду;
ссылочные атрибуты — редактор с тремя точками;
множественные сравнения — также через редактор с тремя точками;
числовые признаки — редактор чекбокс;
Внимание
Если числовой атрибут должен отображаться в универсальном фильтре как чекбокс, в odm.xml необходимо явно указать тег <booleanColumn/>.
Одного attribute-type="Number" и editorType="check" недостаточно. Без <booleanColumn/> универсальный фильтр может определить атрибут как числовой, из-за чего в значении фильтра будет отображаться поле ввода числа, а не чекбокс.
Пример настройки числового признака:
<attr name="bRoundTheClockWork"
attribute-type="Number"
caption="Круглосуточная работа"
editorType="check"
type="basic"
isObjectAttr="true">
<booleanColumn/>
</attr>
Доступные элементы фильтра#
Атрибуты выборки#
Атрибутами выборки считаются все поля, присутствующие в дата-сете.
формируются только при активной выборке;
тип данных определяется типом в дата-сете;
дополняются метаданными класса при наличии связи.
Атрибуты класса#
Для класса в универсальный фильтр по умолчанию попадают все атрибуты, кроме idClass.
При необходимости отдельные атрибуты можно отключить для универсального фильтра:
<attr name="bError">
<uniFilter isActive="false"/>
</attr>
Коллекции#
Коллекции добавляются:
из ODM;
из вкладки Коллекции универсального фильтра в карточке класса.
Фильтрация выполняется через exists / not exists.
Объектные характеристики#
Объектные характеристики хранятся в JSON (jObjAttrs_dz) и отображаются в универсальном фильтре как отдельные атрибуты.
Фильтрация по объектным характеристикам выполняется через SQL-выражение.
Принадлежность объектных характеристик к классу определяется по настройкам класса и типа объекта. Характеристика считается доступной для класса, если она подключена одним из способов:
через настройку группировки класса, если для класса используется группировка;
через вкладку «Объектные характеристики» в настройках типа объекта класса.
Если характеристика подключена через тип объекта, она доступна для объектов соответствующего типа. Если характеристика подключена через группировку, она доступна для объектов, которые относятся к этой группе.
Универсальные характеристики#
Универсальные характеристики отображаются в универсальном фильтре как отдельные атрибуты.
Фильтрация выполняется следующим образом:
единичные характеристики фильтруются через выражения;
множественные характеристики фильтруются через
exists/not exists.
Принадлежность универсальных характеристик к классу определяется по группам класса и типам объекта. Характеристика считается доступной для класса, если она подключена одним из способов:
через группировку объектов;
через вкладку «Объектные характеристики» в настройках типа объекта класса.
Если группа объектов используется в нескольких классах, универсальные характеристики этой группы становятся доступными для всех таких классов.
Примечание
Правила валидации, ограничения выбора и значения по умолчанию влияют на поведение характеристики при вводе и обработке данных, но не являются самостоятельным правилом определения принадлежности характеристики к классу для универсального фильтра.
Технические атрибуты#
Технические атрибуты формируются при наличии связи выборки с классом.
Доступные технические атрибуты:
sHeadLine#;sMnemoCode#;dModifyDate#;dCreateDate#;sModifyUser#;sCreateUser#;IdGroup#— доступен только при включенном сервисе группировки;idObject#.
Инициализация атрибутов фильтра#
Инициализация атрибутов фильтра — это формирование в памяти набора элементов, доступных для фильтрации. На этом этапе система определяет, какие атрибуты, характеристики, коллекции и технические поля можно отобразить пользователю в интерфейсе универсального фильтра.
Инициализация по выборке#
В lazyInitFilter:
формируются атрибуты выборки;
дополняются метаданными класса;
выполняется только при наличии дата-сета.
Инициализация по классу#
Дополнительно формируются:
атрибуты класса;
характеристики;
коллекции;
технические атрибуты.
Для управления инициализацией атрибутов фильтра используется точка расширения фильтра.
Примеры см. в документе:
[Практические сценарии настройки и расширения универсального фильтра.](/040_selection/010_Универсальный_фильтр/030_Практические_сценарии_настройки_универсального_фильтра.md)
Атрибуты переменной ссылочности#
Атрибуты переменной ссылочности могут раскрываться в дереве атрибутов фильтра. При раскрытии система определяет, какие классы или атрибуты нужно показать пользователю для дальнейшей настройки условия.
Правила раскрытия зависят от настройки ссылочности:
если атрибут ссылается на
mixin, при раскрытии дерева формируется подуровень со всеми классами, к которым подключен этотmixin;если атрибут ссылается на один класс, при раскрытии отображаются атрибуты этого ссылочного класса;
если в
odm.xmlилиavm.xmlуказан список классов, при раскрытии дерева формируется подуровень со всеми классами из этого списка;если ссылочность не определена, атрибут не раскрывается в дереве и ведет себя как строковый атрибут. В качестве значения фильтрации указывается
gid.
Пример настройки списка классов для атрибута переменной ссылочности:
<attr name="gidRefDocument" type="refAnyObject">
<uniFilter>
<refAnyObject>
<ref name="Wf_Doc"/>
<ref name="Cnt_Contract"/>
</refAnyObject>
</uniFilter>
</attr>
Приоритет определения ссылочности:
avm.xml>attr>uniFilter.refClass;avm.xml>attr>uniFilter.refAnyObject;avm.xml>attr>ref class;odm.xml>attr>uniFilter.refClass;odm.xml>attr>uniFilter.refAnyObject;odm.xml>attr>ref.class.
Примечание
Настройки ссылочности из avm.xml имеют приоритет над настройками из odm.xml.
Например, если в avm.xml для атрибута указан refClass, а в odm.xml для этого же атрибута задан список классов через refAnyObject, универсальный фильтр будет использовать ссылочность из avm.xml.
Особенности атрибутов#
Выражения фильтрации#
Позволяют задавать SQL-логику:
используются для JSON;
позволяют вычислять значения атрибутов.
HL-атрибуты#
HL – атрибуты (далее IdAttrHL) считаются ссылочными атрибутами и в фильтрации не участвуют. Фильтрация осуществляется по их id-атрибутам (далее IdAttr).
Ссылочность определяется:
Через тег
<ref>, например:<ref class="Rpl_IntOutSession"/>.Через одноименный атрибут класса этой выборки.
Формирование условий фильтрации#
Фильтр преобразует настройку, заданную пользователем в интерфейсе, в SQL-условие.
При построении условия используется главная группа MainGroup. В результате формируется макрос onlyWhere, то есть фрагмент условия без полного SQL-запроса.
При формировании макроса учитываются:
отдельные условия по атрибутам;
логические группы «И» и «ИЛИ», которые определяют порядок объединения условий;
условия по коллекциям, которые преобразуются в
exists/not exists.
Например, обычное условие по атрибуту превращается в сравнение поля со значением, логическая группа объединяет несколько таких условий, а фильтрация по коллекции проверяет наличие или отсутствие связанных записей.
Использование физических имен атрибутов при формировании макроса#
При формировании SQL-макроса универсальный фильтр использует физические имена атрибутов. Физическое имя определяет, какое поле или выражение будет подставлено в SQL-условие.
В большинстве случаев физическое имя совпадает с системным именем атрибута. Исключения возможны для технических и специальных атрибутов.
Например:
для
IdObject#в макрос может подставляться физическое полеID;для ссылочных или специальных атрибутов может использоваться другое физическое имя, например
gidRef.
За счет этого пользователь работает с логическим именем атрибута в интерфейсе фильтра, а при построении макроса система преобразует его в поле или выражение, которое можно использовать в SQL.
Объектные и реляционные запросы#
Универсальный фильтр работает в двух сценариях.
Фильтрация ROP-объектов#
Фильтрация ROP-объектов — это отдельный программный сценарий работы универсального фильтра. Он не применяется автоматически в UI-выборках и используется только в прикладном коде, когда разработчик явно передает в механизм фильтрации коллекцию ROP-объектов.
Механизм работает следующим образом:
Коллекция ROP-объектов преобразуется во временное JSON-представление.
По настройке универсального фильтра формируется SQL-выражение для работы с этим JSON-представлением.
Условие фильтрации применяется к JSON-представлению объектов.
Возвращается отфильтрованная коллекция ROP-объектов.
Ограничения такого сценария:
универсальный фильтр не работает автоматически в выборках, построенных на объектном запросе;
фильтрация не учитывает изменения, которые находятся только в сессионном кеше;
не учитываются изменения в коллекциях фильтруемых объектов, если эти изменения не попали в JSON-представление;
не учитываются изменения в ссылочных объектах, если они не были отражены в JSON-представлении;
результат фильтрации зависит от состава данных, которые разработчик передал в коллекции ROP-объектов.
Пример программного применения см. в разделе Применение к объектным данным.
Реляционные запросы#
Анализируется модель данных;
Формируются атрибуты фильтра:
ссылочные;
переменной ссылочности;
значимые;
Строится SQL-условие.
Для коллекций используется
exists.
Преобразование условий в SQL#
Система формирует SQL на основе:
атрибута;
типа сравнения;
значения.
Строковый атрибут
Условие |
Пример |
|---|---|
Содержит |
|
Равно |
|
Не равно |
|
В списке |
|
Заполнено |
|
Для строковых атрибутов сравнение выполняется в верхнем регистре, поэтому фильтрация не учитывает регистр символов.
Числовой атрибут
Условие |
Пример |
|---|---|
Равно |
|
Больше |
|
Меньше |
|
Интервал |
|
Подробные примеры SQL-макросов для числовых атрибутов, включая интервал с одной или двумя границами, приведены в разделе Примеры формируемых SQL-макросов.
Булевый атрибут
= 1;<> 1;is null;is not null.
Дата
Используется to_timestamp.
JSON
is null;is not null.
BLOB / CLOB
аналогично JSON или строкам.
Ссылочные атрибуты
аналогично числовым.
Примеры формируемых SQL-макросов#
В этом разделе приведены примеры SQL-условий, которые формирует универсальный фильтр для разных типов атрибутов и сценариев фильтрации.
В примерах используется алиас t. Он обозначает исходный запрос выборки, к которому применяется условие универсального фильтра.
Строковый атрибут#
Содержит — накладывает условие на регистронезависимое вхождение строки.
upper(t.sCaption) like upper('%'||'value'||'%')
Начинается с — накладывает условие на регистронезависимое начало строки.
upper(t.sCaption) like upper('value'||'%')
Заканчивается на — накладывает условие на регистронезависимое окончание строки.
upper(t.sCaption) like upper('%'||'value')
Равно — накладывает условие на регистронезависимое совпадение строки.
upper(t.sCaption) = upper('value')
Не равно — накладывает условие на регистронезависимое несовпадение строки.
upper(t.sCaption) <> upper('value')
В списке — накладывает условие на регистронезависимое вхождение в список.
upper(t.sCaption) in (upper('value'))
Не в списке — накладывает условие на регистронезависимое отсутствие в списке.
upper(t.sCaption) not in (upper('value'))
Заполнено — накладывает условие на наличие значения.
t.sCaption is not null
Не заполнено — накладывает условие на отсутствие значения.
t.sCaption is null
Не содержит — накладывает условие на регистронезависимое отсутствие подстроки.
upper(t.sCaption) not like upper('%'||'value'||'%')
В интервале — накладывает условие на вхождение строки в заданный интервал.
upper(t.sCaption) >= upper('valueFrom') and upper(t.sCaption) <= upper('valueTo')
Если одна из границ интервала не задана, формируется только одно условие:
upper(t.sCaption) >= upper('valueFrom')
или:
upper(t.sCaption) <= upper('valueTo')
Числовой атрибут#
Равно — накладывает условие на точное совпадение числового значения.
t.nNumber = value
Не равно — накладывает условие на несовпадение числового значения.
t.nNumber <> value
В списке — накладывает условие на вхождение числового значения в список.
t.nNumber in (value)
Не в списке — накладывает условие на отсутствие числового значения в списке.
t.nNumber not in (value)
Заполнено — накладывает условие на наличие числового значения.
t.nNumber is not null
Не заполнено — накладывает условие на отсутствие числового значения.
t.nNumber is null
В интервале — накладывает условие на вхождение числового значения в заданный интервал.
t.nNumber >= valueFrom and t.nNumber <= valueTo
Для интервала не используется between. Условие формируется через отдельные сравнения по нижней и верхней границе.
Если задана только одна граница интервала, формируется только соответствующее условие:
t.nNumber >= valueFrom
или:
t.nNumber <= valueTo
Меньше — накладывает условие на то, что числовое значение меньше заданного.
t.nNumber < 1
Меньше или равно — накладывает условие на то, что числовое значение меньше или равно заданному.
t.nNumber <= 1
Больше — накладывает условие на то, что числовое значение больше заданного.
t.nNumber > 1
Больше или равно — накладывает условие на то, что числовое значение больше или равно заданному.
t.nNumber >= 1
Внимание
Для типа Long виды сравнения «Меньше», «Меньше или равно», «Больше», «Больше или равно» недоступны.
Булевый атрибут#
Равно — накладывает условие на точное совпадение булевого значения.
t.bBool = 1
Не равно — накладывает условие на несовпадение булевого значения.
t.bBool <> 1
Заполнено — накладывает условие на наличие значения.
t.bBool is not null
Не заполнено — накладывает условие на отсутствие значения.
t.bBool is null
Дата#
Равно — накладывает условие на точное совпадение даты.
t.dDate = to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
Не равно — накладывает условие на несовпадение даты.
t.dDate <> to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
Заполнено — накладывает условие на наличие даты.
t.dDate is not null
Не заполнено — накладывает условие на отсутствие даты.
t.dDate is null
В интервале — накладывает условие на вхождение даты в заданный интервал.
t.dDate >= to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
and t.dDate <= to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
Если одна из границ интервала не задана, формируется только соответствующее условие.
Меньше — накладывает условие на то, что дата меньше заданной.
t.dDate < to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
Меньше или равно — накладывает условие на то, что дата меньше или равна заданной.
t.dDate <= to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
Больше — накладывает условие на то, что дата больше заданной.
t.dDate > to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
Больше или равно — накладывает условие на то, что дата больше или равна заданной.
t.dDate >= to_timestamp('31.12.2000 00:00:00','DD.MM.YYYY HH24:MI:SS')
JSON-атрибут#
Заполнено — накладывает условие на наличие JSON-значения.
t.jJson is not null
Не заполнено — накладывает условие на отсутствие JSON-значения.
t.jJson is null
BLOB-атрибут#
Заполнено — накладывает условие на наличие значения.
t.lBlob is not null
Не заполнено — накладывает условие на отсутствие значения.
t.lBlob is null
CLOB-атрибут#
Для CLOB-атрибутов условия формируются по аналогии со строковыми атрибутами.
Ссылочный атрибут#
Для ссылочных атрибутов условия по идентификатору формируются по аналогии с числовыми атрибутами.
Например, при множественном выборе ссылочного значения формируется условие:
t.idMeasureItem in (102104,101954,101967,101973)
Примеры макросов для класса Bs_Goods#
В примерах показана фильтрация списка объектов класса Bs_Goods.
Собственное поле класса#
Если в фильтр добавлен значимый строковый атрибут sPartNumber, формируется условие:
upper(t.sPartNumber) like upper('%'||'abc'||'%')
Ссылочное поле класса через join#
Если пользователь раскрыл ссылочный атрибут и добавил атрибут ссылочного класса, универсальный фильтр формирует условие через exists.
exists(
select 1
from Msr_MeasureItem t336
where t336.id = t.idMeasureItem
and upper(t336.sCodeGOST) = upper('10')
)
Ссылочное поле класса с множественным выбором#
Если пользователь добавил ссылочный атрибут с множественным выбором значений, формируется условие через in.
t.idMeasureItem in (102104,101954,101967,101973)
Фильтрация коллекций#
При фильтрации по коллекциям универсальный фильтр формирует условия через exists.
Коллекция первого уровня вложенности по значимому атрибуту#
Если пользователь добавил коллекцию Bs_GoodsSrc и задал условие по ее значимому атрибуту, формируется вложенное условие:
exists(
select 1
from Bs_Goods t354
where t354.id = t.id
and exists(
select 1
from Bs_GoodsSrc t370
where t370.idGds = t354.id
and t370.bDefault = 1
)
)
Коллекция первого уровня вложенности по ссылочному атрибуту через join#
Если пользователь добавил коллекцию Bs_GoodsSrc, раскрыл ссылочный атрибут и добавил атрибут ссылочного класса, формируется условие с join внутри exists.
exists(
select 1
from Bs_Goods t354
where t354.id = t.id
and exists(
select 1
from Bs_GoodsSrc t407
join Bs_Prj t408 on t408.id = t407.idPrj
where t407.idGds = t354.id
and t408.idDepOwner = 117801
)
)
Коллекция второго уровня вложенности#
Если пользователь добавил коллекцию Bs_GoodsSrc, затем коллекцию Bs_PrjVerRange и задал условие по атрибуту вложенной коллекции, формируется несколько уровней exists.
exists(
select 1
from Bs_Goods t354
where t354.id = t.id
and exists(
select 1
from Bs_GoodsSrc t410
where t410.idGds = t354.id
and exists(
select 1
from Bs_PrjVerRange t423
where t423.gidSrc = t410.gid
and t423.idPrjVerFrom = 105501
)
)
)
Макрос с несколькими условиями#
Если в фильтре одновременно заданы условия по собственному полю, ссылочному полю и коллекциям, универсальный фильтр объединяет их в общий макрос.
t.idMeasureItem in (102104,101967,101971,101973)
and upper(t.sPartNumber) like upper('%'||'abc'||'%')
and exists(
select 1
from Bs_Goods t354
join Msr_MeasureItem t447 on t447.id = t.idMeasureItem
where t354.id = t.id
and upper(t447.sCodeGOST) = upper('10')
and exists(
select 1
from Bs_GoodsSrc t410
join Bs_Prj t451 on t451.id = t410.idPrj
where t410.idGds = t354.id
and t410.bDefault = 1
and t451.idDepOwner = 117801
and exists(
select 1
from Bs_PrjVerRange t423
where t423.gidSrc = t410.gid
and t423.idPrjVerFrom = 105501
)
)
)