Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions src/typedal/query_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,22 @@ def _qfields(self) -> list[t.Any]:
_, select_args, _ = self._before_query({}, add_id=False)
return select_args

# pydal 3 compiles a Select used in belongs() from these attributes instead of calling _compile().
# They expose the same (query, fields, kwargs) that to_sql() renders, so relationships are already applied.
@property
def _db(self) -> "TypeDAL":
return self._get_db()

@property
def _query(self) -> Query: # type: ignore[override]
query, _, _ = self._before_query({}, add_id=False)
return query

@property
def _attributes(self) -> dict[str, t.Any]: # type: ignore[override]
_, _, select_kwargs = self._before_query({}, add_id=False)
return dict(select_kwargs)

def _compile(
self,
outer_scoped: list[t.Any] | None = None, # noqa ARG002 - inherit from Select
Expand Down Expand Up @@ -193,15 +209,14 @@ def permissions(self, **permissions: t.Unpack[Permissions]) -> "QueryBuilder[T_M

return self._extend(permissions=permissions)

def _normalize_select_option(
self, value: str | Field | Expression | bool | t.Iterable[str | Field]
) -> str | bool | list[str]:
def _normalize_select_option(self, value: str | Field | Expression | bool | t.Iterable[str | Field]) -> str | bool:
# currently only used for 'distinct' since orderby, ... are patched by pydal itself in select()
if isinstance(value, bool):
return value

if isinstance(value, (list, tuple, set)):
return t.cast(list[str], [self._normalize_select_option(val) for val in value])
# pre-joined into one fragment: pydal 3 would otherwise try to `|` the strings together
return ", ".join(str(self._normalize_select_option(val)) for val in value)

if rname := getattr(value, "_rname", None):
return str(rname)
Expand Down Expand Up @@ -558,7 +573,8 @@ def delete(self) -> list[int]:

def _delete(self) -> str:
db = self._get_db()
return str(db(self.query)._delete())
# no str(): pydal 3 may return a str subclass carrying bound params
return db(self.query)._delete()

# QueryBuilder subclasses Select for its query-building surface but yields
# model instances rather than fields, so these two are not substitutable.
Expand All @@ -578,7 +594,8 @@ def update(self, **fields: t.Any) -> list[int]: # ty: ignore[invalid-method-ove

def _update(self, **fields: t.Any) -> str:
db = self._get_db()
return str(db(self.query)._update(**fields))
# no str(): pydal 3 may return a str subclass carrying bound params
return db(self.query)._update(**fields)

def _before_query(self, mut_metadata: Metadata, add_id: bool = True) -> tuple[Query, list[t.Any], SelectKwargs]:
select_args = [self._select_arg_convert(_) for _ in self.select_args] or [self.model.ALL]
Expand Down
3 changes: 2 additions & 1 deletion src/typedal/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ def insert(self: t.Type[T_MetaInstance], **fields: t.Any) -> T_MetaInstance:
def _insert(self, **fields: t.Any) -> str:
table = self._ensure_table_defined()

return str(table._insert(**fields))
# no str(): pydal 3 may return a str subclass carrying bound params
return table._insert(**fields)

def bulk_insert(self: t.Type[T_MetaInstance], items: list[AnyDict]) -> "TypedRows[T_MetaInstance]":
"""
Expand Down
3 changes: 2 additions & 1 deletion tests/test_query_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def test_where_builder():
assert sql
assert isinstance(sql, str)
assert "number" in sql
assert "5" in sql
# pydal 3 binds values as parameters (sqlite) instead of inlining them:
assert "5" in sql or 5 in getattr(sql, "params", ())

result = builder.update(number=5)
assert TestQueryTable.where(lambda row: row.number == -1).update(number=5) == [] # nothing updated
Expand Down
Loading