]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- added NoReferencedColumnError, common base class of NoReferenceError
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 21 Oct 2008 16:17:24 +0000 (16:17 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 21 Oct 2008 16:17:24 +0000 (16:17 +0000)
- relation() won't hide unrelated ForeignKey errors inside of
the "please specify primaryjoin" message when determining
join condition.

CHANGES
lib/sqlalchemy/exc.py
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/schema.py
test/orm/relationships.py

diff --git a/CHANGES b/CHANGES
index 12e14b7f13a9f29c66f72936d73ad7e4834f4f15..afc5209db0399a09d73c5d3b218150c01cec5a46 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -17,7 +17,11 @@ CHANGES
     - Improved weakref identity map memory management to no longer 
       require mutexing, resurrects garbage collected instance
       on a lazy basis for an InstanceState with pending changes.
-      
+
+    - relation() won't hide unrelated ForeignKey errors inside of
+      the "please specify primaryjoin" message when determining
+      join condition.
+
 - sql
     - Further simplified SELECT compilation and its relationship
       to result row processing.
index 96c2e4177a4694ac93c7fe16bcbf9e90e5ae071a..f82c632f677aa89f89a8eabc908181a2f06a09ef 100644 (file)
@@ -63,9 +63,15 @@ class InvalidRequestError(SQLAlchemyError):
 class NoSuchColumnError(KeyError, InvalidRequestError):
     """A nonexistent column is requested from a ``RowProxy``."""
 
-class NoReferencedTableError(InvalidRequestError):
+class NoReferenceError(InvalidRequestError):
+    """Raised by ``ForeignKey`` to indicate a reference cannot be resolved."""
+    
+class NoReferencedTableError(NoReferenceError):
     """Raised by ``ForeignKey`` when the referred ``Table`` cannot be located."""
 
+class NoReferencedColumnError(NoReferenceError):
+    """Raised by ``ForeignKey`` when the referred ``Column`` cannot be located."""
+
 class NoSuchTableError(InvalidRequestError):
     """Table does not exist or is not visible to a connection."""
 
index 40bca8a119194f3adbf4b5fa6cca07e3875e05e9..473c71f7ede082f4ad3019c7dd1a3d057a95a13f 100644 (file)
@@ -13,7 +13,7 @@ attributes.
 
 from sqlalchemy import sql, util, log
 import sqlalchemy.exceptions as sa_exc
-from sqlalchemy.sql.util import ClauseAdapter, criterion_as_pairs
+from sqlalchemy.sql.util import ClauseAdapter, criterion_as_pairs, join_condition
 from sqlalchemy.sql import operators, expression
 from sqlalchemy.orm import (
     attributes, dependency, mapper, object_mapper, strategies,
@@ -581,19 +581,19 @@ class PropertyLoader(StrategizedProperty):
             # found will try the more general mapped table, which in the case of inheritance
             # is a join.
             try:
-                return sql.join(mapper.local_table, table)
+                return join_condition(mapper.local_table, table)
             except sa_exc.ArgumentError, e:
-                return sql.join(mapper.mapped_table, table)
+                return join_condition(mapper.mapped_table, table)
 
         try:
             if self.secondary is not None:
                 if self.secondaryjoin is None:
-                    self.secondaryjoin = _search_for_join(self.mapper, self.secondary).onclause
+                    self.secondaryjoin = _search_for_join(self.mapper, self.secondary)
                 if self.primaryjoin is None:
-                    self.primaryjoin = _search_for_join(self.parent, self.secondary).onclause
+                    self.primaryjoin = _search_for_join(self.parent, self.secondary)
             else:
                 if self.primaryjoin is None:
-                    self.primaryjoin = _search_for_join(self.parent, self.target).onclause
+                    self.primaryjoin = _search_for_join(self.parent, self.target)
         except sa_exc.ArgumentError, e:
             raise sa_exc.ArgumentError("Could not determine join condition between "
                         "parent/child tables on relation %s.  "
index 334c277b45d919ec5fdd567fe86e4725ea5b8702..567b1d43ae4ba9e7f2e911c2b237cf44a0da755d 100644 (file)
@@ -856,7 +856,7 @@ class ForeignKey(SchemaItem):
                     else:
                         self._column = table.c[colname]
                 except KeyError, e:
-                    raise exc.ArgumentError(
+                    raise exc.NoReferencedColumnError(
                         "Could not create ForeignKey '%s' on table '%s': "
                         "table '%s' has no column named '%s'" % (
                         self._colspec, parenttable.name, table.name, str(e)))
index 037df35fb21e91156a35b14246e815ebca3b73c0..2989fcda90fa4a1981e0ee79121cb8817d41e4d5 100644 (file)
@@ -1,8 +1,8 @@
 import testenv; testenv.configure_for_tests()
 import datetime
 from testlib import sa, testing
-from testlib.sa import Table, Column, Integer, String, ForeignKey
-from testlib.sa.orm import mapper, relation, backref, create_session
+from testlib.sa import Table, Column, Integer, String, ForeignKey, MetaData
+from testlib.sa.orm import mapper, relation, backref, create_session, compile_mappers, clear_mappers
 from testlib.testing import eq_, startswith_
 from orm import _base
 
@@ -649,6 +649,60 @@ class RelationTest6(_base.MappedTest):
             sess.query(TagInstance).order_by(TagInstance.data).all(), 
             [TagInstance(data='iplc_case'), TagInstance(data='not_iplc_case')]
         )
+
+
+class JoinConditionErrorTest(testing.TestBase):
+    def test_fk_error_raised(self):
+        m = MetaData()
+        t1 = Table('t1', m, 
+            Column('id', Integer, primary_key=True),
+            Column('foo_id', Integer, ForeignKey('t2.nonexistent_id')),
+        )
+        t2 = Table('t2', m,
+            Column('id', Integer, primary_key=True),
+            )
+
+        t3 = Table('t3', m,
+            Column('id', Integer, primary_key=True),
+            Column('t1id', Integer, ForeignKey('t1.id'))
+        )
+        
+        class C1(object):
+            pass
+        class C2(object):
+            pass
+        
+        mapper(C1, t1, properties={'c2':relation(C2)})
+        mapper(C2, t3)
+        
+        self.assertRaises(sa.exc.NoReferencedColumnError, compile_mappers)
+
+    def test_join_error_raised(self):
+        m = MetaData()
+        t1 = Table('t1', m, 
+            Column('id', Integer, primary_key=True),
+        )
+        t2 = Table('t2', m,
+            Column('id', Integer, primary_key=True),
+            )
+
+        t3 = Table('t3', m,
+            Column('id', Integer, primary_key=True),
+            Column('t1id', Integer)
+        )
+
+        class C1(object):
+            pass
+        class C2(object):
+            pass
+
+        mapper(C1, t1, properties={'c2':relation(C2)})
+        mapper(C2, t3)
+
+        self.assertRaises(sa.exc.ArgumentError, compile_mappers)
+    
+    def tearDown(self):
+        clear_mappers()    
         
 class TypeMatchTest(_base.MappedTest):
     """test errors raised when trying to add items whose type is not handled by a relation"""