i think you underestimate how destablizing and complicated this  
feature would really be.

youre basically saying that Hibernate supports mutation operations  
upon instrumented collections, without it needing to load the full  
state of those collections from the database.   how would this  
support the add() method on Set (need to replace an existing item  
which may not be loaded) ?  __contains__() ?  __setitem__() (recall  
we might need to maintain ordering) ?  i dont really see how that  
would work.  append() seems to be the only method where we can even  
get away with it, and im not completely sure that is without issues.

right now, the collection implementation corresponding to a relation 
() can be anything; a list, dict, Set, user-defined object, etc.,    
it is only created after the entire collection has been loaded, so  
there is no ambiguity over its contents and no surprises or  
assumptions with any operations upon those collections.    to do away  
with that means we have to greatly complicate the instrumentation of  
collection classes, add built-in latency to at least the append()  
method if not many others, and make lots of assumptions about which  
methods do trigger a load and which ones do not... all for what is  
essentially just an optimization.    SA greatly favors stability and  
simplicity over optimizations...things are complicated enough and I  
already have to spend several hours every day just getting what we  
have to be stable.

i would be really surprised if hibernate's collection instrumentation  
actually allows mutating operations upon collections while allowing  
those collections to exist in only a partially loaded or empty  
state.  but if so, perhaps someone can contribute a python port of  
this instrumentation...i  dont have the resources to create such a  
feature right now.

i think the best compromise would be to make an option in the  
attributes package, such that the callable() step it does to fire the  
lazy loader would be ignored by the get() operation and would instead  
be handed off to the user-defined list class itself, meaning your  
list class would get a handle on the callable() that returns your  
results; then its your job to call that function when you need the  
data.    that way nobody has to share the pain of adding this feature  
across the board and those who desire such an optimization can load  
up an extension for a "lazy-enabled collection" and deal with all the  
issues on a localized level.

        class MyCollection(object):
                def __init__(self, callable):
                        self.callable = callable
                        self.data = None
                def __getitem__(self, item):
                        if self.data is None:
                                self.data = callable()
                        return self.data[item]

        class SomeClass(object):
                rels = MyCollection

        mapper (SomeClass, sometable, properties =
                        {'rels':relation(someotherclass, lazy=True, 
custom_lazy=True)}
        )



On Jul 18, 2006, at 7:49 PM, Daniel Miller wrote:

>
> Michael Bayer wrote:
>> you might want to try:
>>     mapper (someclass, sometable, properties = {
>>             'rels' : relation(someotherclass, lazy=None)
>>         })
>> which will turn off all loading on the "rels" attribute.    im not  
>> sure how well thats going to work since it hasnt been tested very  
>> strongly within the context of a flush(), etc.  but it fixes your  
>> unit test even when a flush() is added to the bottom.
>
> I ended up opting for a different solution (remove the backref and  
> add the second property manually):
>
> relmapper = mapper(Relation, rel_table)
> mapper(Information, info_table, properties={
>    'rels': relation(Relation)
> })
> relmapper.add_property("info", relation(Information))
>
>
>> if you have half a million "rels", then the relation() function is  
>> not particularly useful for loads since theres currently no way to  
>> limit the rows you fetch.
>
> Well half a million was an exaggeration, but the thing that really  
> concerns me is that the backref caused an extra database hit when  
> it was not needed. The ORM certainly does not need to fetch those  
> extra rows from the database just to insert a new one, and the  
> whole point of lazy relationships is to defer loading of objects as  
> long as possible.
>
>> it seems like the overall feature youre looking for is "extra lazy  
>> loading", which is a pretty large feature.  adding small hacks to  
>> attributes.py is only going to complicate the attributes module  
>> unnecessarily and not really going to solve the issue.
>
> I don't think so. What you're calling "extra lazy loading" is  
> really more true lazy loading. The backref feature causes a lazy  
> relationship to be loaded when it is not needed, so it's doing a  
> bit less than true lazy loading in this case.
>
>> or maybe you just want "rels" to be there for the purposes of flush 
>> () but you dont care about loading; in that case maybe the above  
>> solves it (then again why even bother having a "rels" attribute?   
>> why not just define the relation in the other direction only? )
>
> Well, I need info.rels sometimes, but I don't want them when I'm  
> just working with a single "rel" and its associated "info".
>
>> one goal of SA is to not add huge complication to the core just to  
>> suit relatively rare use cases, such as heavy manipulation of  
>> detached objects with lazy loaders attached to them.  if you want  
>> the benefits of lazy loading, then you have to have the objects in  
>> a session.
>
> You can downplay my use case as "rare" if that makes you happy. I'm  
> just trying to point out that the backref feature has an annoying  
> side affect that circumvents the main objective of lazy loading--to  
> defer loading until absolutely necessary. It's OK though, I think  
> I've found a simple solution that works so I'm satisfied.
>
> ~ Daniel
>
>
>


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

Reply via email to