For whatever reason I couldn't use compiler.is_subquery():
return len(self.stack) > 1
I guess from this context I need: len(self.stack) > 0
Not sure why, except that I'm "one stack level" off when the @compiles
function is invoked to be able to use compiler.is_subquery().
@compiles(Select)
def compile_forupdateof(select, compiler, **kw):
rendered = compiler.visit_select(select, **kw)
if not compiler.stack and hasattr(select, '_for_update_of'):
mapper = class_mapper(select._for_update_of)
name = mapper.mapped_table.name
if compiler.dialect.name == 'oracle':
# Oracle makes us specify the column name (for views, I
guess, since it locks entire row)
name += '.' + mapper.primary_key[0].name
rendered = "%s FOR UPDATE OF %s" % (rendered, name)
return rendered
On Feb 7, 11:20 am, Michael Bayer <[email protected]> wrote:
> On Feb 7, 2011, at 11:16 AM, Kent wrote:
>
> > On Feb 4, 12:04 pm, Kent <[email protected]> wrote:
> >> Excellent, it is working for the simpler case, but for oracle 8 (who
> >> isn't as smart when indexing) I also need it to work for
> >> subqueryload().
>
> >> So the problem is that my FOR UPDATE OF is also being added for
> >> subqueryload selects.
>
> >> * Can I tell within the compiles context if this is for subqueryload?
> >> (Or can the Query tell?)
>
> > What I worked out based on compiler.is_subquery() is that
> > compiler.stack (in other words, bool(compiler.stack)) should tell me
> > if this is a subqueryload. Does that sound accurate?
>
> yes that is actually the appropriate way to detect if the current context is
> that of a subquery. (is_subquery() that is. I'd prefer that over peeking
> into the stack itself).
>
>
>
> >> * Are there other cases where the query is "reused" that I need to be
> >> careful of?
>
> >> I restructured this way (as you're original suggestion to fix another
> >> issue):
>
> >> @compiles(Select)
> >> def compile_forupdateof(select, compiler, **kw):
> >> rendered = compiler.visit_select(select, **kw)
> >> if hasattr(select, '_for_update_of'):
> >> mapper = class_mapper(select._for_update_of)
> >> name = mapper.mapped_table.name
> >> if compiler.dialect.name == 'oracle':
> >> # Oracle makes us specify the column name (for views, I
> >> guess, since it locks entire row)
> >> name += '.' + mapper.primary_key[0].name
> >> rendered = "%s FOR UPDATE OF %s" % (rendered, name)
> >> return rendered
>
> >> On Feb 3, 9:51 pm, Michael Bayer <[email protected]> wrote:
>
> >>> On Feb 3, 2011, at 9:29 PM, Kent wrote:
>
> >>>> Yeah, I wanted to apologize because my heart wants to contribute to
> >>>> the project (really), but I'm working overtime like mad swamped
> >>>> because our product is live in use now and I've got a backload of
> >>>> tickets to solve! I also feel my level of understanding currently is
> >>>> more hacking than contributing. I hope to be of more help to the
> >>>> project in the future.
>
> >>>> Is "simpler than you had in mind" a good thing or am I over
> >>>> simplifying and it won't work for bunch of cases?
>
> >>>> I note that the simple case is working, but something like this fails:
>
> >>>> DBSession.query(Order).for_update_of(Order).limit(10).all()
>
> >>>> since I really need to have the for update inside in this case... any
> >>>> advise or is this what you meant by "There's not a great way to
> >>>> intercept the middle of the SELECT compilation with a new kind of
> >>>> clause in this case."?
>
> >>> i think if it works for what you need right now, then its great.
> >>> @compiles is meant to give you what you need to get out of a jam.
>
> >>>> On Feb 3, 9:07 pm, Michael Bayer <[email protected]> wrote:
> >>>>> oh OK this is a little simpler than what I had in mind, you just have
> >>>>> to add the mixin expression.Executable to your ForUpdateOf class.
>
> >>>>> On Feb 3, 2011, at 9:05 PM, Kent wrote:
>
> >>>>>> Here is a crude outline (need to properly escape table name, etc.), of
> >>>>>> what I think might work, and it seems to render properly, but crashes
> >>>>>> with:
>
> >>>>>> File "/home/rarch/tg2env/lib/python2.6/site-packages/
> >>>>>> SQLAlchemy-0.6.4.2kbdev-py2.6-linux-x86_64.egg/sqlalchemy/engine/
> >>>>>> default.py", line 353, in __init__
> >>>>>> raise exc.ArgumentError("Not an executable clause: %s" % compiled)
> >>>>>> ArgumentError: Not an executable clause:
> >>>>>> ...
>
> >>>>>> class MyQuery(Query):
> >>>>>> _for_update_of = None
>
> >>>>>> @_generative()
> >>>>>> def for_update_of(self, arg):
> >>>>>> """Keep track that we want to for update of this"""
> >>>>>> self._for_update_of = class_mapper(arg).mapped_table.name
>
> >>>>>> def _compile_context(self, labels=True):
> >>>>>> context = super(MyQuery, self)._compile_context(labels)
> >>>>>> if self._for_update_of:
> >>>>>> context.statement = ForUpdateOf(context.statement,
> >>>>>> self._for_update_of)
> >>>>>> return context
>
> >>>>>> class ForUpdateOf(ClauseElement):
> >>>>>> def __init__(self, statement, for_update_of):
> >>>>>> self.statement = statement
> >>>>>> self.for_update_of = for_update_of
>
> >>>>>> @compiles(ForUpdateOf)
> >>>>>> def compile_forupdateof(element, compiler, **kw):
> >>>>>> return "%s FOR UPDATE OF %s" %
> >>>>>> (compiler.process(element.statement), element.for_update_of)
>
> >>>>>> --
> >>>>>> You received this message because you are subscribed to the Google
> >>>>>> Groups "sqlalchemy" group.
> >>>>>> To post to this group, send email to [email protected].
> >>>>>> To unsubscribe from this group, send email to
> >>>>>> [email protected].
> >>>>>> For more options, visit this group
> >>>>>> athttp://groups.google.com/group/sqlalchemy?hl=en.
>
> >>>> --
> >>>> You received this message because you are subscribed to the Google
> >>>> Groups "sqlalchemy" group.
> >>>> To post to this group, send email to [email protected].
> >>>> To unsubscribe from this group, send email to
> >>>> [email protected].
> >>>> For more options, visit this group
> >>>> athttp://groups.google.com/group/sqlalchemy?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "sqlalchemy" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to
> > [email protected].
> > For more options, visit this group
> > athttp://groups.google.com/group/sqlalchemy?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.