From 46b82976bf8651500de6e1c4ccf8c20d535a14e9 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 7 Mar 2007 18:05:39 +0000 Subject: [PATCH] - fixed use_alter flag on ForeignKeyConstraint [ticket:503] --- CHANGES | 3 ++- lib/sqlalchemy/exceptions.py | 4 ++++ lib/sqlalchemy/schema.py | 4 ++-- lib/sqlalchemy/topological.py | 6 +++--- test/sql/constraints.py | 24 ++++++++++++++++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index f263bcdd19..5501d4cefc 100644 --- a/CHANGES +++ b/CHANGES @@ -22,7 +22,8 @@ 'duplicate' columns from the resulting column clause that are known to be equivalent based on the join condition. this is of great usage when constructing subqueries of joins which Postgres complains about if - duplicate column names are present. + duplicate column names are present. + - fixed use_alter flag on ForeignKeyConstraint [ticket:503] - orm: - a full select() construct can be passed to query.select() (which worked anyway), but also query.selectfirst(), query.selectone() which diff --git a/lib/sqlalchemy/exceptions.py b/lib/sqlalchemy/exceptions.py index 08908cdb60..55c345bd72 100644 --- a/lib/sqlalchemy/exceptions.py +++ b/lib/sqlalchemy/exceptions.py @@ -49,6 +49,10 @@ class ConcurrentModificationError(SQLAlchemyError): pass +class CircularDependencyError(SQLAlchemyError): + """Raised by topological sorts when a circular dependency is detected""" + pass + class FlushError(SQLAlchemyError): """Raised when an invalid condition is detected upon a ``flush()``.""" pass diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index ae4a0b1626..52324e63ee 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -908,7 +908,7 @@ class ForeignKeyConstraint(Constraint): visitor.visit_foreign_key_constraint(self) def append_element(self, col, refcol): - fk = ForeignKey(refcol, constraint=self) + fk = ForeignKey(refcol, constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter) fk._set_parent(self.table.c[col]) self._append_fk(fk) @@ -917,7 +917,7 @@ class ForeignKeyConstraint(Constraint): self.elements.add(fk) def copy(self): - return ForeignKeyConstraint([x.parent.name for x in self.elements], [x._get_colspec() for x in self.elements], name=self.name, onupdate=self.onupdate, ondelete=self.ondelete) + return ForeignKeyConstraint([x.parent.name for x in self.elements], [x._get_colspec() for x in self.elements], name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter) class PrimaryKeyConstraint(Constraint): def __init__(self, *columns, **kwargs): diff --git a/lib/sqlalchemy/topological.py b/lib/sqlalchemy/topological.py index d9f68ac011..41fa9d9b2d 100644 --- a/lib/sqlalchemy/topological.py +++ b/lib/sqlalchemy/topological.py @@ -44,7 +44,7 @@ I realized this characteristic of the algorithm. import string, StringIO from sqlalchemy import util -from sqlalchemy.exceptions import * +from sqlalchemy.exceptions import CircularDependencyError class _Node(object): """Represent each item in the sort. @@ -188,7 +188,7 @@ class QueueDependencySorter(object): n.cycles = util.Set([n]) continue else: - raise FlushError("Self-referential dependency detected " + repr(t)) + raise CircularDependencyError("Self-referential dependency detected " + repr(t)) childnode = nodes[t[1]] parentnode = nodes[t[0]] edges.add((parentnode, childnode)) @@ -222,7 +222,7 @@ class QueueDependencySorter(object): continue else: # long cycles not allowed - raise FlushError("Circular dependency detected " + repr(edges) + repr(queue)) + raise CircularDependencyError("Circular dependency detected " + repr(edges) + repr(queue)) node = queue.pop() if not hasattr(node, '_cyclical'): output.append(node) diff --git a/test/sql/constraints.py b/test/sql/constraints.py index 926022c82d..79ccee4da2 100644 --- a/test/sql/constraints.py +++ b/test/sql/constraints.py @@ -28,6 +28,30 @@ class ConstraintTest(testbase.AssertMixin): ) metadata.create_all() + def test_circular_constraint(self): + a = Table("a", metadata, + Column('id', Integer, primary_key=True), + Column('bid', Integer), + ForeignKeyConstraint(["bid"], ["b.id"], name="afk") + ) + b = Table("b", metadata, + Column('id', Integer, primary_key=True), + Column("aid", Integer), + ForeignKeyConstraint(["aid"], ["a.id"], use_alter=True, name="bfk") + ) + metadata.create_all() + + def test_circular_constraint_2(self): + a = Table("a", metadata, + Column('id', Integer, primary_key=True), + Column('bid', Integer, ForeignKey("b.id")), + ) + b = Table("b", metadata, + Column('id', Integer, primary_key=True), + Column("aid", Integer, ForeignKey("a.id", use_alter=True, name="bfk")), + ) + metadata.create_all() + @testbase.unsupported('mysql') def test_check_constraint(self): foo = Table('foo', metadata, -- 2.47.2