Immutable query builder for chirp.data.
Accumulates SQL clauses through chaining methods, compiles to a SQL string
- parameters tuple, and executes via the existing
Databasemethods.
Each method returns a new frozenQuery— the original is never mutated.
Same pattern asResponse.with_*()but for SELECT queries.
Usage::
from chirp.data import Database, Query
@dataclass(frozen=True, slots=True)
class Todo:
id: int
text: str
done: bool
todos = await (
Query(Todo, "todos")
.where("done = ?", False)
.where_if(search, "text LIKE ?", f"%{search}%")
.order_by("id DESC")
.take(20)
.fetch(db)
)
Transparency:.sql and .paramsshow exactly what will run.
No hidden queries, no magic.
Free-threading safety:
- Frozen dataclass — immutable after creation
- Tuple accumulators — no shared mutable state
- No locks needed
data.query
| Name | Type | Default | Description |
|---|---|---|---|
type
|
|
— | |
qualified_name
|
|
— | |
element_type
|
|
— | |
description
|
|
— | |
source_file
|
|
— | |
line_number
|
|
— | |
is_autodoc
|
|
— | |
autodoc_element
|
|
— | |
_autodoc_template
|
|
— | |
_autodoc_url_path
|
|
— | |
_autodoc_page_type
|
|
— | |
title
|
|
— | |
doc_content_hash
|
|
— |
Symbols on this page
Build a dialect-correct JSON-extraction SQL expression fragment.
Emits the right syntax for the active driver so the sqlite-vs-postgres branch stops leaking into every call…
Immutable SELECT query builder.
Construct with a target dataclass and table name, chain methods to
add clauses, then execute viafetch(), fetch_one(),…
json_path
function
def json_path(column: str, /, *keys: str, dialect: str) -> str
Build a dialect-correct JSON-extraction SQL expression fragment.
Emits the right syntax for the active driver so the sqlite-vs-postgres branch stops leaking into every call site::
json_path("oauth", "sub", dialect="sqlite") # json_extract(oauth, '$.sub')
json_path("oauth", "sub", dialect="postgresql") # oauth->>'sub'
json_path("data", "a", "b", dialect="sqlite") # json_extract(data, '$.a.b')
json_path("data", "a", "b", dialect="postgresql")# data->'a'->>'b'
Drop the result straight into aWHERE/SELECTstring and keep the
actual filter value as a separate bound parameter::
Query(Row, "users").where(
json_path("oauth", "sub", dialect="sqlite") + " = ?", sub_id
)
The expression contains no bound-parameter placeholder of its own — the
JSON pathkeysare static, author-supplied identifiers concatenated into
the SQL text. Never pass request/user-controlled values ascolumnor
keys: they are not parameterized and would be an injection vector. Keep
real filter values in the separate bound params ofQuery.where(clause, *params) / db.fetch(sql, *params).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
column
|
str
|
— | The JSON column name. |
*keys
|
str
|
— | |
dialect
|
str
|
— | The driver dialect — ``"sqlite"`` or ``"postgresql"`` (any non-``"sqlite"`` value is treated as PostgreSQL, matching the driver-dispatch convention in ``chirp.data.shapes``). |
Query
class
Immutable SELECT query builder.
Construct with a target dataclass and table name, chain methods to
add clauses, then execute viafetch(), fetch_one(), etc.
Every method returns a newQuery— the original is unchanged.
View source · /home/runner/work/chirp/chirp/site/../src/chirp/data/query.py:1