Sounds far more complicated than something I'd want to take on.
Thanks for your thoughts and the detailed response.

Ben

On Thu, Jun 2, 2011 at 6:28 PM, Michael Bayer <mike...@zzzcomputing.com> wrote:
>
> On Jun 2, 2011, at 8:25 PM, Ben Chess wrote:
>
>> On Thu, Jun 2, 2011 at 5:18 PM, Michael Bayer <mike...@zzzcomputing.com> 
>> wrote:
>>>
>>> On Jun 2, 2011, at 8:11 PM, Ben Chess wrote:
>>>
>>>> I'm not intending for the contents of the BLOB to be readable to
>>>> MySQL.  It would only be cracked open and read from within Python.
>>>> Meaning Python only knows what the key actually is.  So yeah, I
>>>> understand the caveats of this approach.  I merely want to provide a
>>>> mechanism to, as a second & separate SELECT query, load the relationed
>>>> instance and be able to access it from the child python instance.
>>>>
>>>> Hopefully that clears some things up.
>>>
>>> How do you want to identify what row contains the target key ?   Is the 
>>> comparison on the SQL side or the Python side ?
>>
>> In Python.  Below is an example of what I have.
>>
>> class Account:
>>  data = Column(JSONType)
>>
>>  @property
>>  def salesperson(self):
>>    session = orm.session.object_session(self)
>>    return session.query(Salesperson, id=self.data['salesperson_id']).one()
>
> OK that comparison, assuming you mean to have a "filter()" in there, is on 
> the SQL side.  The extraction of the comparison value from the JSON is python 
> side.
>
> relationship() really has no way to deal with load or persist operations that 
> aren't about columns in the two tables being compared.   Also, an eager load, 
> at least as far as being able to load Parent and related Child objects (I'm 
> using Parent/Child instead of Account/Salesperson here) with less than N+1 
> queries is not possible here, since that requires a set of rows representing 
> parents be compared to a set of rows representing children on the SQL side 
> and that's not an option.   The relationship also can't really do too much 
> with SQL criteria, at least not query.join(), so it would be limited at best 
> with class level behavior.
>
> So what you would get from a hypothetical relationship are:
>
> 1. the attribute is managed, such that it loads when non-populated, remains 
> in __dict__ for subsequent returns, gets expired when the object is expired, 
> after a commit(), etc.
> 2. if you assign to the attribute, "cascade" can establish that the child 
> object or objects are brought into the session
> 3. merge() will merge it in
> 4. potentially the unit of work could fire off rules to establish necessary 
> state on the parent or child based on the object association as well as its 
> history
>
> There is a rough outline of a new extension here, where the end user could 
> plug in functions to establish "how am I loading the object", "I'm flushing, 
> what needs to be populated", "here's my SQL comparison logic", but this would 
> be a big job.  It would be daunting for new users, it would have a complex 
> usage contract.  A rudimentary version could probably happen quickly, but 
> when people start using it for real, the number of edge cases is huge.   
> Could be a nice feature, but would be an enormous maintenance job for many 
> months, or alternatively a little used and weakly supported feature.   
> Attached is a sketch of part of it, does a little bit of the above.    You're 
> free to use it but it uses more of the internals than I think you'd want to 
> (these are internals that aren't guaranteed to stay the same).
>
> But beyond all the work it would require for testing and maintenance, how 
> useful would it actually be, and how confusing would it be that you can kind 
> of build an attribute like this on your own outside of SQLAlchemy, as you've 
> done ?
>
> If all you need is so that hitting salesperson doesn't do the load every 
> time, @memoized_property is easy for that.   Another example for that is 
> attached, it also expires itself when the object is expired.   Doesn't do as 
> much.  It's not clear how much of relationship() you'd really need.
>
> Of course if you could find a way to copy this one aspect of your JSON 
> structure to a plain foreign key attribute (and there's many ways to fire off 
> an event like that), all of this goes away and you get SQL-level eager 
> loading and joins and all that.
>
>
>
>
>
>
>
>
>>
>>
>>>>
>>>> On Thu, Jun 2, 2011 at 4:10 PM, Michael Bayer <mike...@zzzcomputing.com> 
>>>> wrote:
>>>>> Using a BLOB as a key is a really bad idea and wont work on all backends, 
>>>>> but other than the database-level limitations inherent, SQLAlchemy will 
>>>>> let you set up whatever column you'd like to use as the key just fine 
>>>>> within a relationship().     Guessing what the problem might be.  Foreign 
>>>>> key ?  If you rely upon your table metadata to emit CREATE TABLE 
>>>>> statements, you can forego using ForeignKey with your table metadata and 
>>>>> configure the foreign key data on the relationship itself using 
>>>>> "foreign_keys=[table.c.my_referencing_blob_column], 
>>>>> primary_join=table.c.my_key_blob_column==table.c.my_referencing_blob_column".
>>>>>
>>>>> As far as your eager load, both joined eager loading and subquery eager 
>>>>> loading rely on being able to JOIN to the target so if your backend is 
>>>>> not letting the JOIN part happen, I'm not sure exactly what SQL you'd 
>>>>> like to emit.    If you'd like the "lazy" loader to just fire off 
>>>>> immediately, you can use the "immediate" style of loader - 
>>>>> lazy="immediate" or immediateload() as an option - but that won't save 
>>>>> you on SELECT statements.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Jun 2, 2011, at 6:15 PM, Ben Chess wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I want to establish a relationship with an object whose key is defined
>>>>>> inside a JSON BLOB column in the child.  Naively, I know I can do this
>>>>>> via a regular python @property that uses object_session() to then do a
>>>>>> query() using the id from inside the blob.  Is there a better way that
>>>>>> lets sqlalchemy manage the relationship and caching?
>>>>>>
>>>>>> Also, I'd like to be able to sometimes eagerly load this
>>>>>> relationship.  Obviously I can't do in with a JOIN of the original
>>>>>> query, but is there some way to define the relationship, perhaps using
>>>>>> a column_property, to be able to undefer()?
>>>>>>
>>>>>> Thanks,
>>>>>> Ben Chess
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google 
>>>>>> Groups "sqlalchemy" group.
>>>>>> To post to this group, send email to sqlalchemy@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 sqlalchemy@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 sqlalchemy@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 sqlalchemy@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 sqlalchemy@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 sqlalchemy@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 sqlalchemy@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