]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
two more cache examples
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 24 Oct 2008 19:41:25 +0000 (19:41 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 24 Oct 2008 19:41:25 +0000 (19:41 +0000)
examples/query_caching/implicit.py [new file with mode: 0644]
examples/query_caching/per_session.py [new file with mode: 0644]
examples/query_caching/query_caching.py

diff --git a/examples/query_caching/implicit.py b/examples/query_caching/implicit.py
new file mode 100644 (file)
index 0000000..15a6d12
--- /dev/null
@@ -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 (file)
index 0000000..1268408
--- /dev/null
@@ -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()
+    
index 70dc6683c13f687d62d6a44cef167ac46c980888..92d48e2d787b87ea43b94c1fb70cfab886f84a70 100644 (file)
@@ -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()
     
-    
-    
-