]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bug in :meth:`.Table.tometadata` method where the
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 29 Nov 2014 19:44:26 +0000 (14:44 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 29 Nov 2014 19:46:34 +0000 (14:46 -0500)
:class:`.CheckConstraint` associated with a :class:`.Boolean`
or :class:`.Enum` type object would be doubled in the target table.
The copy process now tracks the production of this constraint object
as local to a type object.
fixes #3260

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/sql/schema.py
lib/sqlalchemy/sql/sqltypes.py
test/sql/test_metadata.py

index 4a350370f06550a317c248ea05374a83876bf487..f2bd43a76b5c3b0e37f60617b87cba38fbbed809 100644 (file)
     series as well.  For changes that are specific to 1.0 with an emphasis
     on compatibility concerns, see :doc:`/changelog/migration_10`.
 
+    .. change::
+        :tags: bug, sql
+        :tickets: 3260
+
+        Fixed bug in :meth:`.Table.tometadata` method where the
+        :class:`.CheckConstraint` associated with a :class:`.Boolean`
+        or :class:`.Enum` type object would be doubled in the target table.
+        The copy process now tracks the production of this constraint object
+        as local to a type object.
+
     .. change::
         :tags: feature, orm
         :tickets: 3217
index 4093d7115b95c556212ccdbd963a208564f57fb2..b90f7fc5396e5338c28aff5210ce8fd84a0c7a01 100644 (file)
@@ -824,7 +824,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
                 table.append_constraint(
                     c.copy(schema=fk_constraint_schema, target_table=table))
 
-            else:
+            elif not c._type_bound:
                 table.append_constraint(
                     c.copy(schema=schema, target_table=table))
         for index in self.indexes:
@@ -1295,7 +1295,7 @@ class Column(SchemaItem, ColumnClause):
 
         # Constraint objects plus non-constraint-bound ForeignKey objects
         args = \
-            [c.copy(**kw) for c in self.constraints] + \
+            [c.copy(**kw) for c in self.constraints if not c._type_bound] + \
             [c.copy(**kw) for c in self.foreign_keys if not c.constraint]
 
         type_ = self.type
@@ -2254,7 +2254,7 @@ class Constraint(DialectKWArgs, SchemaItem):
     __visit_name__ = 'constraint'
 
     def __init__(self, name=None, deferrable=None, initially=None,
-                 _create_rule=None, info=None,
+                 _create_rule=None, info=None, _type_bound=False,
                  **dialect_kw):
         """Create a SQL constraint.
 
@@ -2304,6 +2304,7 @@ class Constraint(DialectKWArgs, SchemaItem):
         if info:
             self.info = info
         self._create_rule = _create_rule
+        self._type_bound = _type_bound
         util.set_creation_order(self)
         self._validate_dialect_kwargs(dialect_kw)
 
@@ -2420,7 +2421,7 @@ class CheckConstraint(Constraint):
 
     def __init__(self, sqltext, name=None, deferrable=None,
                  initially=None, table=None, info=None, _create_rule=None,
-                 _autoattach=True):
+                 _autoattach=True, _type_bound=False):
         """Construct a CHECK constraint.
 
         :param sqltext:
@@ -2450,7 +2451,9 @@ class CheckConstraint(Constraint):
         """
 
         super(CheckConstraint, self).\
-            __init__(name, deferrable, initially, _create_rule, info=info)
+            __init__(
+                name, deferrable, initially, _create_rule, info=info,
+                _type_bound=_type_bound)
         self.sqltext = _literal_as_text(sqltext, warn=False)
         if table is not None:
             self._set_parent_with_dispatch(table)
@@ -2485,7 +2488,8 @@ class CheckConstraint(Constraint):
                             deferrable=self.deferrable,
                             _create_rule=self._create_rule,
                             table=target_table,
-                            _autoattach=False)
+                            _autoattach=False,
+                            _type_bound=self._type_bound)
         return self._schema_item_copy(c)
 
 
index 2729bc83e1600190dafbd00601163a04e803f088..7bf2f337ce432dbc57e0c866f8a3166a325da227 100644 (file)
@@ -998,13 +998,11 @@ class SchemaType(SchemaEventTarget):
     def adapt(self, impltype, **kw):
         schema = kw.pop('schema', self.schema)
 
-        # don't associate with MetaData as the hosting type
+        # don't associate with self.metadata as the hosting type
         # is already associated with it, avoid creating event
         # listeners
-        metadata = kw.pop('metadata', None)
         return impltype(name=self.name,
                         schema=schema,
-                        metadata=metadata,
                         inherit_schema=self.inherit_schema,
                         **kw)
 
@@ -1165,7 +1163,8 @@ class Enum(String, SchemaType):
             type_coerce(column, self).in_(self.enums),
             name=_defer_name(self.name),
             _create_rule=util.portable_instancemethod(
-                self._should_create_constraint)
+                self._should_create_constraint),
+            _type_bound=True
         )
         assert e.table is table
 
@@ -1303,7 +1302,8 @@ class Boolean(TypeEngine, SchemaType):
             type_coerce(column, self).in_([0, 1]),
             name=_defer_name(self.name),
             _create_rule=util.portable_instancemethod(
-                self._should_create_constraint)
+                self._should_create_constraint),
+            _type_bound=True
         )
         assert e.table is table
 
index 3f24fd07dcb8d1717946d8ddb659bb8c6c726756..74044e3bbe31e49af8ec47a048599f56463e16d9 100644 (file)
@@ -1473,6 +1473,46 @@ class SchemaTypeTest(fixtures.TestBase):
 
         m1.create_all(testing.db)
 
+    def test_boolean_constraint_type_doesnt_double(self):
+        m1 = MetaData()
+
+        t1 = Table('x', m1, Column("flag", Boolean()))
+        eq_(
+            len([
+                c for c in t1.constraints
+                if isinstance(c, CheckConstraint)]),
+            1
+        )
+        m2 = MetaData()
+        t2 = t1.tometadata(m2)
+
+        eq_(
+            len([
+                c for c in t2.constraints
+                if isinstance(c, CheckConstraint)]),
+            1
+        )
+
+    def test_enum_constraint_type_doesnt_double(self):
+        m1 = MetaData()
+
+        t1 = Table('x', m1, Column("flag", Enum('a', 'b', 'c')))
+        eq_(
+            len([
+                c for c in t1.constraints
+                if isinstance(c, CheckConstraint)]),
+            1
+        )
+        m2 = MetaData()
+        t2 = t1.tometadata(m2)
+
+        eq_(
+            len([
+                c for c in t2.constraints
+                if isinstance(c, CheckConstraint)]),
+            1
+        )
+
 
 class SchemaTest(fixtures.TestBase, AssertsCompiledSQL):