On Sep 8, 2010, at 1:15 PM, Kent Bower wrote:
> I imagine you are already aware of this...
>
> Unfortunately, the clause comparison says these two clauses are different:
>
> (Pdb) print self
> locations.siteid = :param_1 AND locations.locationid = :param_2
> (Pdb) print other
> locations.locationid = :param_1 AND locations.siteid = :param_2
>
> when they are really the equivalent. So composite foreign keys need to be
> listed in the correct order for LazyLoader.use_get to optimize the load with
> get().
use clause.compare(). Here's the source for _BinaryExpression:
def compare(self, other, **kw):
"""Compare this :class:`_BinaryExpression` against the
given :class:`_BinaryExpression`."""
return (
isinstance(other, _BinaryExpression) and
self.operator == other.operator and
(
self.left.compare(other.left, **kw) and
self.right.compare(other.right, **kw) or
(
operators.is_commutative(self.operator) and
self.left.compare(other.right, **kw) and
self.right.compare(other.left, **kw)
)
)
)
see the "commutative" in there ? its handled.
>
> I already saw it would be somewhat of an effort to refactor the clause
> comparison to work that out... bummer.
>
>
>
>
> On 9/7/2010 7:28 PM, Michael Bayer wrote:
>>
>>
>> On Sep 7, 2010, at 6:41 PM, Kent Bower wrote:
>>
>>> Two items:
>>>
>>> * How does the orm currently determine whether it is safe to try get()
>>> (e.i. there are no "funny join conditions")? If you point me to the
>>> function where decision takes place, I can probably answer this myself....
>>
>> it compares the join condition of the relationship() to that of the clause
>> which the Mapper uses when it issues get(), then stores that away as a flag
>> for future consultation. It's very unusual for a many-to-one relationship
>> to be based on something other than a simple foreign-key->primary key
>> relationship, though.
>>
>>
>>>
>>> * When I build up the primary key from the foreign key, is there an
>>> efficient way to build a composite key in the correct order to pass to
>>> get()? (I thought maybe "synchronize_pairs", but that maybe has to do with
>>> getting the direction consistent instead?)
>>
>> Well if you aren't using any composite primary keys in many-to-ones, you
>> wouldn't even have to worry about this. Otherwise, the two collections to
>> correlate would be property.local_remote_pairs and
>> property.mapper.primary_key. Perhaps make a dictionary out of dict([(r, l)
>> for l, r in prop.local_remote_pairs]) and your PK value would be
>> [getattr(instance, prop.parent.get_property_by_column(mydict[p]).key) for p
>> in property.mapper.primary_key].
>>
>> Or if you want to get ambitious you can just copy roughly whats in
>> strategies.py on line 605 but then you're digging into internals....and
>> looking at that now I'm wondering if strategy._equated_columns is really
>> different than local_remote_pairs at all...
>>
>>
>>
>>>
>>> Thanks again, you've been much help!
>>>
>>>
>>>
>>> On 9/7/2010 5:03 PM, Michael Bayer wrote:
>>>>
>>>>
>>>> On Sep 7, 2010, at 4:38 PM, Kent Bower wrote:
>>>>
>>>>> Don't want to strangle me, but when the orm (lazy)loads a MANYTONE
>>>>> object, it doesn't go to the database if the object is in the session.
>>>>> Can I get "with_parent()" to behave this way, or would I need to
>>>>> specifically build up the primary key of the related object and call
>>>>> query.get()?
>>>>
>>>> the latter. You can use get() for all many to ones if you aren't using
>>>> any funny join conditions.
>>>>
>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 9/7/2010 10:25 AM, Michael Bayer wrote:
>>>>>>
>>>>>>
>>>>>> On Sep 7, 2010, at 10:12 AM, Kent Bower wrote:
>>>>>>
>>>>>>> Mike, in your proof of concept, when __getstate__ detected transient,
>>>>>>> why did you need to make a copy of self.__dict__? "self.__dict__.copy()"
>>>>>>
>>>>>> i was modifying the __dict__ from what would be expected in a
>>>>>> non-serialized object, so that was to leave the original object being
>>>>>> serialized unchanged.
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 9/6/2010 2:35 PM, Michael Bayer wrote:
>>>>>>>>
>>>>>>>> On Sep 6, 2010, at 2:11 PM, Kent Bower wrote:
>>>>>>>>
>>>>>>>>> Also, I was hoping you would tell me whether this would be a
>>>>>>>>> candidate for subclassing InstrumentedAttribute? Would that make
>>>>>>>>> more sense or providing custom __getstate__ & __setstate__ ?
>>>>>>>> __getstate__ / __setstate__ are pretty much what I like to use for
>>>>>>>> pickle stuff, unless some exotic situation makes me have to use
>>>>>>>> __reduce__. One problem with the recipe is that theres no 'deferred'
>>>>>>>> loading of attributes. So in that sense playing with
>>>>>>>> InstrumentedAttribute would give you a chance to put a callable in
>>>>>>>> there that does what you want.
>>>>>>>>
>>>>>>>> There is also the possibility that __setstate__ can load up callables
>>>>>>>> into the instance_state using state.set_callable(). This is a
>>>>>>>> callable that triggers when you access the attribute that is otherwise
>>>>>>>> None. There's a little bit of fanfare required to get that callable
>>>>>>>> to assign to the attribute in the right way. Attached is an example
>>>>>>>> of that. This is all a little more shaky since the state/callable
>>>>>>>> API isn't really public. Hasn't changed for awhile but there's no
>>>>>>>> guarantee.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>> Thanks for your help, hopefully I'll be able to contribute such a
>>>>>>>>> recipe.
>>>>>>>>>
>>>>>>>>> Kent
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>> Since sqla won't load that for me in the case of transient, I need
>>>>>>>>>>> to load the relation manually (unless you feel like enhancing that
>>>>>>>>>>> as well).
>>>>>>>>>> its not an enhancement - it was a broken behavior that was
>>>>>>>>>> specifically removed. The transient object has no session, so
>>>>>>>>>> therefore no SQL can be emitted - there's no context established.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> Now I can manually emulate the obj being persistent with your
>>>>>>>>>>> changes for
>>>>>>>>>>>
>>>>>>>>>>> On Sep 6, 2010, at 10:58 AM, Michael Bayer
>>>>>>>>>>> <[email protected]> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> On Sep 6, 2010, at 9:06 AM, Kent wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> with_parent seems to add a join condition.
>>>>>>>>>>>> OK, so I guess you read the docs which is why you thought it
>>>>>>>>>>>> joined and why you didn't realize it doesn't work for transient.
>>>>>>>>>>>> r20b6ce05f194 changes all that so that with_parent() accepts
>>>>>>>>>>>> transient objects and will do the "look at the attributes" thing.
>>>>>>>>>>>> The docs are updated as this method does use the lazy loader SQL
>>>>>>>>>>>> mechanism, not a join.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Is there a way to get at
>>>>>>>>>>>>> the query object that would be rendered from a lazy load (or what
>>>>>>>>>>>>> "subqueryload" would render on the subsequent load), but on a
>>>>>>>>>>>>> transient object, if i supply the session?
>>>>>>>>>>>>>
>>>>>>>>>>>>> even though not "recommended", can it make sqla believe my
>>>>>>>>>>>>> transient
>>>>>>>>>>>>> object is detached by setting its state key?
>>>>>>>>>>>>>
>>>>>>>>>>>>> There are reasons i do not want to add this to the session and
>>>>>>>>>>>>> disabling autoflush would also cause problems.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Sep 3, 9:58 am, Michael Bayer <[email protected]> wrote:
>>>>>>>>>>>>>> On Sep 3, 2010, at 9:36 AM, Kent wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> For the case of customerid = '7', that is a simple problem, but
>>>>>>>>>>>>>>> when
>>>>>>>>>>>>>>> it is a more complex join condition, we only wanted to define
>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>> condition in one single place in our application (namely, the
>>>>>>>>>>>>>>> orm).
>>>>>>>>>>>>>>> That way, if or when that changes, developers don't need to
>>>>>>>>>>>>>>> search for
>>>>>>>>>>>>>>> other places in the app that needed to manually duplicate the
>>>>>>>>>>>>>>> logic of
>>>>>>>>>>>>>>> the orm join condition.
>>>>>>>>>>>>>>> If I supplied the DBSession to sqla, it would know how to
>>>>>>>>>>>>>>> create the
>>>>>>>>>>>>>>> proper Query object for this lazyload. Can you point me in the
>>>>>>>>>>>>>>> right
>>>>>>>>>>>>>>> direction (even if where you point me is not currently part of
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> public API)?
>>>>>>>>>>>>>> Query has the with_parent() method for this use case.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Thanks again,
>>>>>>>>>>>>>>> Kent
>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>> 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.
>>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> 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.
>>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> 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.
>>>>>>
>>>>>> --
>>>>>> 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.
>>>>
>>>> --
>>>> 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.
>>
>> --
>> 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.
--
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.