query_first_or_default_async
query_first_or_default_async can execute a query and serialize the first result, or return a default value if the result
set contains no records.
Parameters🔗
All command methods also accept keyword-only options=; see Command options.
| name | type | description | optional | default |
|---|---|---|---|---|
| sql | str |
the sql query str to execute | ||
| default | Any |
any object to return if the result set is empty | ||
| params | ParamType |
params to substitute in the query | None |
|
| model | Any |
the callable to serialize the model; callable must be able to accept column names as kwargs. | dict |
|
| mapper | Callable[[RawRow], Any] |
callable that receives a RawRow and returns a projected value. Mutually exclusive with model. |
None |
param= remains accepted as a 1.x compatibility alias for params=. Pass only one of the two names.
Parameter Shapes🔗
params accepts one parameter record: a mapping, mapping subclass, mutable mapping, or object/dataclass with attributes
matching the placeholder names. Top-level list params are only for execute and execute_async; read and scalar methods
raise InvalidParameterShapeException for top-level lists before opening a cursor.
params=None, param=None, or omitting both names means there is no parameter object. If the SQL contains pydapper
placeholders such as ?id?, every referenced placeholder must be supplied or pydapper raises
MissingParameterException before calling the DBAPI. An empty mapping is a real parameter record with no keys. A list
inside one parameter record, such as {"ids": []} or {"ids": [1, 2, 3]}, is one value and is reserved for future IN
list expansion support.
Rows🔗
When rows are returned as dictionaries, they are insertion-ordered dict[str, Any] values. Key order follows the column order reported by the DB-API cursor.
Column names must be unique exactly as the driver reports them. If a result includes duplicate names, pydapper raises DuplicateColumnException with columns, duplicate_columns, and duplicate_indexes attributes. Alias joined columns instead of using ambiguous select * joins.
Missing keys on returned dict rows raise normal Python KeyError. When custom model construction is requested with model= or models=, pydapper uses the same column-name keyword argument mapping path for results with unique column names.
Use mapper= when column-name mapping is too restrictive. The mapper receives a RawRow with columns, values, and as_dict(). RawRow preserves duplicate column names and positional values in cursor order, so mapper functions can intentionally project joined rows, nested objects, aliases, or duplicate names. Positional indexing and slicing read from values; name indexing and RawRow.as_dict() require unique column names and raise DuplicateColumnException when a dict would be ambiguous.
First, Single and Default🔗
Be careful to use the right method. first and single methods are very different.
For default methods, callable defaults that accept no arguments are called only when no row is returned.
| method | no item | one item | many items |
|---|---|---|---|
first |
NoResultException |
item | first item |
single |
NoResultException |
item | MoreThanOneResultException |
first_or_default |
default | item | first item |
single_or_default |
default | item | MoreThanOneResultException |
Example🔗
Execute a query and map the first result to a dataclass.
import asyncio
import datetime
from dataclasses import dataclass
from pydapper import connect_async
@dataclass
class Task:
id: int
description: str
due_date: datetime.date
owner_id: int
sentinel = object()
async def main():
async with connect_async() as commands:
task = await commands.query_first_or_default_async(
"select * from task where id = -1", model=Task, default=sentinel
)
if task is sentinel:
print("No results found!")
# No results found!
asyncio.run(main())