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 >>>>>>>>>>> <mike...@zzzcomputing.com> 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 <mike...@zzzcomputing.com> 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 >>>>>>>>>>>>>>> sqlalch...@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 sqlalch...@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. >>>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>>>>> Groups "sqlalchemy" group. >>>>>>>>>>>> To post to this group, send email to sqlalch...@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. >>>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>>>> Groups "sqlalchemy" group. >>>>>>>>>>> To post to this group, send email to sqlalch...@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. >>>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>>> Groups "sqlalchemy" group. >>>>>>>>>> To post to this group, send email to sqlalch...@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. >>>>>>>>>> >>>>>>>>> -- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "sqlalchemy" group. >>>>>>>>> To post to this group, send email to sqlalch...@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. >>>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "sqlalchemy" group. >>>>>>> To post to this group, send email to sqlalch...@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. >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "sqlalchemy" group. >>>>>> To post to this group, send email to sqlalch...@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. >>>>> >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google Groups >>>>> "sqlalchemy" group. >>>>> To post to this group, send email to sqlalch...@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. >>>> >>>> -- >>>> You received this message because you are subscribed to the Google Groups >>>> "sqlalchemy" group. >>>> To post to this group, send email to sqlalch...@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. >>> >>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "sqlalchemy" group. >>> To post to this group, send email to sqlalch...@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. >> >> -- >> You received this message because you are subscribed to the Google Groups >> "sqlalchemy" group. >> To post to this group, send email to sqlalch...@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. > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalch...@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. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@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.