diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-10-03 15:55:04 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-10-04 12:09:29 -0400 |
| commit | 95d4cd30420414fcede2662aed87b0f2e5a861d4 (patch) | |
| tree | b77df1c621fdea15a95a784fae5c76765c117bbd /doc | |
| parent | 728ce8cc480d0ada690e5a97067cff821b9a65f3 (diff) | |
| download | sqlalchemy-95d4cd30420414fcede2662aed87b0f2e5a861d4.tar.gz | |
Enhance "raise" strategy to include "raise_on_sql" option
The "raise_on_sql" option differentiates from "raise" in that
firing a lazy loader is OK as long as it does a simple
get from identity map. Whereas "raise" is more useful
for the case that objects are to be detached.
As part of this, refactors the strategy initiation logic
a bit so that a LoaderStrategy itself knows what "key" was used
to create it, thus allowing variants of a single strategy
based on what the "lazy" argument is. To achieve this we
have to also get rid of _get_strategy_by_cls().
Everything here is internal with the one exception of an apparently
undocumented, but not underscored, "strategy_class" key
on relationship(). Though it's not clear what
"strategy_class" accomplishes; at this point the strategy
system is extensible using Property.strategy_for().
Fixes: #3812
Change-Id: I812ad878ea5cf764e15f6f71cb39eee78a645d88
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/build/changelog/changelog_11.rst | 10 | ||||
| -rw-r--r-- | doc/build/changelog/migration_11.rst | 26 |
2 files changed, 29 insertions, 7 deletions
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index a3cc96f99..6e2fc014c 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -22,6 +22,16 @@ :version: 1.1.0 .. change:: + :tags: feature, orm + :tickets: 3812 + + Enhanced the new "raise" lazy loader strategy to also include a + "raise_on_sql" variant, available both via :paramref:`.orm.relationship.lazy` + as well as :func:`.orm.raiseload`. This variant only raises if the + lazy load would actually emit SQL, vs. raising if the lazy loader + mechanism is invoked at all. + + .. change:: :tags: bug, orm :tickets: 3808 diff --git a/doc/build/changelog/migration_11.rst b/doc/build/changelog/migration_11.rst index e514f4dbb..7f8ead143 100644 --- a/doc/build/changelog/migration_11.rst +++ b/doc/build/changelog/migration_11.rst @@ -1019,21 +1019,33 @@ added to the :ref:`mutable_toplevel` extension, to complement the existing .. _change_3512: -New "raise" loader strategy ---------------------------- +New "raise" / "raise_on_sql" loader strategies +---------------------------------------------- To assist with the use case of preventing unwanted lazy loads from occurring -after a series of objects are loaded, the new "lazy='raise'" strategy and +after a series of objects are loaded, the new "lazy='raise'" and +"lazy='raise_on_sql'" strategies and corresponding loader option :func:`.orm.raiseload` may be applied to a relationship attribute which will cause it to raise ``InvalidRequestError`` -when a non-eagerly-loaded attribute is accessed for read:: +when a non-eagerly-loaded attribute is accessed for read. The two variants +test for either a lazy load of any variety, including those that would +only return None or retrieve from the identity map:: + + >>> from sqlalchemy.orm import raiseload + >>> a1 = s.query(A).options(raiseload(A.some_b)).first() + >>> a1.some_b + Traceback (most recent call last): + ... + sqlalchemy.exc.InvalidRequestError: 'A.some_b' is not available due to lazy='raise' + +Or a lazy load only where SQL would be emitted:: >>> from sqlalchemy.orm import raiseload - >>> a1 = s.query(A).options(raiseload(A.bs)).first() - >>> a1.bs + >>> a1 = s.query(A).options(raiseload(A.some_b, sql_only=True)).first() + >>> a1.some_b Traceback (most recent call last): ... - sqlalchemy.exc.InvalidRequestError: 'A.bs' is not available due to lazy='raise' + sqlalchemy.exc.InvalidRequestError: 'A.bs' is not available due to lazy='raise_on_sql' :ticket:`3512` |
