From aadb45612034d00874c7be405d3c78403f883c9d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 28 Jun 2009 20:31:01 +0000 Subject: [PATCH] Column calls _set_parent() on child items within the constructor, so that the Column is easily navigable before table attachment. helps migrate. --- lib/sqlalchemy/schema.py | 91 +++++++++++++++++++------------- test/orm/test_eager_relations.py | 1 + test/sql/test_constraints.py | 6 +-- 3 files changed, 57 insertions(+), 41 deletions(-) diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 8f6516c631..d85f36b39e 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -407,7 +407,7 @@ class Column(SchemaItem, expression.ColumnClause): """Represents a column in a database table.""" __visit_name__ = 'column' - + def __init__(self, *args, **kwargs): """ Construct a new ``Column`` object. @@ -577,7 +577,6 @@ class Column(SchemaItem, expression.ColumnClause): type_ = args.pop(0) super(Column, self).__init__(name, None, type_) - self._pending_args = args self.key = kwargs.pop('key', name) self.primary_key = kwargs.pop('primary_key', False) self.nullable = kwargs.pop('nullable', not self.primary_key) @@ -591,6 +590,28 @@ class Column(SchemaItem, expression.ColumnClause): self.autoincrement = kwargs.pop('autoincrement', True) self.constraints = set() self.foreign_keys = util.OrderedSet() + self._table_events = set() + + if self.default is not None: + if isinstance(self.default, ColumnDefault): + args.append(self.default) + else: + args.append(ColumnDefault(self.default)) + if self.server_default is not None: + if isinstance(self.server_default, FetchedValue): + args.append(self.server_default) + else: + args.append(DefaultClause(self.server_default)) + if self.onupdate is not None: + args.append(ColumnDefault(self.onupdate, for_update=True)) + if self.server_onupdate is not None: + if isinstance(self.server_onupdate, FetchedValue): + args.append(self.server_default) + else: + args.append(DefaultClause(self.server_onupdate, + for_update=True)) + self._init_items(*args) + util.set_creation_order(self) if kwargs.get('info'): @@ -688,28 +709,16 @@ class Column(SchemaItem, expression.ColumnClause): "external to the Table.") table.append_constraint(UniqueConstraint(self.key)) - toinit = list(self._pending_args) - if self.default is not None: - if isinstance(self.default, ColumnDefault): - toinit.append(self.default) - else: - toinit.append(ColumnDefault(self.default)) - if self.server_default is not None: - if isinstance(self.server_default, FetchedValue): - toinit.append(self.server_default) - else: - toinit.append(DefaultClause(self.server_default)) - if self.onupdate is not None: - toinit.append(ColumnDefault(self.onupdate, for_update=True)) - if self.server_onupdate is not None: - if isinstance(self.server_onupdate, FetchedValue): - toinit.append(self.server_default) - else: - toinit.append(DefaultClause(self.server_onupdate, - for_update=True)) - self._init_items(*toinit) - del self._pending_args - + for fn in self._table_events: + fn(table) + del self._table_events + + def _on_table_attach(self, fn): + if self.table: + fn(self.table) + else: + self._table_events.add(fn) + def copy(self, **kw): """Create a copy of this ``Column``, unitialized. @@ -732,14 +741,15 @@ class Column(SchemaItem, expression.ColumnClause): """Create a *proxy* for this column. This is a copy of this ``Column`` referenced by a different parent - (such as an alias or select statement). - + (such as an alias or select statement). The column should + be used only in select scenarios, as its full DDL/default + information is not transferred. + """ fk = [ForeignKey(f.column) for f in self.foreign_keys] c = Column( name or self.name, self.type, - self.default, key = name or self.key, primary_key = self.primary_key, nullable = self.nullable, @@ -749,8 +759,9 @@ class Column(SchemaItem, expression.ColumnClause): selectable.columns.add(c) if self.primary_key: selectable.primary_key.add(c) - for f in fk: - c._init_items(f) + for fn in c._table_events: + fn(selectable) + del c._table_events return c def get_children(self, schema_visitor=False, **kwargs): @@ -959,18 +970,20 @@ class ForeignKey(SchemaItem): raise exc.InvalidRequestError("This ForeignKey already has a parent !") self.parent = column - if self.constraint is None and isinstance(self.parent.table, Table): + self.parent.foreign_keys.add(self) + self.parent._on_table_attach(self._set_table) + + def _set_table(self, table): + if self.constraint is None and isinstance(table, Table): self.constraint = ForeignKeyConstraint( [], [], use_alter=self.use_alter, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, deferrable=self.deferrable, initially=self.initially, ) - self.constraint._elements[column] = self - self.constraint._set_parent(self.parent.table) - - self.parent.foreign_keys.add(self) - self.parent.table.foreign_keys.add(self) - + self.constraint._elements[self.parent] = self + self.constraint._set_parent(table) + table.foreign_keys.add(self) + class DefaultGenerator(SchemaItem): """Base class for column *default* values.""" @@ -1086,7 +1099,11 @@ class Sequence(DefaultGenerator): def _set_parent(self, column): super(Sequence, self)._set_parent(column) column.sequence = self - self.metadata = column.table.metadata + + column._on_table_attach(self._set_table) + + def _set_table(self, table): + self.metadata = table.metadata @property def bind(self): diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py index e853a85c1f..3eabe2db72 100644 --- a/test/orm/test_eager_relations.py +++ b/test/orm/test_eager_relations.py @@ -659,6 +659,7 @@ class EagerTest(_fixtures.FixtureTest): 'orders':relation(Order, backref='user', lazy=False), 'max_order':relation(mapper(Order, max_orders, non_primary=True), lazy=False, uselist=False) }) + q = create_session().query(User) def go(): diff --git a/test/sql/test_constraints.py b/test/sql/test_constraints.py index 2dbf181176..6188357c35 100644 --- a/test/sql/test_constraints.py +++ b/test/sql/test_constraints.py @@ -37,10 +37,8 @@ class ConstraintTest(TestBase, AssertsExecutionResults, AssertsCompiledSQL): def test_double_fk_usage_raises(self): f = ForeignKey('b.id') - assert_raises(exc.InvalidRequestError, Table, "a", metadata, - Column('x', Integer, f), - Column('y', Integer, f) - ) + Column('x', Integer, f) + assert_raises(exc.InvalidRequestError, Column, "y", Integer, f) def test_circular_constraint(self): a = Table("a", metadata, -- 2.47.3