diff options
Diffstat (limited to 'examples/beaker_caching/advanced.py')
-rw-r--r-- | examples/beaker_caching/advanced.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/examples/beaker_caching/advanced.py b/examples/beaker_caching/advanced.py new file mode 100644 index 000000000..6a8db082c --- /dev/null +++ b/examples/beaker_caching/advanced.py @@ -0,0 +1,79 @@ +"""advanced.py + +Illustrate usage of Query combined with the FromCache option, +including front-end loading, cache invalidation, namespace techniques +and collection caching. + +""" + +import __init__ # if running as a script +from model import Person, Address, cache_address_bits +from meta import Session, FromCache +from sqlalchemy.orm import eagerload + +def load_name_range(start, end, invalidate=False): + """Load Person objects on a range of names. + + start/end are integers, range is then + "person <start>" - "person <end>". + + The cache option we set up is called "name_range", indicating + a range of names for the Person class. + + The `Person.addresses` collections are also cached. Its basically + another level of tuning here, as that particular cache option + can be transparently replaced with eagerload(Person.addresses). + The effect is that each Person and his/her Address collection + is cached either together or separately, affecting the kind of + SQL that emits for unloaded Person objects as well as the distribution + of data within the cache. + """ + q = Session.query(Person).\ + filter(Person.name.between("person %.2d" % start, "person %.2d" % end)).\ + options(cache_address_bits).\ + options(FromCache("default", "name_range")) + + # have the "addresses" collection cached separately + # each lazyload of Person.addresses loads from cache. + q = q.options(FromCache("default", "by_person", Person.addresses)) + + # alternatively, eagerly load the "addresses" collection, so that they'd + # be cached together. This issues a bigger SQL statement and caches + # a single, larger value in the cache per person rather than two + # separate ones. + #q = q.options(eagerload(Person.addresses)) + + # if requested, invalidate the cache on current criterion. + if invalidate: + q.invalidate() + + return q.all() + +print "two through twelve, possibly from cache:\n" +print ", ".join([p.name for p in load_name_range(2, 12)]) + +print "\ntwenty five through forty, possibly from cache:\n" +print ", ".join([p.name for p in load_name_range(25, 40)]) + +# loading them again, no SQL is emitted +print "\ntwo through twelve, from the cache:\n" +print ", ".join([p.name for p in load_name_range(2, 12)]) + +# but with invalidate, they are +print "\ntwenty five through forty, invalidate first:\n" +print ", ".join([p.name for p in load_name_range(25, 40, True)]) + +# illustrate the address loading from either cache/already +# on the Person +print "\n\nPeople plus addresses, two through twelve, addresses possibly from cache" +for p in load_name_range(2, 12): + print p.format_full() + +# illustrate the address loading from either cache/already +# on the Person +print "\n\nPeople plus addresses, two through twelve, addresses from cache" +for p in load_name_range(2, 12): + print p.format_full() + +print "\n\nIf this was the first run of advanced.py, try "\ + "a second run. Only one SQL statement will be emitted." |