On Thu, Jun 6, 2013 at 2:20 PM, Michael Bayer <mike...@zzzcomputing.com>
wrote:
>
> diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
> index c2ec72c..b458975 100644
> --- a/lib/sqlalchemy/orm/query.py
> +++ b/lib/sqlalchemy/orm/query.py
> @@ -40,12 +40,15 @@ from ..sql import (
>  __all__ = ['Query', 'QueryContext', 'aliased']
>
>
> -def _generative(*assertions):
> +def _generative(*assertions, maintain_baked=False):
>      """Mark a method as generative."""
>
>      @util.decorator
>      def generate(fn, *args, **kw):
>          self = args[0]._clone()
> +        if not maintain_baked:
> +            del self._baked_cache
> +            del self._baked_context
>          for assertion in assertions:
>              assertion(self, fn.func_name)
>          fn(self, *args[1:], **kw)
> @@ -1157,7 +1160,7 @@ class Query(object):
>
>          self._lockmode = mode
>
> -    @_generative()
> +    @_generative(maintain_baked=True)
>      def params(self, *args, **kwargs):
>          """add values for bind parameters which may have been
>          specified in filter().


That doesn't seem to be enough.

subqueryload seems to be using the wrong query still, after clearing the
baked context, resulting in some very wrong sharing of connections between
threads (I'm getting some very fun segmentation faults).

I think it's with_parent, it clears the baked context through a filter, but
the filter is called on the wrong query (the global query instance I use as
template), that has the wrong session attached or something.

This is my current BakedQuery:

 class BakedQuery(sqlalchemy.orm.query.Query):

_baked_context = None

_baked_cache = None


 def _clone(self):

rv = super(BakedQuery, self)._clone()

try:

del rv._baked_context

del rv._baked_cache

except AttributeError:

pass

return rv


 def params(self, *p, **kw):

rv = super(BakedQuery, self).params(*p, **kw)

rv._baked_context = self._baked_context

rv._baked_cache = self._baked_cache

return rv

 def with_session(self, *p, **kw):

rv = super(BakedQuery, self).with_session(*p, **kw)

rv._baked_context = self._baked_context

rv._baked_cache = self._baked_cache

return rv

 @sqlalchemy.orm.query._generative()

def bake_as(self, name, cache):

"""Freeze the statement used by this Query."""


 if name not in cache:

cache[name] = context = self._compile_context()

del context.session

del context.query

self._baked_context = cache[name]

self._baked_cache = cache


 def _compile_context(self, **kw):

if self._baked_context is not None:

QueryContext = sqlalchemy.orm.query.QueryContext

context = QueryContext.__new__(QueryContext)

context.__dict__.update(self._baked_context.__dict__)

context.query = self

context.session = self.session

# need to fix these names, urg

context.attributes = context._attributes = context.attributes.copy()

return context

else:

return super(BakedQuery, self)._compile_context(**kw)


 def _execute_and_instances(self, querycontext):

if self._baked_cache is not None:

self = self.execution_options(compiled_cache=self._baked_cache)

return super(BakedQuery, self)._execute_and_instances(querycontext)



And I invoke it like:


def some_function(query = blabla.bake_as(blablah)):

return query.with_session(S).params(...).first()


This code still breaks if I don't use a baked template:


def some_function(query = blabla):

return query.with_session(S).bake_as(blablah).params(...).first()

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to