diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-10-24 19:41:25 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-10-24 19:41:25 +0000 |
| commit | eba763b2588987224c6313b4d1c9f8feec616c1d (patch) | |
| tree | 9e108798e6e8342ba090de3dde9a6dd6f3dd296d /examples | |
| parent | ecf22b390b3d3b44d6094ee0355748b4d163fccb (diff) | |
| download | sqlalchemy-eba763b2588987224c6313b4d1c9f8feec616c1d.tar.gz | |
two more cache examples
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/query_caching/implicit.py | 70 | ||||
| -rw-r--r-- | examples/query_caching/per_session.py | 73 | ||||
| -rw-r--r-- | examples/query_caching/query_caching.py | 5 |
3 files changed, 145 insertions, 3 deletions
diff --git a/examples/query_caching/implicit.py b/examples/query_caching/implicit.py new file mode 100644 index 000000000..15a6d121a --- /dev/null +++ b/examples/query_caching/implicit.py @@ -0,0 +1,70 @@ +"""Example of caching objects in a per-session cache, +including implicit usage of the statement and params as a key. + +""" +from sqlalchemy.orm.query import Query +from sqlalchemy.orm.session import Session + +class CachingQuery(Query): + + # single point of object loading is __iter__(). objects in the cache are not associated + # with a session and are never returned directly; only merged copies. + def __iter__(self): + try: + cache = self.session._cache + except AttributeError: + self.session._cache = cache = {} + + stmt = self.statement.compile() + params = stmt.params + params.update(self._params) + cachekey = str(stmt) + str(params) + + try: + ret = cache[cachekey] + except KeyError: + ret = list(Query.__iter__(self)) + cache[cachekey] = ret + + return iter(ret) + + +# example usage +if __name__ == '__main__': + from sqlalchemy import Column, create_engine, Integer, String + from sqlalchemy.orm import sessionmaker + from sqlalchemy.ext.declarative import declarative_base + + Session = sessionmaker(query_cls=CachingQuery) + + Base = declarative_base(engine=create_engine('sqlite://', echo=True)) + + class User(Base): + __tablename__ = 'users' + id = Column(Integer, primary_key=True) + name = Column(String(100)) + + def __repr__(self): + return "User(name=%r)" % self.name + + Base.metadata.create_all() + + sess = Session() + + sess.add_all( + [User(name='u1'), User(name='u2'), User(name='u3')] + ) + sess.commit() + + # issue a query + print sess.query(User).filter(User.name.in_(['u2', 'u3'])).all() + + # issue another + print sess.query(User).filter(User.name == 'u1').all() + + # pull straight from cache + print sess.query(User).filter(User.name.in_(['u2', 'u3'])).all() + + print sess.query(User).filter(User.name == 'u1').all() + + diff --git a/examples/query_caching/per_session.py b/examples/query_caching/per_session.py new file mode 100644 index 000000000..12684082c --- /dev/null +++ b/examples/query_caching/per_session.py @@ -0,0 +1,73 @@ +"""Example of caching objects in a per-session cache. + + +This approach is faster in that objects don't need to be detached/remerged +between sessions, but is slower in that the cache is empty at the start +of each session's lifespan. + +""" + +from sqlalchemy.orm.query import Query, _generative +from sqlalchemy.orm.session import Session + +class CachingQuery(Query): + + # generative method to set a "cache" key. The method of "keying" the cache + # here can be made more sophisticated, such as caching based on the query._criterion. + @_generative() + def with_cache_key(self, cachekey): + self.cachekey = cachekey + + # single point of object loading is __iter__(). objects in the cache are not associated + # with a session and are never returned directly; only merged copies. + def __iter__(self): + if hasattr(self, 'cachekey'): + try: + cache = self.session._cache + except AttributeError: + self.session._cache = cache = {} + + try: + ret = cache[self.cachekey] + except KeyError: + ret = list(Query.__iter__(self)) + cache[self.cachekey] = ret + + return iter(ret) + + else: + return Query.__iter__(self) + +# example usage +if __name__ == '__main__': + from sqlalchemy import Column, create_engine, Integer, String + from sqlalchemy.orm import sessionmaker + from sqlalchemy.ext.declarative import declarative_base + + Session = sessionmaker(query_cls=CachingQuery) + + Base = declarative_base(engine=create_engine('sqlite://', echo=True)) + + class User(Base): + __tablename__ = 'users' + id = Column(Integer, primary_key=True) + name = Column(String(100)) + + def __repr__(self): + return "User(name=%r)" % self.name + + Base.metadata.create_all() + + sess = Session() + + sess.add_all( + [User(name='u1'), User(name='u2'), User(name='u3')] + ) + sess.commit() + + # cache two user objects + sess.query(User).with_cache_key('u2andu3').filter(User.name.in_(['u2', 'u3'])).all() + + # pull straight from cache + print sess.query(User).with_cache_key('u2andu3').all() + diff --git a/examples/query_caching/query_caching.py b/examples/query_caching/query_caching.py index 70dc6683c..92d48e2d7 100644 --- a/examples/query_caching/query_caching.py +++ b/examples/query_caching/query_caching.py @@ -1,3 +1,5 @@ +"""Example of caching objects in a global cache.""" + from sqlalchemy.orm.query import Query, _generative from sqlalchemy.orm.session import Session @@ -67,6 +69,3 @@ if __name__ == '__main__': # pull straight from cache print sess.query(User).with_cache_key('u2andu3').all() - - - |
