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
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:
# 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
__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.
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)
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:
"""
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)
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)
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)
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
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
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):