|
20.11.2023, 16:28 | #1 |
Участник
|
Объект упрощающий создание расширенных запросов
Всем привет.
Как на проекте, так и на Аксфоруме, встречается код использующий расширенные запросы: X++: qbr.value(StrFmt("((%1.%3 != 0) || (%1.%2 != 0))"... Во вложении проект содержащий класс QueryBuildRangeCondition. Он упрощает разработку, но обратной стороной является снижение читабельности и быстродействия. Как оформить код, чтобы она не страдала - вопрос открытый. Текущее решение - прототип. Вероятно, это скорее "строитель" корректных запросов. Реализованные функции... create - конструктор. Намеренно один и принимает QBDS + FieldName. toString - результат. Результат ее выполнения необходимо передать в экземпляр QueryBuildRange как value. value/link- задает оператор сравнения и само значение. В качестве значения можно передать другой QueryBuildRangeCondition. add/or - добавляют еще один объект QueryBuildRangeCondition через оператор И/ИЛИ. Пример использования: X++: Query q = new Query(); QueryBuildDataSource qbds = q.addDataSource(tableNum(CustTable)); QueryBuildRange qbr = qbds.addRange(fieldNum(CustTable, RecId)); QueryBuildRangeCondition qbrc = QueryBuildRangeCondition::create(qbds, fieldStr(CustTable, InvoiceAccount)) .and( QueryBuildRangeCondition::create(qbds, fieldStr(CustTable, RecId)).value(QueryBuildRangeOperator::Equal, 403387) .or(QueryBuildRangeCondition::create(qbds, fieldStr(CustTable, Name)).value(QueryBuildRangeOperator::NonEqual, CustTable::findRecId(403387).Name)) ) .and(QueryBuildRangeCondition::create(qbds, fieldStr(CustTable, RecId)).link(QueryBuildRangeOperator::Equal, qbds, fieldStr(CustTable, RecId))); ; qbds.addRange(fieldNum(CustTable, RecId)).value(qbrc.toString()); Код: ((CustTable_1.InvoiceAccount)&&((CustTable_1.RecId=403387)||((CustTable_1.Name!="\"Василий\"")))&&((CustTable_1.RecId=((CustTable_1.RecId))))) Последний раз редактировалось Товарищ ♂uatr; 27.11.2023 в 22:23. |
|
|
За это сообщение автора поблагодарили: Logger (5), S.Kuskov (10), PavelX (4), Pandasama (3). |
23.11.2023, 07:31 | #2 |
Участник
|
А более сложные конструкции с различными вложенностями AND и OR и NOT он делать позволяет?
|
|
23.11.2023, 13:52 | #3 |
Участник
|
Позволяет, вложенному QueryBuildRangeCondition указываете доп. критерии - рекурсия.
Исходный пример выглядел бы примерно так: X++: QueryBuildRangeCondition::create(qbds, fieldStr(CustTable, InvoiceAccount)) .and(QueryBuildRangeCondition::create(qbds, fieldStr(CustTable, RecId)).value(QueryBuildRangeOperator::Equal, 403387) .and( ... ) ) NOT - оператор, за это отвечает перечисление QueryBuildRangeOperator. Оно передается как параметр в функции value и link. Больше или равно, просто больше и тд - там же. Последний раз редактировалось Товарищ ♂uatr; 23.11.2023 в 14:03. |
|
23.11.2023, 14:13 | #4 |
Участник
|
Цитата:
Можно ли, например, собрать вот такое условие: Код: NOT((Table1.Field1 == "aaa") OR (Table2.Field2 == "aaa")) Код: ((Table1.Field1 != "aaa") AND (Table2.Field2 != "aaa")) |
|
23.11.2023, 14:24 | #5 |
Участник
|
Да, путаю. Не рассматриваю расширенные запросы в рамках чистого TSQL. Спасибо.
Верно пишите, в рамках текущей реализации возможность реверса логики не была заложена и условие нужно будет развернуть. Добавить можно. К исправлениям - очевидно, что функция link лишние скобки создает. |
|
23.11.2023, 15:56 | #6 |
Участник
|
Ещё можно добавить тип сравнения LIKE. Вроде он поддерживается в расширенном синтаксисе начиная с AX2009
|
|
|
За это сообщение автора поблагодарили: Logger (1). |
23.11.2023, 19:40 | #7 |
Участник
|
Там еще всякие нюансы были, типа для dimension поля обязательно указывать датасорс итп.
На аксаптапедии было расписано. |
|
27.11.2023, 22:49 | #8 |
Участник
|
Привет.
-добавил "реверс" логики блока. Для использования необходимо применять новый конструктор "createNegation". Т.е. добавлена возможность написать: Код: NOT((Table1.Field1 == "aaa") OR (Table2.Field2 == "aaa")) Актуальная версия во вложении (предыдущую удалил). На тему массивов - функционал не расширял, он и так поддерживается: X++: QueryBuildRangeCondition::createNegation(qbds, fieldId2Name(tableNum(LedgerTrans), fieldId2ext(fieldNum(LedgerTrans, Dimension), 4))).value(QueryBuildRangeOperator::Equal, 'Что-то'); Код: !((LedgerTrans_1.Dimension[4]="Что-то")) Последний раз редактировалось Товарищ ♂uatr; 27.11.2023 в 23:00. |
|
|
За это сообщение автора поблагодарили: ashu (2), Logger (10), Ace of Database (10), Pandasama (3), SRF (2). |