I'm getting the following error with SQLAlchemy 0.7.3:
sqlalchemy.exc.ArgumentError: Could not determine join condition between parent/child tables on relationship Survey.bossSpectrumHeaders. Specify a 'primaryjoin' expression. If 'secondary' is present, 'secondaryjoin' is needed as well.
I am relating two tables named "Survey" and "BOSSSpectrumHeader". The former is in a schema called "platedb" and the latter in another schema called "boss". The latter table has numerous foreign keys from the platedb schema, but and each fail if I comment out the previous one. The search path is "platedb, shared, boss, photofield, twomass, public". The python code is:
class BOSSSpectrumHeader(Base):
__tablename__ = 'spectrum_header'
__table_args__ = {'autoload' : True, 'schema' : 'boss', 'extend_existing' : True}
class Survey(Base):
__tablename__ = 'survey'
__table_args__ = {'autoload' : True, 'schema' : 'platedb'}
Survey.bossSpectrumHeaders = relationship(BOSSSpectrumHeader, backref="survey")
Finally, the SQL definitions of the tables are pasted below. Is there something I am missing? Why is the foreign key not being retrieved via reflection? Virtually everything else (including cross-schema relationships) is working fine.
Thanks for any help!
Cheers,
Demitri
---
CREATE TABLE boss.spectrum_header
(
pk integer NOT NULL DEFAULT nextval('spectrum_header_pk_seq'::regclass),
...
survey_pk integer NOT NULL,
CONSTRAINT boss_spectrum_header_pk PRIMARY KEY (pk ),
CONSTRAINT survey_fk FOREIGN KEY (survey_pk)
REFERENCES survey (pk) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT
)
CREATE TABLE survey
(
pk serial NOT NULL,
label text,
CONSTRAINT survey_pk PRIMARY KEY (pk ),
CONSTRAINT survey_label_uniq UNIQUE (label )
)
> Hi,
>
> I'm getting the following error with SQLAlchemy 0.7.3:
>
> sqlalchemy.exc.ArgumentError: Could not determine join condition between parent/child tables on relationship Survey.bossSpectrumHeaders. Specify a 'primaryjoin' expression. If 'secondary' is present, 'secondaryjoin' is needed as well.
>
> I am relating two tables named "Survey" and "BOSSSpectrumHeader". The former is in a schema called "platedb" and the latter in another schema called "boss". The latter table has numerous foreign keys from the platedb schema, but and each fail if I comment out the previous one. The search path is "platedb, shared, boss, photofield, twomass, public". The python code is:
two things I notice, first why using "extend_existing" - suggests theres more going on here. Also are you certain the foreign key from boss.spectrum_header points to the "platedb.schema" table and not another "schema" table elsewhere ? Yet another thing, when you reflect the foreign key from spectrum_header, it may not be coming back with "platedb" as the schema since you appear to be referring to the remote table using the implicit search path. SQLAlchemy may not be matching that up like you expect. There was an issue regarding this which was fixed in 0.7.3, another user relying upon a long search path. Do you get different results using 0.7.2 ? can you try defining your foreign key constraints in PG consistently with regards to how you're using schemas in your model ? (i.e. either the FK is to platedb.schema in PG, or remove the "platedb" schema from Survey).
> --
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> To post to this group, send email to sqlal...@googlegroups.com.
> To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>
Thanks Mike for the comments. Before I answer the questions you asked, I want to note I found a workaround without making any changes to the database-- I just reversed the tables in the definition. At first I was using:
Survey.bossSpectrumHeaders = relationship(BOSSSpectrumHeader, backref="survey")
Changing this to the following worked:
BOSSSpectrumHeader.survey = relationship(Survey, backref="bossSpectrumHeaders")
I'm not really sure how to interpret that.
On Nov 3, 2011, at 6:25 PM, Michael Bayer wrote:
> two things I notice, first why using "extend_existing" - suggests theres more going on here.
I'm not wholly sure why that is in place; my colleague wrote that part.
> Also are you certain the foreign key from boss.spectrum_header points to the "platedb.schema" table and not another "schema" table elsewhere ?
Yes, that table name is unique across all schemas.
> Yet another thing, when you reflect the foreign key from spectrum_header, it may not be coming back with "platedb" as the schema since you appear to be referring to the remote table using the implicit search path. SQLAlchemy may not be matching that up like you expect. There was an issue regarding this which was fixed in 0.7.3, another user relying upon a long search path.
I do have a long search path.
> Do you get different results using 0.7.2 ?
No, the first thing I did when I got this error was upgrade to 0.7.3.
> can you try defining your foreign key constraints in PG consistently with regards to how you're using schemas in your model ? (i.e. either the FK is to platedb.schema in PG, or remove the "platedb" schema from Survey).
I was reading the descriptions from PGAdmin3 - apparently they drop the schema in the display when the table is on the search path. There's nothing that I can do to further put the table in the schema, as it were.
I hope that knowing that reversing the order works helps to point to the problem...?
Cheers,
Demitri
I think the important thing here is that the table definition on the Python side needs to represent the table in the same way that the foreign key def will represent it from PG.
It's based on this fact:
> I was reading the descriptions from PGAdmin3 - apparently they drop the schema in the display when the table is on the search path. There's nothing that I can do to further put the table in the schema, as it were.
So SQLA does this:
1. reflect boss.spectrum_header
2. see that boss.spectrum_header has a foreign key - to a table called "survey". No schema is given for this FK def. So SQLAlchemy creates a new table called "survey" in the metadata collection. The schema is "None".
3. SQLAlchemy then reflects "survey", all its columns. PG's liberal search path allows this to work without issue.
4. The application then goes to reflect what is, from SQLAlchemy's perspective, an entirely different table called platedb.survey. Populates that table with things too.
5. The MetaData now has three tables: boss.spectrum_header, platedb.survey, survey. Errors ensue since boss.spectrum_header points to "survey" and not "platedb.survey".
Solutions:
1. set the search path to be only "public" for the application's connection. Use explicit schema names for all constructs outside of "public". A connection event that emits "SET search_path TO public" on each new connection will achieve this without affecting the database outside of the app.
2. Leave the liberal search path in place. Remove the usage of "schema" within the SQLAlchemy application and let PG's liberal search path find things.