diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/base.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/ddl.py | 14 | ||||
-rw-r--r-- | lib/sqlalchemy/schema.py | 12 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/visitors.py | 4 | ||||
-rw-r--r-- | test/engine/test_bind.py | 28 | ||||
-rw-r--r-- | test/engine/test_ddlevents.py | 3 |
7 files changed, 30 insertions, 38 deletions
@@ -121,6 +121,9 @@ CHANGES to get_primary_keys() except returns a dict that includes the name of the constraint, for supported backends (PG so far). [ticket:1769] + + - Table.create() and Table.drop() no longer apply metadata- + level create/drop events. [ticket:1771] - ext - the compiler extension now allows @compiles decorators diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index d35796063..5068167c3 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1497,14 +1497,14 @@ class Engine(Connectable, log.Identified): self.pool = self.pool.recreate() def create(self, entity, connection=None, **kwargs): - """Create a table or index within this engine's database connection given a schema.Table object.""" + """Create a table or index within this engine's database connection given a schema object.""" from sqlalchemy.engine import ddl self._run_visitor(ddl.SchemaGenerator, entity, connection=connection, **kwargs) def drop(self, entity, connection=None, **kwargs): - """Drop a table or index within this engine's database connection given a schema.Table object.""" + """Drop a table or index within this engine's database connection given a schema object.""" from sqlalchemy.engine import ddl diff --git a/lib/sqlalchemy/engine/ddl.py b/lib/sqlalchemy/engine/ddl.py index ef10aa5ea..74205dbb0 100644 --- a/lib/sqlalchemy/engine/ddl.py +++ b/lib/sqlalchemy/engine/ddl.py @@ -39,12 +39,15 @@ class SchemaGenerator(DDLBase): listener('before-create', metadata, self.connection, tables=collection) for table in collection: - self.traverse_single(table) + self.traverse_single(table, create_ok=True) for listener in metadata.ddl_listeners['after-create']: listener('after-create', metadata, self.connection, tables=collection) - def visit_table(self, table): + def visit_table(self, table, create_ok=False): + if not create_ok and not self._can_create(table): + return + for listener in table.ddl_listeners['before-create']: listener('before-create', table, self.connection) @@ -92,7 +95,7 @@ class SchemaDropper(DDLBase): listener('before-drop', metadata, self.connection, tables=collection) for table in collection: - self.traverse_single(table) + self.traverse_single(table, drop_ok=True) for listener in metadata.ddl_listeners['after-drop']: listener('after-drop', metadata, self.connection, tables=collection) @@ -106,7 +109,10 @@ class SchemaDropper(DDLBase): def visit_index(self, index): self.connection.execute(schema.DropIndex(index)) - def visit_table(self, table): + def visit_table(self, table, drop_ok=False): + if not drop_ok and not self._can_drop(table): + return + for listener in table.ddl_listeners['before-drop']: listener('before-drop', table, self.connection) diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 0e03be686..4e4468a85 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -405,15 +405,23 @@ class Table(SchemaItem, expression.TableClause): """Issue a ``CREATE`` statement for this table. See also ``metadata.create_all()``. + """ - self.metadata.create_all(bind=bind, checkfirst=checkfirst, tables=[self]) + + if bind is None: + bind = _bind_or_error(self) + bind.create(self, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=False): """Issue a ``DROP`` statement for this table. See also ``metadata.drop_all()``. + """ - self.metadata.drop_all(bind=bind, checkfirst=checkfirst, tables=[self]) + if bind is None: + bind = _bind_or_error(self) + bind.drop(self, checkfirst=checkfirst) + def tometadata(self, metadata, schema=RETAIN_SCHEMA): """Return a copy of this ``Table`` associated with a different ``MetaData``.""" diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py index 799486c02..791e3b80c 100644 --- a/lib/sqlalchemy/sql/visitors.py +++ b/lib/sqlalchemy/sql/visitors.py @@ -70,11 +70,11 @@ class ClauseVisitor(object): __traverse_options__ = {} - def traverse_single(self, obj): + def traverse_single(self, obj, **kw): for v in self._visitor_iterator: meth = getattr(v, "visit_%s" % obj.__visit_name__, None) if meth: - return meth(obj) + return meth(obj, **kw) def iterate(self, obj): """traverse the given expression structure, returning an iterator of all elements.""" diff --git a/test/engine/test_bind.py b/test/engine/test_bind.py index 1122f1632..c958f6f4c 100644 --- a/test/engine/test_bind.py +++ b/test/engine/test_bind.py @@ -31,16 +31,14 @@ class BindTest(testing.TestBase): table.drop(*args[0], **args[1]) assert not table.exists(*args[0], **args[1]) - def test_create_drop_err(self): + def test_create_drop_err_metadata(self): metadata = MetaData() table = Table('test_table', metadata, Column('foo', Integer)) - + for meth in [ metadata.create_all, metadata.drop_all, - table.create, - table.drop, ]: try: meth() @@ -54,27 +52,7 @@ class BindTest(testing.TestBase): "against. Either execute with an explicit connection or " "assign the MetaData's .bind to enable implicit execution.") - for meth in [ - table.exists, - # future: - #table.create, - #table.drop, - ]: - try: - meth() - assert False - except exc.UnboundExecutionError, e: - eq_( - str(e), - "The Table 'test_table' " - "is not bound to an Engine or Connection. " - "Execution can not proceed without a database to execute " - "against. Either execute with an explicit connection or " - "assign this Table's .metadata.bind to enable implicit " - "execution.") - - @testing.future - def test_create_drop_err2(self): + def test_create_drop_err_table(self): metadata = MetaData() table = Table('test_table', metadata, Column('foo', Integer)) diff --git a/test/engine/test_ddlevents.py b/test/engine/test_ddlevents.py index 2e5817c01..06d293526 100644 --- a/test/engine/test_ddlevents.py +++ b/test/engine/test_ddlevents.py @@ -156,7 +156,6 @@ class DDLEventTest(TestBase): metadata.drop_all(bind) assert canary.state == 'after-create' - @testing.future def test_metadata_table_isolation(self): metadata, table, bind = self.metadata, self.table, self.bind @@ -166,8 +165,6 @@ class DDLEventTest(TestBase): metadata_canary = self.Canary(metadata, bind) metadata.ddl_listeners['before-create'].append(metadata_canary.before_create) - # currently, table.create() routes through the same execution - # path that metadata.create_all() does self.table.create(self.bind) assert metadata_canary.state == None |