]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bug whereby mapper couldn't initialize if a composite
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 4 Sep 2008 17:44:48 +0000 (17:44 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 4 Sep 2008 17:44:48 +0000 (17:44 +0000)
primary key referenced another table that was not defined
yet [ticket:1161]

CHANGES
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/sql/util.py
test/ext/declarative.py

diff --git a/CHANGES b/CHANGES
index 1f7151823e841af0cc58361e6c0b27b0ebd7b3b5..b395f6edd750f3c95a52820f1bac80f5e33ec485 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -112,6 +112,11 @@ CHANGES
       
     - The `echo_uow` flag on `Session` is deprecated, and unit-of-work
       logging is now application-level only, not per-session level.
+
+- declarative
+    - Fixed bug whereby mapper couldn't initialize if a composite
+      primary key referenced another table that was not defined
+      yet [ticket:1161]
       
 - schema
     - Added "sorted_tables" accessor to MetaData, which returns
index cfea61e26c4cf452747a99008ba6dd3b51acf40b..d6dbc26341e8ec7aff16f4cdabeff0188c7b9665 100644 (file)
@@ -545,11 +545,11 @@ class Mapper(object):
             # determine primary key from argument or mapped_table pks - reduce to the minimal set of columns
             if self.primary_key_argument:
                 primary_key = sqlutil.reduce_columns(
-                    self.mapped_table.corresponding_column(c)
-                    for c in self.primary_key_argument)
+                    [self.mapped_table.corresponding_column(c) for c in self.primary_key_argument], 
+                    ignore_nonexistent_tables=True)
             else:
                 primary_key = sqlutil.reduce_columns(
-                    self._pks_by_table[self.mapped_table])
+                    self._pks_by_table[self.mapped_table], ignore_nonexistent_tables=True)
 
             if len(primary_key) == 0:
                 raise sa_exc.ArgumentError("Mapper %s could not assemble any primary key columns for mapped table '%s'" % (self, self.mapped_table.description))
index e1636ccf90dde14d5483d560ce24848c4f5d36c9..d9c3ed89989a2603ad53ba489f4a43fb87fa3a21 100644 (file)
@@ -190,7 +190,7 @@ def splice_joins(left, right, stop_on=None):
 
     return ret
     
-def reduce_columns(columns, *clauses):
+def reduce_columns(columns, *clauses, **kw):
     """given a list of columns, return a 'reduced' set based on natural equivalents.
 
     the set is reduced to the smallest list of columns which have no natural
@@ -200,12 +200,17 @@ def reduce_columns(columns, *clauses):
     \*clauses is an optional list of join clauses which will be traversed
     to further identify columns that are "equivalent".
 
+    \**kw may specify 'ignore_nonexistent_tables' to ignore foreign keys
+    whose tables are not yet configured.
+    
     This function is primarily used to determine the most minimal "primary key"
     from a selectable, by reducing the set of primary key columns present
     in the the selectable to just those that are not repeated.
 
     """
 
+    ignore_nonexistent_tables = kw.pop('ignore_nonexistent_tables', False)
+    
     columns = util.OrderedSet(columns)
 
     omit = set()
@@ -214,7 +219,14 @@ def reduce_columns(columns, *clauses):
             for c in columns:
                 if c is col:
                     continue
-                if fk.column.shares_lineage(c):
+                try:
+                    fk_col = fk.column
+                except exc.NoReferencedTableError:
+                    if ignore_nonexistent_tables:
+                        continue
+                    else:
+                        raise
+                if fk_col.shares_lineage(c):
                     omit.add(col)
                     break
 
index 6b226cc9f7e563c4b800ca617273c1cb0e9f3002..3121f959fe77b63052ed7ba240d065422450a9ef 100644 (file)
@@ -679,6 +679,22 @@ class DeclarativeTest(testing.TestBase, testing.AssertsExecutionResults):
               Address(email='one'),
               Address(email='two')])])
 
+    def test_pk_with_fk_init(self):
+        class Bar(Base):
+            __tablename__ = 'bar'
+
+            id = sa.Column(sa.Integer, sa.ForeignKey("foo.id"), primary_key=True)
+            ex = sa.Column(sa.Integer, primary_key=True)
+
+        class Foo(Base):
+            __tablename__ = 'foo'
+
+            id = sa.Column(sa.Integer, primary_key=True)
+            bars = sa.orm.relation(Bar)
+        
+        assert Bar.__mapper__.primary_key[0] is Bar.__table__.c.id
+        assert Bar.__mapper__.primary_key[1] is Bar.__table__.c.ex
+        
     def test_single_inheritance(self):
         class Company(Base, ComparableEntity):
             __tablename__ = 'companies'