On Feb 7, 2011, at 11:26 AM, Kent wrote:

> 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


Oh, because the stack increment/decrement is inside of visit_select(), and 
you're wrapping outside of that.

I can assure you, you know more about the internals of the compiler now than is 
needed for that patch ;)






> 
> 
> 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.
> 

-- 
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.

Reply via email to