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 <mike...@zzzcomputing.com> wrote: > On Feb 7, 2011, at 11:16 AM, Kent wrote: > > > On Feb 4, 12:04 pm, Kent <jkentbo...@gmail.com> 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 <mike...@zzzcomputing.com> 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 <mike...@zzzcomputing.com> 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 sqlalchemy@googlegroups.com. > >>>>>> To unsubscribe from this group, send email to > >>>>>> sqlalchemy+unsubscr...@googlegroups.com. > >>>>>> 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 sqlalchemy@googlegroups.com. > >>>> To unsubscribe from this group, send email to > >>>> sqlalchemy+unsubscr...@googlegroups.com. > >>>> 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 sqlalchemy@googlegroups.com. > > To unsubscribe from this group, send email to > > sqlalchemy+unsubscr...@googlegroups.com. > > 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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.