--- /dev/null
+.. change::
+ :tags: bug, examples
+
+ The dogpile_caching examples have been updated for 2.0 style queries.
+ Within the "caching query" logic itself there is one conditional added to
+ differentiate between ``Query`` and ``select()`` when performing an
+ invalidation operation.
"""Illustrate usage of Query combined with the FromCache option,
including front-end loading, cache invalidation and collection caching.
+
"""
+from sqlalchemy import select
from .caching_query import FromCache
from .caching_query import RelationshipCache
from .environment import cache
of data within the cache.
"""
q = (
- Session.query(Person)
+ select(Person)
.filter(
Person.name.between("person %.2d" % start, "person %.2d" % end)
)
cache.invalidate(q, {}, FromCache("default", "name_range"))
cache.invalidate(q, {}, RelationshipCache(Person.addresses, "default"))
- return q.all()
+ return Session.scalars(q).all()
print("two through twelve, possibly from cache:\n")
from sqlalchemy import event
from sqlalchemy.orm import loading
+from sqlalchemy.orm import Query
from sqlalchemy.orm.interfaces import UserDefinedOption
dogpile_region = self.cache_regions[opt.region]
our_cache_key = opt._generate_cache_key(
- orm_context.statement, orm_context.parameters, self
+ orm_context.statement, orm_context.parameters or {}, self
)
if opt.ignore_expiration:
def invalidate(self, statement, parameters, opt):
"""Invalidate the cache value represented by a statement."""
- statement = statement.__clause_element__()
+ if isinstance(statement, Query):
+ statement = statement.__clause_element__()
dogpile_region = self.cache_regions[opt.region]
"""
+from sqlalchemy import select
from .caching_query import FromCache
from .environment import cache
from .environment import Session
# load Person objects. cache the result in the "default" cache region
print("loading people....")
-people = Session.query(Person).options(FromCache("default")).all()
+people = Session.scalars(select(Person).options(FromCache("default"))).all()
# remove the Session. next query starts from scratch.
Session.remove()
# load again, using the same FromCache option. now they're cached,
# so no SQL is emitted.
print("loading people....again!")
-people = Session.query(Person).options(FromCache("default")).all()
+people = Session.scalars(select(Person).options(FromCache("default"))).all()
# Specifying a different query produces a different cache key, so
# these results are independently cached.
print("loading people two through twelve")
-people_two_through_twelve = (
- Session.query(Person)
+people_two_through_twelve = Session.scalars(
+ select(Person)
.options(FromCache("default"))
.filter(Person.name.between("person 02", "person 12"))
- .all()
-)
+).all()
# the data is cached under string structure of the SQL statement, *plus*
# the bind parameters of the query. So this query, having
# different literal parameters under "Person.name.between()" than the
# previous one, issues new SQL...
print("loading people five through fifteen")
-people_five_through_fifteen = (
- Session.query(Person)
+people_five_through_fifteen = Session.scalars(
+ select(Person)
.options(FromCache("default"))
.filter(Person.name.between("person 05", "person 15"))
- .all()
-)
+).all()
# ... but using the same params as are already cached, no SQL
print("loading people two through twelve...again!")
-people_two_through_twelve = (
- Session.query(Person)
+people_two_through_twelve = Session.scalars(
+ select(Person)
.options(FromCache("default"))
.filter(Person.name.between("person 02", "person 12"))
- .all()
-)
+).all()
# invalidate the cache for the three queries we've done. Recreate
cache.invalidate(Session.query(Person), {}, FromCache("default"))
cache.invalidate(
- Session.query(Person).filter(
- Person.name.between("person 02", "person 12")
- ),
+ select(Person).filter(Person.name.between("person 02", "person 12")),
{},
FromCache("default"),
)
cache.invalidate(
- Session.query(Person).filter(
- Person.name.between("person 05", "person 15")
- ),
+ select(Person).filter(Person.name.between("person 05", "person 15")),
{},
FromCache("default", "people_on_range"),
)
from dogpile.cache.api import NO_VALUE
from dogpile.cache.region import register_backend
+from sqlalchemy import select
from . import environment
from .caching_query import FromCache
from .environment import regions
# query to load Person by name, with criterion
# of "person 10"
q = (
- Session.query(Person)
+ select(Person)
.filter(Person.name == "person 10")
.options(FromCache("local_session"))
)
# load from DB
- person10 = q.one()
+ person10 = Session.scalars(q).one()
# next call, the query is cached.
- person10 = q.one()
+ person10 = Session.scalars(q).one()
# clear out the Session. The "_cache_dictionary" dictionary
# disappears with it.
Session.remove()
# query calls from DB again
- person10 = q.one()
+ person10 = Session.scalars(q).one()
# identity is preserved - person10 is the *same* object that's
# ultimately inside the cache. So it is safe to manipulate
# inserts, deletes, or modification to attributes that are
# part of query criterion, still require careful invalidation.
cache_key = FromCache("local_session")._generate_cache_key(
- q._statement_20(), {}, environment.cache
+ q, {}, environment.cache
)
assert person10 is regions["local_session"].get(cache_key)().scalar()
"""
import os
+from sqlalchemy import select
from sqlalchemy.orm import joinedload
from .environment import root
from .environment import Session
from .model import Person
-for p in Session.query(Person).options(
- joinedload(Person.addresses), cache_address_bits
-):
+for p in Session.scalars(
+ select(Person).options(joinedload(Person.addresses), cache_address_bits)
+).unique():
print(p.format_full())