Формат JSONQ
Модуль jsonq создан для удобного создания простых SQL конструкций по текстовой конфигурации в формате JSON
Спецификация формата
{
"SELECT": ["expression", ...],
"FROM": ["table_element", ...],
"WHERE": ["expression", ...],
"GROUP BY": ["expression", ...],
"HAVING": ["expression", ...],
"ORDER BY": ["expression", ...],
"OPTIONS": ["option", ...],
"LIMIT": int,
"OFFSET": int
}
expression
=
| <str> # имя столбца; короткий формат
| [ <expr>, <as> ] # выражение с алиасом; формат list
;
<expr> : любое поддерживаемое выражение в fs_alchemy.parsing.expression
table_element
=
| <str> # имя таблицы
| [ <tab_expr>, <as>, <on>, <on>, ... ] # имя таблицы, алиас, условие для join; формат list
;
<tab_expr> : любое поддерживаемое выражение в fs_alchemy.parsing.segment
// если в секции всего один элемент и это str, то скобки списка можно опустить
{
...
"SECTION1": ["str", ...],
"SECTION2": "str"
...
}
Поддержка переменных в запросе
Элементы \<expr>, \<tab_expr>, \<as>, \<on> поддерживают подстановку перенных. Переменной является alphanumeric текст в фигурных скобках, например "{prev_task}". Виды поддерживаемых переменных:
- простые типы: int, float, bool, str - по ним подстановка осуществляется методом str.replace()
- сложные: SQLAlchemy Selectable - поддерживается только в \<tab_expr> и только если выражение состоит ровно из одной переменной
Примеры запросов
// базовые SELECT
{
"SELECT": "*",
"FROM": "schema1.users"
}
{
"SELECT": ["name", "gender"],
"FROM": ["schema1.users"]
}
{
"SELECT": [["1", "const_int"], ["'abc'", "const_str"]]
}
// алиасы
{
"SELECT": ["u.name", "u.gender"],
"FROM": [["schema1.users", "u"]]
}
{
"SELECT": [
["u.name", "user_name"],
"u.gender"
],
"FROM": [["schema1.users", "u"]]
}
// джойны
{
"SELECT": "*",
"FROM": [
["schema1.users", "u"],
["schema1.salary", "s", "u.name = s.name"], // LEFT by default
]
}
{
"OPTIONS": "inner",
"SELECT": "*",
"FROM": [
["schema1.users", "u"],
["schema1.salary", "s", "u.name = s.name"], // INNER
]
}
// фильтры
{
"SELECT": "*",
"FROM": "schema1.users",
"WHERE": "name = 'vasya'"
}
{
"SELECT": "*",
"FROM": "schema1.users",
"WHERE": ["name = 'vasya'", "age > 18"] // условия через AND
}
// GROUP BY, HAVING, ORDER BY
{
"SELECT": ["name", "gender", "count(1)"],
"FROM": "schema1.users",
"GROUP BY": ["name", "gender"],
"HAVING": ["count(1) > 0"],
"ORDER BY": "name" // ASC
}
// flat params
// column_name = 'name'
// salary_table = 'salary'
// min_pay = 1000
{
"SELECT": "u.{column_name}",
"FROM": [
["users", "u"],
["{salary_table}", "s", "u.{column_name} = s.{column_name}"],
],
"WHERE": "gender = 'm' or salary_amt>{min_pay}",
}
// table params
{
"id": "salary_subquery",
"type": "cte",
"body": {
"SELECT": ["name", "salary_amt"],
"FROM": "dwh.salary",
"WHERE": ["salary_src = 'gbc'"]
}
},
{
"id": "query",
"type": "cte",
"body":{
"SELECT": "u.name",
"FROM": [
["users", "u"],
["{salary_subquery}", "s", "u.name = s.name"],
],
"WHERE": "gender = 'm' or salary_amt > 1000",
}
}