summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-04-16 13:08:45 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-04-16 13:08:45 -0400
commit23f8c6c241a457d88bcb470e37a5d23926195290 (patch)
treed8c7c75f464fdcd16cea9cf1d4fe33308dbd4b54
parenta4032d2929d82af81379893c3d2037ea253e929e (diff)
downloadsqlalchemy-23f8c6c241a457d88bcb470e37a5d23926195290.tar.gz
- Table.create() and Table.drop() no longer apply metadata-
level create/drop events. [ticket:1771]
-rw-r--r--CHANGES3
-rw-r--r--lib/sqlalchemy/engine/base.py4
-rw-r--r--lib/sqlalchemy/engine/ddl.py14
-rw-r--r--lib/sqlalchemy/schema.py12
-rw-r--r--lib/sqlalchemy/sql/visitors.py4
-rw-r--r--test/engine/test_bind.py28
-rw-r--r--test/engine/test_ddlevents.py3
7 files changed, 30 insertions, 38 deletions
diff --git a/CHANGES b/CHANGES
index e997eb56c..c11fa3431 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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