Okay, that's fair. I figured it was a bit pathological, even though
it's a real-world use case. :)

Sorry I didn't find #1401 in my searches. Wrong keywords!

I'll see if I can find some time to write up a sqla test case out of
my repro script. Too bad my netbook seems dead set on corrupting my
flash media. :(

Thanks for the prompt response!

On Fri, May 6, 2011 at 11:55 AM, Michael Bayer <mike...@zzzcomputing.com> wrote:
> OK this is actually a classic issue, for which no solution has been built 
> yet.   Mostly because its an incredibly obscure case - there's a way to do it 
> in the internals but its a bit of a killer.
>
> we get the relationship's local side:
>
> (Pdb) self.local_side
> OrderedSet([Column('accountid', Integer(), ForeignKey('folder.accountid'), 
> table=<folder>, primary_key=True, nullable=False), Column('folderid', 
> Integer(), table=<folder>, primary_key=True, nullable=False)])
>
> we get the relationship's remote side:
>
> (Pdb) self.remote_side
> OrderedSet([Column('accountid', Integer(), ForeignKey('folder.accountid'), 
> table=<folder>, primary_key=True, nullable=False), Column('parent', 
> Integer(), ForeignKey('folder.folderid'), table=<folder>, nullable=False)])
>
> and the primaryjoin:
>
> (Pdb) primaryjoin.__str__()
> 'folder.accountid = folder.accountid AND folder.folderid = folder.parent'
>
> we tell ClauseAdapter, "change all the columns in the "folder" table, which 
> are not in the "local side", to come from the alias "folder_1"".
>
> when we chain this along several joins, we also have to say:
>
> "change all the columns in the "folder" table, which are not in the "remote 
> side", to come from the alias "folder_1"".
>
> the solution has to involve adding annotations to just one side of 
> "folderid=folderid", then enhancing ClauseAdapter to be able to take cues 
> from callables that look at annotations, instead of just presence in a set.
>
> so the answer right now is that we don't have this one case covered.   Its 
> ticket 1401 which is two years old, I've added some thoughts there.
>
> the two workarounds are to use joined load with contains_eager(), or the 
> hand-rolled subqueryload recipe at 
> http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DisjointEagerLoading .
>
>
> On May 6, 2011, at 11:15 AM, Taavi Burns wrote:
>
>> We have a multi-tenant database that includes a heirarchical layout.
>> We tried to apply subqueryloads across the board, but tests fail in
>> this one case.
>>
>> class Folder(Base):
>>    __tablename__ = 'folder'
>>    __table_args__ = (
>>        ForeignKeyConstraint(['accountid', 'parent'],
>> ['folder.accountid', 'folder.folderid']),
>>        {}
>>    )
>>    folderid = Column(Integer(), primary_key=True, nullable=False)
>>    accountid = Column(Integer(), primary_key=True,
>> autoincrement=False, nullable=False)
>>    parent = Column(Integer(), primary_key=False, nullable=False)
>>    name = Column(String(length=50), primary_key=False, nullable=False)
>>
>> Folder.child_folders = relation(
>>    Folder,
>>    backref=backref(
>>        'parent_folder',
>>        remote_side=[Folder.accountid, Folder.folderid]
>>    )
>> )
>>
>> We have multiple hierarchies with overlapping folderids, so we need
>> any walk to related resources to include that restriction. With normal
>> lazy loads, things work fine. With either eagerloads or subqueryloads,
>> we get too many rows back. It looks like the accountid part of the
>> foreign key doesn't get specified properly in the query:
>> "folder.accountid = folder.accountid".
>>
>> eagerload:
>> SELECT …
>> FROM folder LEFT OUTER JOIN folder AS folder_1 ON
>>    folder.accountid = folder.accountid --< lol, wut
>> AND folder.folderid = folder_1.parent
>> WHERE folder.folderid = ? AND folder.accountid = ?
>>
>> subqueryload:
>> SELECT …
>> FROM (SELECT … FROM folder WHERE folder.folderid = ? AND
>> folder.accountid = ?) AS anon_1
>> JOIN folder ON
>>    folder.accountid = folder.accountid --< lol, wut
>> AND anon_1.folder_folderid = folder.parent
>> ORDER BY anon_1.folder_accountid, anon_1.folder_folderid
>>
>> I've attached a full sqlite repro script and tried it against 0.6.4,
>> 0.6.8dev, and 0.7b5; same result every time.
>>
>> Thoughts? Thanks!
>>
>> --
>> taa
>> /*eof*/
>>
>> --
>> 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.
>>
>> <subquery_self_referential_foreign_key.py>
>
> --
> 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.
>
>



-- 
taa
/*eof*/

-- 
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