Custom expressions
Query
An example of how to create any custom parameterized query
import dataclasses
from david8 import get_default_qb
from david8.protocols.dialect import DialectProtocol
from david8.protocols.sql import ExprProtocol
@dataclasses.dataclass(slots=True)
class CustomQuery(ExprProtocol):
static_param: int
dynamic_param: str
def get_sql(self, dialect: DialectProtocol) -> str:
# or you can use param
# from david8.expressions import param as p
# alias = p(self.dynamic_param).get_sql(dialect)
_, alias = dialect.get_paramstyle().add_param(self.dynamic_param)
col_name = dialect.quote_ident('col_name')
return f'CUSTOM SQL ... SELECT {self.static_param}, {alias}, {col_name}'
query = get_default_qb().query(CustomQuery(static_param=1, dynamic_param='test'))
print(query.get_sql()) # CUSTOM SQL ... SELECT 1, %(p1)s, col_name
print(query.get_parameters()) # {'p1': 'test'}
SELECT expression
import dataclasses
from david8.protocols.dialect import DialectProtocol
from david8.expressions import param as p
from david8.protocols.sql import ExprProtocol
@dataclasses.dataclass(slots=True)
class InsertCat(ExprProtocol):
cat: str
age: int
def get_sql(self, dialect: DialectProtocol) -> str:
cat = p(self.cat).get_sql(dialect)
age = p(self.age).get_sql(dialect)
return f"insert_cat({cat}, {age})"
qb.select(InsertCat('Baksya', 2))
# SELECT insert_cat(%(p1)s, %(p2)s)
# {'p1': 'Baksya', 'p2': 2}
INSERT expression
import dataclasses
from david8.functions import sum_
from david8.predicates import between, ne
from david8.protocols.dialect import DialectProtocol
from david8.protocols.sql import ExprProtocol
@dataclasses.dataclass(slots=True)
class SelectTotalRevenue(ExprProtocol):
start: str
end: str
def get_sql(self, dialect: DialectProtocol) -> str:
return (
qb
.select(
'provider',
sum_('revenue').as_('total_revenue'),
)
.from_table('table1')
.where(between('date', self.start, self.end))
.group_by('provider')
.union(qb
.select(
'provider',
sum_('revenue').as_('total_revenue'),
)
.from_table('table2')
.where(
between('date', self.start, self.end),
ne('category', 'bug')
)
.group_by('provider')
)
.get_sql(dialect)
)
qb.insert().into('total_revenue').from_expr(
['provider_name', 'total_revenue'],
SelectTotalRevenue('2026-01-01', '2026-12-31')
).get_sql()
# INSERT INTO total_revenue (provider_name, total_revenue)
# SELECT provider, sum(revenue) AS total_revenue
# FROM table1
# WHERE date BETWEEN %(p1)s AND %(p2)s
# GROUP BY provider
# UNION ALL
# SELECT provider, sum(revenue) AS total_revenue
# FROM table2
# WHERE date BETWEEN %(p3)s AND %(p4)s AND category != %(p5)s
# GROUP BY provider
# {'p1': '2026-01-01', 'p2': '2026-12-31', 'p3': '2026-01-01', 'p4': '2026-12-31', 'p5': 'bug'}
Function
PostgreSQL expression CAST(json_field->>'id' AS INTEGER) > 3: extract id key from json field and compare with an integer value:
from dataclasses import dataclass
from david8 import get_default_qb
from david8.protocols.dml import FunctionProtocol
from david8.expressions import param
@dataclass(slots=True)
class MyFunction(FunctionProtocol):
col_name: str
json_key: str
value: int | str
def get_sql(self, dialect: DialectProtocol) -> str:
return f"CAST({dialect.quote_ident(self.col_name)}->>'{self.json_key}' AS INTEGER) > {int(self.value)}"
@dataclass(slots=True)
class MyParametrizedFunction(MyFunction):
def get_sql(self, dialect: DialectProtocol) -> str:
quoted_col = dialect.quote_ident(self.col_name)
parameter = param(self.value).get_sql(dialect)
return f"CAST({quoted_col}->>'{self.json_key}' AS INTEGER) > {parameter}"
qb = get_default_qb()
qb.select(MyFunction('json_field', 'id', 3)).from_table('table').get_sql()
qb.select(MyParametrizedFunction('json_field', 'id', 3)).from_table('table').get_sql()
# [INFO]: SELECT CAST(json_field->>'id' AS INTEGER) > 3 FROM table
# {}
# [INFO]: SELECT CAST(json_field->>'id' AS INTEGER) > %(p1)s FROM table
# {'p1': 3}