From fbd81de0ebdbc54b0df6ba08cc8309e1328888fa Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 11 Dec 2012 16:31:41 -0500 Subject: Fixed a regression caused by :ticket:`2410` whereby a :class:`.CheckConstraint` would apply itself back to the original table during a :meth:`.Table.tometadata` operation, as it would parse the SQL expression for a parent table. The operation now copies the given expression to correspond to the new table. [ticket:2633] --- lib/sqlalchemy/schema.py | 31 ++++++++++++++++++++++--------- lib/sqlalchemy/util/langhelpers.py | 10 ++++++---- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'lib/sqlalchemy') diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 553936299..84d133dad 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -659,12 +659,13 @@ class Table(SchemaItem, expression.TableClause): args = [] for c in self.columns: args.append(c.copy(schema=schema)) - for c in self.constraints: - args.append(c.copy(schema=schema)) table = Table( self.name, metadata, schema=schema, *args, **self.kwargs ) + for c in self.constraints: + table.append_constraint(c.copy(schema=schema, target_table=table)) + for index in self.indexes: # skip indexes that would be generated # by the 'index' flag on Column @@ -2077,7 +2078,8 @@ class CheckConstraint(Constraint): """ def __init__(self, sqltext, name=None, deferrable=None, - initially=None, table=None, _create_rule=None): + initially=None, table=None, _create_rule=None, + _autoattach=True): """Construct a CHECK constraint. :param sqltext: @@ -2102,7 +2104,7 @@ class CheckConstraint(Constraint): self.sqltext = expression._literal_as_text(sqltext) if table is not None: self._set_parent_with_dispatch(table) - else: + elif _autoattach: cols = sqlutil.find_columns(self.sqltext) tables = set([c.table for c in cols if c.table is not None]) @@ -2117,12 +2119,23 @@ class CheckConstraint(Constraint): return "column_check_constraint" __visit_name__ = property(__visit_name__) - def copy(self, **kw): - c = CheckConstraint(self.sqltext, + def copy(self, target_table=None, **kw): + if target_table is not None: + def replace(col): + if self.table.c.contains_column(col): + return target_table.c[col.key] + else: + return None + sqltext = visitors.replacement_traverse(self.sqltext, {}, replace) + else: + sqltext = self.sqltext + c = CheckConstraint(sqltext, name=self.name, initially=self.initially, deferrable=self.deferrable, - _create_rule=self._create_rule) + _create_rule=self._create_rule, + table=target_table, + _autoattach=False) c.dispatch._update(self.dispatch) return c @@ -2265,10 +2278,10 @@ class ForeignKeyConstraint(Constraint): event.listen(table.metadata, "before_drop", DropConstraint(self, on=supports_alter)) - def copy(self, **kw): + def copy(self, schema=None, **kw): fkc = ForeignKeyConstraint( [x.parent.name for x in self._elements.values()], - [x._get_colspec(**kw) for x in self._elements.values()], + [x._get_colspec(schema=schema) for x in self._elements.values()], name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index f43cb0b3a..203b39c37 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -303,6 +303,8 @@ def generic_repr(obj, additional_kw=(), to_inspect=None): if to_inspect is None: to_inspect = obj + missing = object() + def genargs(): try: (args, vargs, vkw, defaults) = \ @@ -322,16 +324,16 @@ def generic_repr(obj, additional_kw=(), to_inspect=None): yield repr(getattr(obj, arg, None)) for (arg, defval) in zip(args[-default_len:], defaults): try: - val = getattr(obj, arg, None) - if val != defval: + val = getattr(obj, arg, missing) + if val is not missing and val != defval: yield '%s=%r' % (arg, val) except: pass if additional_kw: for arg, defval in additional_kw: try: - val = getattr(obj, arg, None) - if val != defval: + val = getattr(obj, arg, missing) + if val is not missing and val != defval: yield '%s=%r' % (arg, val) except: pass -- cgit v1.2.1