[Sqlalchemy-tickets] Issue #3054: new idea for bake (zzzeek/sqlalchemy)
Brought to you by:
zzzeek
|
From: Mike B. <iss...@bi...> - 2014-05-16 19:48:39
|
New issue 3054: new idea for bake https://bitbucket.org/zzzeek/sqlalchemy/issue/3054/new-idea-for-bake Mike Bayer: The issue with "bake" has always been the ability to derive an appropriate cache key for a query. Based on the observation of other SQL products that a Python code object presents a direct way of establishing a unique line number in a unique source file, I'd like to see if we can make use of lambdas in order to establish this as a key. Example: ``` #!python def do_something(session): x1 = 5 x2 = 10 q = session.query(Foo).filter(Foo.x == bindparam('x1')).filter(Foo.y == bindparam('x2')) baked = Bake(lambda: q) return baked.params(x1=x1, x2=x2).all() ``` the above: 1. receives the lambda within Bake. We use the code object present here to retrieve the source file and line number. 2. we establish some kind of cache, perhaps within the namespace of the source module itself, that will store everything we need about this query keyed to the line number. 3. Assuming the line number is not in the cache: 3a. we call the lambda and get the Query back. We scan this query for bound parameters and establish those as the arguments we'd use in params(). Note that this includes bound parameters that were created implicitly (see below). 3b. we do the various "bake" things that we do in the [baked query recipe](https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/BakedQuery) with this new Query object. We store what we need in the cache. 3c. we invoke the query with the params and return results. 4. if the line number *is* in the cache: 4a. we get the Query that we've "baked" from this lambda. 4b. we apply the current session, invoke the query with the params and return results. Note that we can pull out the bound parameters without calling bindparam() as well. *And*, if the whole Query is placed into the lambda, then we *dont even need to build the query* in order to get the cached version: ``` #!python def do_something(session): x1 = 5 x2 = 10 baked = Bake(lambda: \ session.query(Foo).filter(Foo.x == 5).filter(Foo.y == 10) ) return baked.params(x1, x2).all() ``` to support the usage of the params without any explicit keys, the `params()` method will also maintain the order in which it encounters these bound parameters and allow the values to be passed positionally in that order. |