On Sep 10, 2010, at 5:16 PM, Kent Bower wrote:

> Actually, my coworker and I were discussing, if the foreign key is specified, 
> whether transient, pending (with autoflush off), or persistent, you 
> intuitively *expect* that referencing the attribute will load the persistent 
> related object.

I dont agree with that, if you are aware that your objects represent a linkage 
to a database transaction.   If I wrote a program and all it said was "select * 
from table", where's "table" ? Don't i need to tell it about a database to 
connect to ?  It is totally surprise behavior, which is why we took it out 
years ago.    As far as "pending", autoflush takes care of it.   Turning off 
autoflush means you're preventing the ORM from being able to automatically 
synchronize state to the current transaction.

> 
> The difficultly for sqlalchemy is that you have no idea what session to pull 
> it from.  However, for many users, there is only one (Scoped)Session at a 
> time, so there is no ambiguity.  In that case, I'd argue the correct behavior 
> is load the object/collection, if possible....

Having objects be "associated" with a Session, but then they aren't really 
"associated" with it, is entirely confusing - it would mean adding a fifth 
object state to our list of states.   The rationale is muddy.  Would it be, 
Session.add_with_asterisk(object) ?    It would be impossible to document 
without confusing everyone, the rationale is unclear, etc.  The ScopedSession 
is a thread local, but that's *all* it is.  Once you have the ORM magically 
"find" it, which we absolutely used to do, now your system is magic.  People 
are immediately wary of the whole thing once you start doing things like that.

What is needed here is some way for developers to add more custom behavior to 
mapped attributes, as well as more granular forms of various ORM behaviors like 
lazyloading, so that custom behaviors outside the core ORM paradigm can be 
engineered.   I would like there to be a simple recipe to enable this behavior, 
but it would be code that invested developers apply to their applications - not 
built in "optional" behavior.

I must be extremely protective of the core ORM paradigm.   If switches and 
flags allow it to behave differently, first of all the burden of test coverage 
shoots up like a rocket - now dozens/hundreds of tests have to be duplicated to 
ensure they work as expected with this new "flag".   The switches find their 
way into online HOWTOs, confusing users who now think the feature must be used 
at all times.   This is a *huge* problem.    I see tons of code that uses all 
kinds of un-needed features like "threadlocal", "Session.mapper", 
"clear_mappers", "Session.flush()" called once , twice, before each "commit()", 
inappropriate usage of the old "entity_name" feature - every optional behavior 
there is gets misunderstood and abused - users who google around for SQLAlchemy 
then see these horrendous examples and tweet/blog how "overly complicated" and 
"perlish" SQLAlchemy is.   So this is a large documentation problem as well as 
a leakage of ambiguous functionality, and its my central focus for a few years 
now to seal it up, remove everything that is not part of one simple behavior, 
while striving to provide an open ended system that allows their use cases to 
be met.    The goal with core API is to continue shrinking it.   Synonym(), 
comparable_property() are next, as more generalized forms of these have been 
devised, and I am very close to removing "composite" though that will probably 
remain in 0.7 without deprecation.


> (The other expected behavior, which I hope to tackle, is that if you change a 
> foreign key reference and the ORM *knows* it is a foreign key reference to a 
> loaded relation, it should expire that relation... I've asked you about that 
> and you said it was a big undertaking... I wish I understood why better, 
> because my plan is to implement this for my project and my hopes are that 
> whatever has stopped you from doing so for sqlalchemy won't be an issue for 
> our use case)

That feature is something I am open to exploring.    But very hesitantly - 
state management and expiration types of issues are extremely complicated, 
another reason why I constantly seek a simpler, more constrained model with 
zero ambiguities in its behavior.   The model of "if you want state management, 
give the ORM state", i.e. as opposed to foreign key identifiers, has worked 
very well.



> 
> 
> 
> 
> On 9/10/2010 5:07 PM, Michael Bayer wrote:
>> I almost needed the exact same feature you have the other day.    So I 
>> wouldn't close the book on it.   I just know that as default behavior, or 
>> even readily switchable behavior, non-invested users get confused rather 
>> quickly.
>> 
>> 
>> On Sep 10, 2010, at 4:21 PM, Kent Bower wrote:
>> 
>>> I've got a "fix" for our project.  Python is really cool about letting you 
>>> reassign methods and functions, so I just reassigned 
>>> CollectionAttributeImpl._set_iterable to my own function.
>>> 
>>> The point is, for my sake, don't worry about a public API, unless others 
>>> also ask about it...
>>> 
>>> Thanks for your help.
>>> 
>>> 
>>> 
>>> On 9/10/2010 3:27 PM, Michael Bayer wrote:
>>>> Sent from my iPhone
>>>> 
>>>> On Sep 10, 2010, at 2:11 PM, Kent Bower<k...@retailarchitects.com>   wrote:
>>>> 
>>>>> I'm headed that direction now, thanks.
>>>>> 
>>>>> I didn't find anything on the wiki for how to plug in a subclassed 
>>>>> CollectionAttributeImpl, for example.  I could hack it, but is there a 
>>>>> public or preferred way?
>>>> Well this is all entirely uncharted territory.  Ideally there would be 
>>>> solid public Apis for this stuff but especially in highly customized 
>>>> situations like this, they need to be specified very carefully.  It seems 
>>>> at least that the lazy callables techniques might be further exposed.
>>>> 
>>>>>> this is a lot to review, and I'll try to get to it, but since you're 
>>>>>> digging into internals anyway have you considered just creating your own 
>>>>>> AttributeImpl subclasses ?   You can then implement get()/set() and make 
>>>>>> it do whatever you'd like.
>>>>>> 
>>>>>> 
>>>>> -- 
>>>>> 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.

Reply via email to