sqlakit 0.15.0__tar.gz → 0.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sqlakit-0.15.0 → sqlakit-0.16.0}/PKG-INFO +1 -1
- {sqlakit-0.15.0 → sqlakit-0.16.0}/pyproject.toml +1 -1
- {sqlakit-0.15.0 → sqlakit-0.16.0}/pyproject.toml.orig +1 -1
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_query.py +82 -3
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/orm.py +4 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/LICENSE +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/README.md +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/__init__.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_base.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_cli.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_db.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_debugserver.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_discovery.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_model.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_recording.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_registry.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_routing.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_sql.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/__init__.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/_db.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/_registry.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/orm.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/sql.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/debugserver.html +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/exceptions.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/py.typed +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/pytest_plugin.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/sql.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/testing.py +0 -0
- {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/types.py +0 -0
|
@@ -24,9 +24,14 @@ from sqlalchemy.ext.compiler import compiles
|
|
|
24
24
|
from sqlalchemy.orm import (
|
|
25
25
|
InstrumentedAttribute,
|
|
26
26
|
contains_eager,
|
|
27
|
+
defer,
|
|
27
28
|
joinedload,
|
|
29
|
+
load_only,
|
|
28
30
|
selectinload,
|
|
29
31
|
subqueryload,
|
|
32
|
+
undefer,
|
|
33
|
+
undefer_group,
|
|
34
|
+
with_expression,
|
|
30
35
|
)
|
|
31
36
|
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
|
32
37
|
from sqlalchemy.sql import operators
|
|
@@ -507,10 +512,23 @@ class BaseQuery(Generic[ModelT]):
|
|
|
507
512
|
self._reject_statement("where")
|
|
508
513
|
return self.with_select(self._select.where(*criteria))
|
|
509
514
|
|
|
510
|
-
def filter_by(
|
|
511
|
-
|
|
515
|
+
def filter_by(
|
|
516
|
+
self,
|
|
517
|
+
values: Mapping[str, Any] | None = None,
|
|
518
|
+
/,
|
|
519
|
+
**fields: Any, # noqa: ANN401
|
|
520
|
+
) -> Self:
|
|
521
|
+
"""Narrow the rows by equality, as `Select.filter_by` does.
|
|
522
|
+
|
|
523
|
+
```python
|
|
524
|
+
db.query(User).filter_by(team="red")
|
|
525
|
+
db.query(User).filter_by(request.query_params)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
The fields are keywords, a mapping, or both, as `create()` takes them.
|
|
529
|
+
"""
|
|
512
530
|
self._reject_statement("filter_by")
|
|
513
|
-
return self.with_select(self._select.filter_by(**values))
|
|
531
|
+
return self.with_select(self._select.filter_by(**merged(values, fields)))
|
|
514
532
|
|
|
515
533
|
def join(
|
|
516
534
|
self,
|
|
@@ -659,6 +677,67 @@ class BaseQuery(Generic[ModelT]):
|
|
|
659
677
|
"""Read a relationship from a join this query already makes."""
|
|
660
678
|
return self.options(_chain(contains_eager, keys))
|
|
661
679
|
|
|
680
|
+
def load_only(self, *columns: Any) -> Self: # noqa: ANN401
|
|
681
|
+
"""Load these columns of the row, and defer the rest.
|
|
682
|
+
|
|
683
|
+
```python
|
|
684
|
+
db.query(User).load_only(User.id, User.name).all()
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
The rows are still instances: a column left out is read from the
|
|
688
|
+
database when something touches it, one statement per instance, which
|
|
689
|
+
is the cost this trades the narrower row for. `only_columns` is the
|
|
690
|
+
other one: it gives the instances up and reads values.
|
|
691
|
+
"""
|
|
692
|
+
return self.options(load_only(*columns))
|
|
693
|
+
|
|
694
|
+
def defer(self, *columns: Any) -> Self: # noqa: ANN401
|
|
695
|
+
"""Leave these columns out of the row until something reads them.
|
|
696
|
+
|
|
697
|
+
```python
|
|
698
|
+
db.query(Post).defer(Post.body).all()
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
For the wide column of a table read for everything else.
|
|
702
|
+
"""
|
|
703
|
+
return self.options(*(defer(column) for column in columns))
|
|
704
|
+
|
|
705
|
+
def undefer(self, *columns: Any) -> Self: # noqa: ANN401
|
|
706
|
+
"""Load these columns with the row, though the model defers them.
|
|
707
|
+
|
|
708
|
+
```python
|
|
709
|
+
db.query(Post).undefer(Post.body).all()
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
The other side of `mapped_column(deferred=True)`, for the read that
|
|
713
|
+
wants the column after all.
|
|
714
|
+
"""
|
|
715
|
+
return self.options(*(undefer(column) for column in columns))
|
|
716
|
+
|
|
717
|
+
def undefer_group(self, name: str) -> Self:
|
|
718
|
+
"""Load the columns a model defers under this group name.
|
|
719
|
+
|
|
720
|
+
```python
|
|
721
|
+
db.query(Post).undefer_group("body").all()
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
The group is the one `mapped_column(deferred_group="body")` names, for
|
|
725
|
+
the columns a read wants together or not at all.
|
|
726
|
+
"""
|
|
727
|
+
return self.options(undefer_group(name))
|
|
728
|
+
|
|
729
|
+
def with_expression(self, key: Any, expression: Any) -> Self: # noqa: ANN401
|
|
730
|
+
"""Give a `query_expression()` attribute its value for this read.
|
|
731
|
+
|
|
732
|
+
```python
|
|
733
|
+
db.query(Post).with_expression(Post.comments, _comment_count()).all()
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
The attribute holds what this statement selects into it, so a count or
|
|
737
|
+
a window function arrives on the instance rather than beside it.
|
|
738
|
+
"""
|
|
739
|
+
return self.options(with_expression(key, expression))
|
|
740
|
+
|
|
662
741
|
def with_for_update(
|
|
663
742
|
self,
|
|
664
743
|
*,
|
|
@@ -327,6 +327,10 @@ class Query(BaseQuery[ModelT]):
|
|
|
327
327
|
```python
|
|
328
328
|
names = User.query.where(User.is_active).only_columns(User.name).all()
|
|
329
329
|
```
|
|
330
|
+
|
|
331
|
+
One column arrives as values and several as tuples, and neither is an
|
|
332
|
+
instance. `load_only` is the other one: the rows stay instances, and
|
|
333
|
+
the columns it leaves out are read when something touches them.
|
|
330
334
|
"""
|
|
331
335
|
return ColumnQuery(
|
|
332
336
|
self.model,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|