Skip to content

Commit

Permalink
Changes:
Browse files Browse the repository at this point in the history
- fix queryset copy accidentally initializing table
- improve sql debug property
- update docs
  • Loading branch information
devkral committed Oct 24, 2024
1 parent c41290d commit ef64e61
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 11 deletions.
6 changes: 5 additions & 1 deletion docs/queries/queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ The pendant in a model are `identifying_clauses`.
query = Model.query.filter(id=1)
# ensures that the db connection doesn't drop during operation
async with query.database as database:
# when using joins a exist subquery is generated
# when using joins a subquery is generated
expression = query.table.select().where(await query.build_where_clause())
# as generic sql
print(str(expression))
Expand All @@ -1124,6 +1124,10 @@ async with model.database as database:
If you want raw sql see the print statements. You most probably want a dialect specific sql string for non-basic
sql types because otherwise some features are not supported or cause warnings.

## Debugging

QuerySet contains a cached debug property named `sql` which contains the QuerySet as query with inserted blanks.

[model]: ../models.md
[managers]: ../managers.md
[lambda statements](https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.lambda_stmt)
3 changes: 3 additions & 0 deletions edgy/core/db/models/mixins/row.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ async def __set_prefetch(
) -> None:
model_key = ()
if related._is_finished:
# when force_rollback
# we can only bake after all rows are retrieved
# this is why it is here
await related.init_bake(type(model))
model_key = model.create_model_key()
if model_key in related._baked_results:
Expand Down
30 changes: 20 additions & 10 deletions edgy/core/db/querysets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def _clone(self) -> "QuerySet":
"""
queryset = self.__class__(
self.model_class,
database=self.database,
database=getattr(self, "_database", None),
filter_clauses=self.filter_clauses,
select_related=self._select_related,
prefetch_related=self._prefetch_related,
Expand Down Expand Up @@ -336,9 +336,8 @@ def _build_tables_join_from_relationship(
"""

# How does this work?
# First we build a transitions table with a dependency, so we find a path
# Secondly we check if a select_related path is joining a table from the set in an opposite direction
# If yes, we mark the transition for a full outer join (dangerous, there could be side-effects)
# First we build a transitions tree (maintable is root) by providing optionally a dependency.
# Resolving a dependency automatically let's us resolve the tree.
# At last we iter through the transisitions and build their dependencies first
# We pop out the transitions so a path is not taken 2 times

Expand All @@ -362,7 +361,14 @@ def _build_tables_join_from_relationship(
former_table = maintable
former_transition = None
prefix: str = ""
# prefix which expands m2m fields
_select_prefix: str = ""
# False (default): add prefix regularly.
# True: skip adding existing prefix to tables_and_models and skip adding the next field to the
# public prefix.
# string: add a custom prefix instead of the calculated one and skip adding the next field to the
# public prefix.

injected_prefix: Union[bool, str] = False
model_database: Optional[Database] = self.database
while select_path:
Expand Down Expand Up @@ -424,6 +430,8 @@ def _build_tables_join_from_relationship(
table = model_class.table_schema(self.active_schema)
table = table.alias(hash_tablekey(tablekey=table.key, prefix=prefix))

# it is guranteed that former_table is either root and has a key or is an unique join node
# except there would be a hash collision which is very unlikely
transition_key = (get_table_key_or_name(former_table), table.name, field_name)
if transition_key in transitions:
# can not provide new informations
Expand Down Expand Up @@ -1041,14 +1049,16 @@ class QuerySet(BaseQuerySet):
QuerySet object used for query retrieving. Public interface
"""

async def _sql_helper(self) -> Any:
async with self.database:
return (await self.as_select()).compile(
self.database.engine, compile_kwargs={"literal_binds": True}
)

@cached_property
def sql(self) -> str:
"""Get SQL select query as string."""
return str(
run_sync(self.as_select()).compile(
compile_kwargs={"literal_binds": True},
)
)
"""Get SQL select query as string with inserted blanks. For debugging only!"""
return str(run_sync(self._sql_helper()))

def filter(
self,
Expand Down

0 comments on commit ef64e61

Please sign in to comment.