Skip to content

ArtemYeremeev/SQaLice-compiler

Repository files navigation

SQaLice-compiler

SQa-Lice-logo

Описание компиляции основного запроса

Описание компиляции поискового запроса

Описание методов парсинга запроса

Описание методов изменения запроса

Описание и назначение

Пакет компилятора SQaLice предназначен для гибкой обработки запросов к БД на PostgreSQL в проектах с применением go-swagger. SQaLice позволяет запрашивать конкретный набор полей из установленного target, фильтровать, сортировать и ограничивать получаемый набор строк.

Подготовка к использованию компилятора

В функцию-компилятор Compile в качестве аргумента передается modelsMap, содержащая информацию о полях моделей проекта, используемых для обработки целевого SQL кода. Рекомендуется формировать данную map динамически, например в init модуля при запуске проекта, что обеспечит консистентность сгенерированных посредством go-swagger моделей и данных, передаваемых в компилятор через map. Для этого можно использовать функцию FormDinamicModel. Также в этом случае в swagger-модели не должно быть вложенных моделей, иначе произойдут некорректное считывание тегов полей и ошибки формирования полей.

UPDATE 0.4 Начиная с данной версии считывание полей модели, используемых при компиляции запроса, а также при изменении исходной строки-аргумента params внесено внутрь целевых функций и не нуждается в отдельном формировании. В качестве аргумента model в Compile следует передавать структуру-модель, на которую планируется считывание данных из БД.

UPDATE 0.4.1 Начиная с данной версии компилятор поддерживает считывание тегов полей из вложенных структур

UPDATE 0.5.0 Запрос компиляции Compile разделен на основной запрос Get и поисковый Search. Примеры вызовов запроса Search описаны в отдельном блоке

UPDATE 0.7.1 Добавлена возможность раздельного формирования запроса и параметров блока условий для постобработки и безопасной передачи в стандартный пакет GO - database/sql. Данная опция активируется при вызове Get или Search и передаче withArgs = true. Примеры запросов сформированных запросов и аргументов приведены в отдельном блоке этого документа.

Формат запроса

В случае обращения к компилятору SQaLice для генерации основного Get запроса все параметры целевого запроса должны содержаться в аргументе params. В target передается целевая таблица или view, к которой осуществляется запрос и которая используется при указании динамической модели.

Структура запроса

Аргумент params при парсинге запроса внутри Get разделяется на 3 блока - fields, conditions, restrictions.

Пример адресной строки запроса, содержащей все 3 блока

http://url/.../query=ID,title,updatedAt?ID==10||ID==8?ID,desc,2,0

В случае отсутствия необходимости в указании одного из этих блоков, приведенное форматирование должно сохраняться.

Пример адресной строки запроса без блока conditions

http://url/.../query=ID,title,updatedAt??ID,desc,2,0

Запрос без указания условий в 3 блоках одновременно не рекомендуется, так как может привести к неожиданным ошибкам.

Типы математических операторов

SQaLice поддерживает следующие математические операторы:

Оператор SQaLice PG
РАВНО == =
НЕ РАВНО != !=
МЕНЬШЕ < <
МЕНЬШЕ ИЛИ РАВНО <= <=
БОЛЬШЕ > >
БОЛЬШЕ ИЛИ РАВНО >= >=
СОДЕРЖИТ >> &&
ВКЛЮЧАЕТ ->> ->>

Пример адресной строки, содержащей математический оператор

http://url/.../query=ID,name?ID!=10?,,2,0

Типы логических операторов

SQaLice поддерживает следующие логические операторы:

Оператор SQaLice PG
И * AND
ИЛИ Двойная прямая черта OR

Пример адресной строки запроса, содержащей оба оператора

http://url/.../query=?(ID==8*title==Тест)||ID==10?

Блок fields

Для получения всех полей из целевой SQL, содержащиеся в структуре модели modelsMap, нужно передавать данный блок пустым.

Пример адресной строки запроса с пустым блоком fields

http://url/.../query=?ID==10||ID==8?ID,desc,2,0

Для получения конкретных полей, в поле fields необходимо передавать название поля в формате json с запятыми в качестве разделителя и без пробелов.

ID,title,createdAt?

Пример адресной строки запроса для получения ID

http://url/.../query=ID?ID>=1?ID,desc,10,0

При передаче некорректного названия поля, SQaLice вернет ошибку:

"[SQaLice] Passed unexpected field name in select"

Блок conditions

В данном блоке возможно указание условий получения записей. Допускается передача пустого блока conditions, в таком случае происходит выборка без дополнительных условий.

Пример запроса без блока conditions

http://url/.../query=ID,title,createdAt??ID,asc,10,0

Условия должны разделяться допустимыми математическими операторами и не содержать пробелов.

Пример использования простой условной конструкции

?title==Тест?

Разделение нескольких условий осуществляется с помощью допустимых логических операторов, так же без пробелов. Кроме того могут быть использованы условные блоки в круглых скобках. Количество таких блоков не ограничено.

Пример использования сложной условной конструкции

(ID>8*ID<10)||title==Тест

ВАЖНО! При использовании сочетания условных блоков в скобках и без, блок без скобок должен указываться последним, как на приведенном выше примере. В противном случае запрос будет некорректным.

Примеры условных конструкций с выбором по массиву

http://url/.../query=title?ID==7,8,9?
select q.title from v_test q where q.id = any(array[7,8,9])
http://url/.../query=title?ID!=7,8,9?
select q.title from v_test q where not q.id = any(array[7,8,9])

При передаче условной конструкции с неверным логическим оператором, SQaLice вернет ошибку:

"[SQaLice] Unsupported operator in condition"

При передаче условной конструкции с неверным названием поля, SQaLice вернет ошибку:

"[SQaLice] Passed unexpected field name in condition"

При передаче условной конструкции с массивом и неверным оператором, SQaLice вернет ошибку:

"[SQaLice] Passed unexpected operator in array condition - <="

UPDATE 0.5.8

Для операторов == и != возможно указание нескольких значений через запятую, без пробелов. В таком случае происходит отбор строк по переданному массиву.

UPDATE 0.6.3

Для запроса нулевых значений необходимо передавать значение null или NULL c оператором РАВНО или НЕ РАВНО

http://url/.../query=ID?ID!=null*title==NULL?
select q.id from v_test q where q.id is not null and q.title is null

При передаче некорректного для NULL условия оператора, SQaLice вернет ошибку:

"[SQaLice] Passed unexpected operator in NULL condition - <"

Блок conditions (аргументы)

UPDATE 0.7.1

Добавлен блок раздельного получения параметров и тела запроса к БД. В блоке условий запроса значения величин заменяются аргументами-плейсхолдерами ($1, $2 и т.д). Сами аргументы выдаются в ответе компилятора массивом, по последовательному порядку плейсхолдеров запроса.

Примеры запросов с возратом аргументов

Запрос с одним условием

http://url/.../query=?ID==1?
select q.id, q.content, q.count, q.extra_field, q.is_bool, q.one_more_field from v_test q where q.id = $1
[1]

Запрос с несколькими условиями

http://url/.../query=ID?(ID==1,2,3||content!=new)*isBool==true?ID,desc,10,0
select q.id from v_test q where (q.id = any(array[$1]) or q.content != $2) and q.is_bool = $3 order by q.id desc limit 10 offset 0
["1,2,3", "'new'", true]

Запрос с несколькими условиями 2

http://url/.../query=isBool?(ID==null||content!=new)*(isBool==true)?ID,desc,10,0
select q.is_bool from v_test q where (q.id is null or q.content != $1) and (q.is_bool = $2) order by q.id desc limit 10 offset 0
[nil, "'new'", true]

Запрос с вложенным полем в условии

http://url/.../query=ID?content==content^^smth?
select q.id from v_test q where q.content->>'content' = $1
["'smth'"]

Блок restrictions

В данном блоке возможно указание ограничений конечной выборки. Допускается передача пустого блока ограничений, в таком случае SQaLice не накладывает дополнительных условий на выборку.

Пример запроса без блока ограничений

http://url/.../query=ID,title,createdAt?ID>1?

При заполнении ограничений в блоке restrictions необходимо соблюдать порядок параметров блока, разделять их запятыми и не использовать пробелы

Порядок указания ограничений

Параметр Допустимые значения
Поля сортировки Поля, переданные в fieldsMap
Порядок сортировки asc, desc
Лимит Целое число >= 0
Оффсет Целое число >= 0

Пример запроса со всеми параметрами ограничений

http://url/.../query=ID,title,createdAt?ID>1?ID,asc,10,0

Пример запроса с несколькими полями сортировки (разделитель |)

http://url/.../query=ID,title,createdAt?ID>1?ID|isBool,asc,10,0

Пример запроса с частью параметров (лимит, оффсет)

http://url/.../query=ID,title,createdAt?ID>1?,,10,0

При передаче некорректного названия поля сортировки, SQaLice вернет ошибку:

"[SQaLice] Unexpected selection order field"

При передаче некорректного порядка сортировки, SQaLice вернет ошибку:

"[SQaLice] Unexpected selection order"

При передаче некорректного лимита, SQaLice вернет ошибку:

"[SQaLice] Unexpected selection limit"

При передаче некорректного оффсета, SQaLice вернет ошибку:

"[SQaLice] Unexpected selection offset"

TO-DO

TO-DO Статус
Покрытие тестами Выполнено
Обработка сложных условий (вложенность, дополнительные операторы) Выполнено частично
Снятие ограничений порядка условий Не выполнено

Описание компиляции поискового запроса

Описание поискового запроса

Функция Search обеспечивает компиляцию запроса с LIKE-поиском по переданной строке и параметру. Параметры компиляции запроса (выборка полей, условия, ограничения) работают аналогично основному запросу Get. Функция поиска дополнительно принимает строковый параметр - searchParams, содержащий условные выражения, аналогичные блоку условий основного запроса. Использование логических операторов также аналогично основному запросу Поле и значение внутри условной конструкции требуется разделять оператором ~~. В случае использования иных операторов, выражение будет разделено некорректно. При формировании итогового запроса, поисковая часть отделяется от основной скобками. Поиск протестирован для работы с полями строкового и цифрового формата (varchar, text, integer, numeric). Корректность работы поиска по другим полям не гарантирована.

UPDATE 0.5.5 Добавлена обработка скобочных выражений аналогично основному блоку условий. Примеры реализации приведены ниже.

Примеры построения поисковых запросов

Примеры полной сборки запроса

Запрос с пустыми основными параметрами и поиском по одному полю:

http://url/.../query=??&searchQuery=title~~some
select q.id, q.title, q.updatedAt from v_test q where (q.title::text like '%%some%%')

Запрос со сложными основными параметрами и поиску по нескольким полям:

http://url/.../query=title?ID!=1?ID,desc,10,0&searchQuery=ID~~1||ID~~2
select q.title from v_test q where (q.id::text like '%%1%%' or q.id::text like '%%2%%') and q.id != 1 order by q.id desc limit 10 offset 0

Запрос с одним скобочным выражением (должен быть на первом месте):

http://url/.../query=ID??&searchQuery=(content~~1||content~~2)*extraField~~ok
select q.id from v_test q where ((lower(q.content::text) like '%1%' or lower(q.content::text) like '%2%') and lower(q.extra_field::text) like '%ok%')

Запрос с несколькими скобочными выражениями (порядок произволен):

http://url/.../query=ID,content,extraField??ID,desc,,&searchQuery=(content~~1||content~~2)*(extraField~~some||extraField~~any)
select q.id, q.content, q.extra_field from v_test q where ((lower(q.content::text) like '%1%' or lower(q.content::text) like '%2%') and (lower(q.extra_field::text) like '%some%' or lower(q.extra_field::text) like '%any%')) order by q.id desc

Запрос со вложенным объектом:

http://url/.../query=ID,content,extraField??ID,desc,,&searchQuery=content~~extraField^^something
select q.id, q.content, q.extra_field from v_test q where (q.content->>'extraField'::text like '%something%')

При передаче значения searchField, отсутствующего в параметре модели, SQaLice вернет ошибку:

"[SQaLice] Passed unexpected field name in search condition - extra_Field"

Примеры сборки запроса с массивом аргументов

Запрос 1 + 1

http://url/.../query=content?ID!=1?ID,asc,,&searchQuery=ID~~1
select q.content from v_test q where (lower(q.id::text) like $1) and q.id != $2 order by q.id asc
["'%1%'", 1]

Запрос по множеству полей

http://url/.../query=ID?(ID==1,2,13||isBool==true)*content!=anth?&searchQuery=ID~~1||content~~smth
select q.id from v_test q where (lower(q.id::text) like $1 or lower(q.content::text) like $2) and (q.id = any(array[$3]) or q.is_bool = $4) and q.content != $5
["'%1%'", "'%smth%'", "1,2,13", true, "'anth'"]

Описание методов парсинга запроса

Список полей

Функция GetFieldsList позволяет получать список полей, приведенных к формату запроса в базу.

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?ID==10||ID==8?ID,desc,2,0

Получаемый массив полей:

["id", "title", "updated_at"]

При обработке строки запроса, не содержащей список полей, будет возвращен пустой массив:

http://url/.../query=??
[]

При запросе поля, не входящего в модель, компилятор вернет ошибку:

"[SQaLice] Passed unexpected field name in select - field"

Список условий

Функция GetConditionsList позволяет получить список условий, содержащихся в запросе. При этом элементы условий приводятся к формату запроса к БД.

Формат условной структуры:

Имя Тип Описание
fieldName string Название поля
operator string Оператор
value interface Значение
isBracket string Признак "Условие в скобках"

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?(title==testText)*ID!=8?ID,desc,2,0

Получаемый массив условий:

[
    {
        "fieldName": "title",
        "operator": "=",
        "value": {"testText"},
        "isBracket": true
    },
    {
        "fieldName": "id",
        "operator": "!=",
        "value": {"8"},
        "isBracket": false
    },
]

При обработке строки запроса, не содержащей условий, будет возвращен пустой массив:

http://url/.../query=??
[]

Пример ошибки:

"[SQaLice] Unsupported operator in condition - <<"

Условие по названию

Функция GetConditionByName позволяет получить первое по порядку условие по с переданным названием поля, содержащегося в запросе. При этом элементы условия приводятся к формату запроса к БД.

Формат условной структуры:

Имя Тип Описание
fieldName string Название поля
operator string Оператор
value interface Значение
isBracket string Признак "Условие в скобках"

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?(ID==3)*ID!=8?ID,desc,2,0

Получаемый массив условий:

{
    "fieldName": "id",
    "operator": "=",
    "value": {"3"},
    "isBracket": true
}

При обработке строки запроса, не содержащей условий, будет возвращен пустой массив:

http://url/.../query=??
[]

Пример ошибки:

"[SQaLice] Unsupported operator in condition - <<"

Поля сортировки

Функция GetSortField позволяет получить массив полей сортировки, содержащихся в запросе. При этом названия полей приводятся к формату запроса в БД.

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?(ID==3)*ID!=8?ID,desc,2,0

Получаемое название поля:

{
    ["id"]
}

Пример строки запроса с несколькими полями:

http://url/.../query=ID,title,updatedAt?(ID==3)*ID!=8?ID,isBool,desc,2,0

Получаемое название поля:

{
    ["id", "is_bool"]
}

При обработке строки запроса, не содержащей ограничений, будет возвращена пустая строка:

http://url/.../query=??
""

Пример ошибки:

"[SQaLice] Unsupported field in restrictions - field"

Порядок сортировки

Функция GetSortOrder позволяет получить порядок сортировки, содержащийся в запросе.

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?(ID==3)*ID!=8?ID,desc,2,0

Получаемый порядок сортировки:

{"desc"}

При обработке строки запроса, не содержащей ограничений, будет возвращена пустая строка:

http://url/.../query=??
""

Пример ошибки:

"[SQaLice] Unsupported field in restrictions - field"

Лимит

Функция GetLimit позволяет получить лимит, содержащийся в запросе.

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?(ID==3)*ID!=8?ID,desc,2,0

Получаемый порядок сортировки:

2

При обработке строки запроса, не содержащего ограничений, будет возвращен nil:

http://url/.../query=??
nil

Пример ошибки:

"[SQaLice] Invalid negative selection limit - -1"

Отступ

Функция GetOffset позволяет получить отступ, содержащийся в запросе.

Пример строки запроса:

http://url/.../query=ID,title,updatedAt?(ID==3)*ID!=8?ID,desc,2,0

Получаемый порядок сортировки:

0

При обработке строки запроса, не содержащей ограничений, будет возвращен nil:

http://url/.../query=??
nil

Пример ошибки:

"[SQaLice] Invalid negative selection offset - -1"
TO-DO Статус
Покрытие тестами Выполнено
Расширение получения условий запроса Не выполнено

Изменение списка полей

Функция AddQueryFieldsToSelect позволяет добавлять дополнительные поля в SELECT блок запроса, либо полностью заменить его. Это регулируется флагом isDeleteCurrent. Передаваемые поля проверяются по аргументу fieldsMap на наличие в модели, если он передан. В случае передачи неверного поля, компилятор пропустит данное поле. Если fieldsMap не передан, все поля добавляются в запрос без проверки

UPDATE 0.4 Начиная с данной версии считывание полей модели, используемых при компиляции запроса, а также при изменении исходной строки-аргумента params внесено внутрь целевых функций и не нуждается в отдельном формировании. В качестве аргумента model при получении/изменении условий запроса необходимо передавать модель, на которую планируется считывание данных

Добавление условий

Функция AddQueryConditions позволяет добавлять дополнительные условия в запрос, либо полностью заменить их. Это регулируется флагом isDeleteCurrent. Если в условии передан некорректный оператор, компилятор вернет ошибку:

"[SQaLice] Passed incorrect operator in query condition"

Добавляемые поля разделяются логическим оператором AND между собой, а также с текущими условиями запроса.

Замена условия

Функция ReplaceQueryCondition позволяет заменить текущее условие в запросе по названию поля. Если условия с переданным именем нет в запросе, компилятор вернет ошибку:

"[SQaLice] Condition with passed name not found"

Удаление условия

Функция DeleteQueryCondition позволяет удалить текущее условие в запросе по названию поля. Если условия с переданным именем нет в запросе, компилятор вернет исходную строку запроса

Добавление ограничений

Функция AddQueryRestrictions позволяет заменить поля и порядок сортировки, лимит и оффсет в запросе.

About

go-swagger compiler

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages