diff --git a/pages/products/flexberry-ember/3.x/work-with-data/efd3_query-language.ru.md b/pages/products/flexberry-ember/3.x/work-with-data/efd3_query-language.ru.md
index 592c4bb8a..093d7f798 100644
--- a/pages/products/flexberry-ember/3.x/work-with-data/efd3_query-language.ru.md
+++ b/pages/products/flexberry-ember/3.x/work-with-data/efd3_query-language.ru.md
@@ -47,6 +47,8 @@ summary: Описание клиентского языка запросов.
* `GeometryPredicate` - класс для создания фильтра в запросе по геометрическим атрибутам.
* `createPredicate` - функция для создания предиката по заданным параметрам.
* `stringToPredicate` - функция для конвертации строки в предикат.
+* `AttributeParam` - класс для описания атрибута в `SimplePredicate` и `DatePredicate`.
+* `ConstParam`- класс для описания константы в `SimplePredicate` и `DatePredicate`.
Для импорта и использования классов языка запросов необходимо использовать следующий код:
@@ -56,7 +58,7 @@ import Builder from 'ember-flexberry-data/query/builder';
let builder = new Builder(store);
```
-{% include note.html content="В версиях Flexberry Ember 2.x содержалось пространство имен Query, содержащее перечисленные выше классы. Поскольку в Ember 3.x пространства имен более не используются в связи с [использованием ES6-модулей](https://github.com/emberjs/rfcs/blob/master/text/0176-javascript-module-api.md), все классы, содержавшиеся в пространстве имен Query, во Flexberry Ember 3.x теперь необходимо импортировать напрямую из [папки query](https://github.com/Flexberry/ember-flexberry-data/tree/feature-ember-update/addon/query) аддона [ember-flexberry-data](https://github.com/Flexberry/ember-flexberry-data)." %}
+> В версиях Flexberry Ember 2.x содержалось пространство имен Query, содержащее перечисленные выше классы. Поскольку в Ember 3.x пространства имен более не используются в связи с [использованием ES6-модулей](https://github.com/emberjs/rfcs/blob/master/text/0176-javascript-module-api.md), все классы, содержавшиеся в пространстве имен Query, во Flexberry Ember 3.x теперь необходимо импортировать напрямую из [папки query](https://github.com/Flexberry/ember-flexberry-data/tree/feature-ember-update/addon/query) аддона [ember-flexberry-data](https://github.com/Flexberry/ember-flexberry-data).
## Builder
@@ -100,13 +102,13 @@ builder.from('employee');
Для указания того, какой предикат будет использоваться в запросе, используется метод `where` построителя запросов. При этом можно использовать различные варианты передачи параметров в данный метод.
-1. Передача предиката любого типа в качестве параметра:
+1.Передача предиката любого типа в качестве параметра:
```javascript
builder.where(SomePredicate);
```
-2. Передача имени атрибута, операции и значения атрибута (аналог использования `SimplePredicate`)в качестве параметров:
+2.Передача имени атрибута, операции и значения атрибута (аналог использования `SimplePredicate`)в качестве параметров:
```javascript
let builder = new Builder(store, 'customer').where('firstName', FilterOperator.Eq, 'Vasya');
@@ -124,10 +126,10 @@ let builder = new Builder(store, 'customer').where('manager', FilterOperator.Eq,
let builder = new Builder(store, 'customer').where('manager.firstName', FilterOperator.Eq, 'Vasya');
```
-{% include note.html content="Пожалуйста, не используйте в значениях ограничений функцию `cast` и другие OData-специфичные функции!
+> Пожалуйста, не используйте в значениях ограничений функцию `cast` и другие OData-специфичные функции!
Поступая так, вы привязываетесь в запросах к бэкенду конкретного типа.
Язык запросов создан для того, чтобы абстрагироваться от какого-либо типа бэкенда.
-При несоблюдении этого правила ожидайте проблемы при работе в офлайне или смене типа бэкенда.
" %}
+При несоблюдении этого правила ожидайте проблемы при работе в офлайне или смене типа бэкенда.
### Сортировка
@@ -177,7 +179,7 @@ builder.count();
builder.select('id,age,name');
```
-{% include note.html content="Если используется данный способ указания вычитываемых атрибутов в запросе, то нельзя одновременно использовать в запросе метод selectByProjection!" %}
+> Если используется данный способ указания вычитываемых атрибутов в запросе, то нельзя одновременно использовать в запросе метод selectByProjection!
## Указание проекции
@@ -187,11 +189,11 @@ builder.select('id,age,name');
builder.selectByProjection('EmployeeTestProjection');
```
-{% include note.html content="Если используется данный способ указания вычитываемых атрибутов в запросе, то нельзя одновременно использовать в запросе метод select!" %}
+> Если используется данный способ указания вычитываемых атрибутов в запросе, то нельзя одновременно использовать в запросе метод select!
## Создание объекта запроса
-Для того, чтобы создать объект запроса с указанными ранее опциями, используется метод `build` построителя запросов:
+Для создания объекта запроса с указанными ранее опциями используется метод `build` построителя запросов:
```javascript
builder.build();
@@ -199,7 +201,7 @@ builder.build();
## Использование объекта запроса
-Созданный объект запроса должен быть передан в качестве второго параметра в метод [query](https://api.emberjs.com/ember-data/3.1/classes/DS.Store/methods/query?anchor=query) сервиса [store](https://api.emberjs.com/ember-data/3.1/classes/DS.Store) библиотеки [Ember Data](https://api.emberjs.com/ember-data/3.1).
+Созданный объект запроса должен быть передан в качестве второго параметра в метод [query](https://api.emberjs.com/ember-data/3.1/classes/DS.Store/methods/query?anchor=query) сервиса [store](https://api.emberjs.com/ember-data/3.1/classes/DS.Store) библиотеки [Ember Data](https://api.emberjs.com/ember-data/3.1).
```javascript
store.query(modelName, builder.build());
@@ -213,7 +215,8 @@ store.query(modelName, builder.build());
#### Конструктор
-Конструктор класса `SimplePredicate` принимает 3 параметра:
+Конструктор класса `SimplePredicate` принимает 3 параметра:
+
* `attributePath` - атрибут (собственный или у связанных моделей).
* `operator` - оператор (операция).
* `value` - значение атрибута.
@@ -222,7 +225,75 @@ store.query(modelName, builder.build());
let predicate = new SimplePredicate('name', FilterOperator.Eq, 'Vasya');
```
-### Свойства предиката
+#### Свойства предиката
+
+Получить заданный в предикате атрибут ("путь атрибута") можно с использованием свойства `attributePath` предиката:
+
+```javascript
+predicate.attributePath
+```
+
+Получить заданный в предикате оператор (операцию) можно с использованием свойства `operator` предиката:
+
+```javascript
+predicate.operator
+```
+
+Получить заданное в предикате значение для атрибута можно с использованием свойства `value` предиката:
+
+```javascript
+predicate.value
+```
+
+#### AttributeParam и ConstParam
+
+Для расширения возможностей `SimplePredicate` были добавлены сущности `AttributeParam` (указание, что передаётся атрибут) и `ConstParam` (указание, что передаётся значение).
+В качестве первого параметра конструктора класса `SimplePredicate` может передаваться атрибут, `AttributeParam` или `ConstParam`.
+В качестве третьего параметра конструктора класса `SimplePredicate` может передаваться значение атрибута, `AttributeParam` или `ConstParam`.
+
+Такое расширение позволяет делать запрос с указанием двух атрибутов.
+
+```javascript
+let predicate = new SimplePredicate(new AttributeParam('currentMark'), FilterOperator.Le, new AttributeParam('lastMark'));
+```
+
+Также становится возможным менять местами в конструкторе атрибут и значение атрибута
+
+```javascript
+let predicate = new SimplePredicate(new ConstParam(5), FilterOperator.Le, new AttributeParam('lastMark'));
+```
+
+Возможно указание и двух значений, однако в такой ситуации разумнее использовать `TruePredicate` или `FalsePredicate`.
+
+Существуют **ограничения**, связанные с использованием `AttributeParam` и `ConstParam` в конструкторе `SimplePredicate`.
+
+1.При применении двух `AttributeParam` в конструкторе `SimplePredicate` необходимо при использовании `IndexedDbAdapter` или `JsAdapter` мастера указывать с "id" (без этого указания некорректно могут обрабатываться ситуации, когда мастер не задан). Например, если у сущности есть мастера author и editor:
+
+```javascript
+let predicate = new SimplePredicate(new AttributeParam('author.id'), FilterOperator.Eq, new AttributeParam('editor.id'));
+```
+
+2.При указании двух `ConstParam` с датами в виде строковых констант в конструкторе `SimplePredicate` возможно некорректное поведение в связи с тем, что конструктор не распознает, что это даты.
+
+### DatePredicate
+
+`DatePredicate` - предикат для фильтрации записей по атрибуту с типом "дата".
+
+#### Конструктор
+
+Конструктор класса `DatePredicate` принимает 4 параметра:
+
+* `attributePath` - атрибут (собственный или у связанных моделей).
+* `operator` - оператор (операция).
+* `value` - значение атрибута.
+* `timeless` - флаг, указывающий нужно ли учитывать время при сравнении дат (если указано `true`, то время не учитывается).
+
+```javascript
+let predicate = new DatePredicate('birthday', FilterOperator.Eq, '2018-02-06T11:00:00.000Z');
+let predicate = new DatePredicate('birthday', FilterOperator.Eq, '2018-02-06', true);
+```
+
+#### Свойства предиката
Получить заданный в предикате атрибут ("путь атрибута") можно с использованием свойства `attributePath` предиката:
@@ -242,13 +313,28 @@ predicate.operator
predicate.value
```
+Получить заданный в предикате флаг для необходимости учета времени можно с использованием свойства `timeless` предиката:
+
+```javascript
+predicate.timeless
+```
+
+#### AttributeParam и ConstParam
+
+Для расширения возможностей `DatePredicate` были добавлены сущности `AttributeParam` (указание, что передаётся атрибут) и `ConstParam` (указание, что передаётся значение). Их использование аналогично применению в `SimplePredicate`, однако есть дополнительное ограничение: в `ODataAdapter` пока что **не поддерживаются** ограничения, формируемые `DatePredicate`, в конструктор которого переданы два `AttributeParam` и флаг отсутствия учёта времени (фильтрация в этом случае вернёт некорректное значение).
+
+```javascript
+let predicate = new DatePredicate(new AttributeParam('startDate'), FilterOperator.Le, new AttributeParam('endDate'), true);
+```
+
### ComplexPredicate
`ComplexPredicate` - предикат, объединяющий несколько предикатов с помощью логических условий.
#### Конструктор
-Конструктор класса `ComplexPredicate` принимает 2 параметра:
+Конструктор класса `ComplexPredicate` принимает 2 параметра:
+
* `condition` - логическое условие (операция) для объединения предикатов.
* `...predicates` - список предикатов для объединения.
@@ -344,7 +430,8 @@ predicate.containsValue
#### Конструктор
-Конструктор класса `DetailPredicate` принимает единственный параметр:
+Конструктор класса `DetailPredicate` принимает единственный параметр:
+
* `detailPath` - имя связанной детейловой модели.
```javascript
@@ -431,49 +518,6 @@ let cp1 = new ComplexPredicate(Condition.Or, sp1, sp2);
let dp = new DetailPredicate('tags').any(cp1);
```
-### DatePredicate
-
-`DatePredicate` - предикат для фильтрации записей по атрибуту с типом "дата".
-
-#### Конструктор
-
-Конструктор класса `DatePredicate` принимает 4 параметра:
-* `attributePath` - атрибут (собственный или у связанных моделей).
-* `operator` - оператор (операция).
-* `value` - значение атрибута.
-`timeless` - флаг, указывающий нужно ли учитывать время при сравнении дат (если указано `true`, то время не учитывается).
-
-```javascript
-let predicate = new DatePredicate('birthday', FilterOperator.Eq, '2018-02-06T11:00:00.000Z');
-let predicate = new DatePredicate('birthday', FilterOperator.Eq, '2018-02-06', true);
-```
-
-#### Свойства предиката
-
-Получить заданный в предикате атрибут ("путь атрибута") можно с использованием свойства `attributePath` предиката:
-
-```javascript
-predicate.attributePath
-```
-
-Получить заданный в предикате оператор (операцию) можно с использованием свойства `operator` предиката:
-
-```javascript
-predicate.operator
-```
-
-Получить заданное в предикате значение для атрибута можно с использованием свойства `value` предиката:
-
-```javascript
-predicate.value
-```
-
-Получить заданный в предикате флаг для необходимости учета времени можно с использованием свойства `timeless` предиката:
-
-```javascript
-predicate.timeless
-```
-
### GeographyPredicate и GeometryPredicate
* `GeographyPredicate` - предикат для проверки пересечения атрибута с типом "Geography" с заданной геометрической фигурой.
@@ -482,6 +526,7 @@ predicate.timeless
#### Конструктор
Конструктор принимает один параметр:
+
* `attributePath` - атрибут (собственный или у связанных моделей).
Также необходимо задать геометрическую фигуру, пересечение с которой будет проверяться. Для этого нужно воспользоваться методом `intersects` предиката.
@@ -513,6 +558,7 @@ predicate.intersectsValue
#### Конструктор
Конструктор класса `NotPredicate` принимает единственный параметр:
+
* `predicate` - предикат, значение которого нужно инвертировать.
```javascript
@@ -542,7 +588,8 @@ let predicateToInvert = np.predicate;
let predicate = new IsOFPredicate('customer');
```
-Конструктор класса `IsOfPredicate` может также принимать два параметра:
+Конструктор класса `IsOfPredicate` может также принимать два параметра:
+
* `expression` - атрибут (собственный или у связанных моделей).
* `typeName` - имя модели.
@@ -572,6 +619,7 @@ let builder = new Builder(store, 'creator').isOf('man');
## Операторы (операции)
В клиентском языке есть два класса, которые содержат свойства, являющиеся операторами (операциями) предикатов:
+
* `Condition` - класс с логическими операциями для `ComplexPredicate`.
* `FilterOperator` - класс с операциями для `SimplePredicate`, `StringPredicate` и `DatePredicate`.