Examples
Each block is the SQL, the parameter object, and the compiled statement.
Optional filter and sort
--(active, sort, dir)--
select u.user_id, u.user_name
from users u
where 1 = 1
and optional(u.active = {{active}})
order by
sort({{sort}}, name = u.user_name, id = u.user_id)
dir({{dir}})
{
"active": 1,
"sort": "name",
"dir": "desc"
}
select u.user_id, u.user_name
from users u
where (u.active = ?)
order by
u.user_name DESC
The bind is active integer 1. Omitting active drops the where. Omitting sort drops the dynamic order term.
One optional predicate
--(param1)--
select *
from a
where 1 = 1
or optional(col1 = {{param1}})
{"param1": 1} compiles to:
select *
from a
where (col1 = ?)
{} compiles to:
select *
from a
Several parameters in one optional
--(a, b)--
select *
from t
where optional(
col1 = {{a}}
and col3 = {{b}}
)
{"a": 1, "b": 1} compiles to:
select *
from t
where (
col1 = ?
and col3 = ?
)
{} removes the where. {"b": 1} is an error: every parameter in the block must be present, or all of them omitted.
List expansion
--(cv)--
select *
from t
where optional(col in ({{cv}}...))
{"cv": [1, 1, 1]} compiles to:
select *
from t
where (col in (?, ?, ?))
{} compiles to select * from t. An empty list outside optional(...) is an error.
optional_when
--(apply, id)--
select *
from t
where z = 1
and optional_when({{apply}}, u.user_id = {{id}})
{"apply": true, "id": 1} compiles to:
select *
from t
where z = 1
and (u.user_id = ?)
{"id": 1} compiles to:
select *
from t
where z = 1
apply is not bound.
Nested
optional_when wraps optional_groups_or.
--(apply, pairs blob)--
select *
from t
where z = 1
and optional_when(
{{apply}},
optional_groups_or({{pairs}}, id = {{self.id}})
)
{
"apply": true,
"pairs": [
{"id": 1},
{"id": 1}
]
}
select *
from t
where z = 1
and (
(id = ?)
or (id = ?)
)
{"pairs": [{"id": 1}, {"id": 1}]} compiles to select * from t where z = 1. The group is not rendered.
optional_when inside a group. The condition is the header argument flag.
--(pairs blob, flag)--
select *
from t
where optional_groups_or(
{{pairs}},
c1 = {{self.cv}}
and optional_when({{flag}}, c2 = {{self.cv2}})
)
{
"flag": true,
"pairs": [
{"cv": 1, "cv2": 1},
{"cv": 1, "cv2": 1}
]
}
select *
from t
where (
(c1 = ? and (c2 = ?))
or (c1 = ? and (c2 = ?))
)
Omitting flag leaves where ((c1 = ?) or (c1 = ?)).
optional wrapping a group and a header argument.
--(pairs blob, x)--
select *
from t
where z = 1
and optional(
a = {{x}}
and optional_groups_or({{pairs}}, id = {{self.id}})
)
{
"x": 1,
"pairs": [
{"id": 1},
{"id": 1}
]
}
select *
from t
where z = 1
and (
a = ?
and (
(id = ?)
or (id = ?)
)
)
{"x": 1, "pairs": null} compiles to select * from t where z = 1 and (a = ?).
optional inside a group.
--(pairs blob, flag)--
select *
from t
where optional_groups_or(
{{pairs}},
col1 = {{self.cv1}}
and optional(col2 = {{flag}})
)
{
"flag": 1,
"pairs": [
{"cv1": 1},
{"cv1": 1}
]
}
select *
from t
where (
(col1 = ? and (col2 = ?))
or (col1 = ? and (col2 = ?))
)
Omitting flag leaves where ((col1 = ?) or (col1 = ?)).
Group rows
--(pairs blob)--
select u.user_id
from users u
where optional_groups_or(
{{pairs}},
u.user_id = {{self.id}}
and u.role_id in ({{self.ids}}...)
)
{
"pairs": [
{"id": 1, "ids": [8, 9]}
]
}
select u.user_id
from users u
where (
u.user_id = ?
and u.role_id in (?, ?)
)
Binds are self.id 1, then self.ids 8 and 9.
optional_groups_or with two rows:
--(pairs blob)--
select *
from t
where optional_groups_or(
{{pairs}},
col2 = {{self.cv}}
and col1 = {{self.cv1}}
)
{
"pairs": [
{"cv": 1, "cv1": 1},
{"cv": 1, "cv1": 1}
]
}
select *
from t
where (
(col2 = ? and col1 = ?)
or (col2 = ? and col1 = ?)
)
optional_groups_and with two rows:
--(pairs blob)--
select *
from t
where optional_groups_and(
{{pairs}},
id = {{self.id}}
)
{
"pairs": [
{"id": 1},
{"id": 1}
]
}
select *
from t
where (
(id = ?)
and (id = ?)
)
{"pairs": null} removes the group.
Group and sort
--(pairs blob, sort)--
select *
from t
where optional_groups_or(
{{pairs}},
col1 = {{self.cv1}}
)
order by sort({{sort}}, id = id)
{
"pairs": [
{"cv1": 1}
],
"sort": "id"
}
select *
from t
where (col1 = ?)
order by id ASC
Errors
These inputs do not compile.
Partial optional
a is omitted and b is present.
--(a, b)--
select *
from t
where optional(
col1 = {{a}}
and col3 = {{b}}
)
{"b": 1}
optional(...) requires every parameter to be provided or all omitted; partial parameters: a
Empty list
--(cv)--
select *
from t
where col in ({{cv}}...)
{"cv": []}
empty array for {{cv}}; IN list cannot be empty
Empty list on a group row
--(pairs blob)--
select *
from t
where optional_groups_or(
{{pairs}},
col2 in ({{self.cv}}...)
)
{
"pairs": [
{"cv": []}
]
}
empty array for optional_groups field {{cv}} in pairs; IN list cannot be empty
Group source is not blob
--(pairs)--
select *
from t
where optional_groups_or(
{{pairs}},
col1 = {{self.cv1}}
)
{"pairs": 1}
optional_groups_*(...) source {{pairs}} must be declared blob in query.sql
Bad header
--(a integer junk)--
select {{a}}
{"a": 1}
invalid parameter declaration 'a integer junk' in query.sql
Nested optional_when
--(a, b, x)--
select *
from t
where optional_when({{a}}, optional_when({{b}}, c = {{x}}))
{"a": true, "b": true, "x": 1}
nested optional_when(...) is not supported
Nested groups
--(pairs blob, pairs1 blob)--
select *
from t
where optional_groups_or(
{{pairs}},
optional_groups_and({{pairs1}}, id = {{self.id}})
)
{}
nested optional_groups_or(...)/optional_groups_and(...) is not supported
is null or without parentheses
--(a)--
select *
from t
where {{a}} is null or a = 1
{"a": 1}
{{a}} is null or must be wrapped in parentheses in query.sql