summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/ddl.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql/ddl.py')
-rw-r--r--lib/sqlalchemy/sql/ddl.py136
1 files changed, 89 insertions, 47 deletions
diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py
index 7a1c7fef6..48f27b8b8 100644
--- a/lib/sqlalchemy/sql/ddl.py
+++ b/lib/sqlalchemy/sql/ddl.py
@@ -1,5 +1,5 @@
# sql/ddl.py
-# Copyright (C) 2009-2014 the SQLAlchemy authors and contributors
+# Copyright (C) 2009-2016 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@@ -679,13 +679,16 @@ class SchemaGenerator(DDLBase):
def _can_create_table(self, table):
self.dialect.validate_identifier(table.name)
- if table.schema:
- self.dialect.validate_identifier(table.schema)
+ effective_schema = self.connection.schema_for_object(table)
+ if effective_schema:
+ self.dialect.validate_identifier(effective_schema)
return not self.checkfirst or \
not self.dialect.has_table(self.connection,
- table.name, schema=table.schema)
+ table.name, schema=effective_schema)
def _can_create_sequence(self, sequence):
+ effective_schema = self.connection.schema_for_object(sequence)
+
return self.dialect.supports_sequences and \
(
(not self.dialect.sequences_optional or
@@ -695,7 +698,7 @@ class SchemaGenerator(DDLBase):
not self.dialect.has_sequence(
self.connection,
sequence.name,
- schema=sequence.schema)
+ schema=effective_schema)
)
)
@@ -711,8 +714,11 @@ class SchemaGenerator(DDLBase):
seq_coll = [s for s in metadata._sequences.values()
if s.column is None and self._can_create_sequence(s)]
+ event_collection = [
+ t for (t, fks) in collection if t is not None
+ ]
metadata.dispatch.before_create(metadata, self.connection,
- tables=collection,
+ tables=event_collection,
checkfirst=self.checkfirst,
_ddl_runner=self)
@@ -723,25 +729,29 @@ class SchemaGenerator(DDLBase):
if table is not None:
self.traverse_single(
table, create_ok=True,
- include_foreign_key_constraints=fkcs)
+ include_foreign_key_constraints=fkcs,
+ _is_metadata_operation=True)
else:
for fkc in fkcs:
self.traverse_single(fkc)
metadata.dispatch.after_create(metadata, self.connection,
- tables=collection,
+ tables=event_collection,
checkfirst=self.checkfirst,
_ddl_runner=self)
def visit_table(
self, table, create_ok=False,
- include_foreign_key_constraints=None):
+ include_foreign_key_constraints=None,
+ _is_metadata_operation=False):
if not create_ok and not self._can_create_table(table):
return
- table.dispatch.before_create(table, self.connection,
- checkfirst=self.checkfirst,
- _ddl_runner=self)
+ table.dispatch.before_create(
+ table, self.connection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ _is_metadata_operation=_is_metadata_operation)
for column in table.columns:
if column.default is not None:
@@ -761,9 +771,11 @@ class SchemaGenerator(DDLBase):
for index in table.indexes:
self.traverse_single(index)
- table.dispatch.after_create(table, self.connection,
- checkfirst=self.checkfirst,
- _ddl_runner=self)
+ table.dispatch.after_create(
+ table, self.connection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ _is_metadata_operation=_is_metadata_operation)
def visit_foreign_key_constraint(self, constraint):
if not self.dialect.supports_alter:
@@ -797,32 +809,50 @@ class SchemaDropper(DDLBase):
tables = list(metadata.tables.values())
try:
- collection = reversed(
+ unsorted_tables = [t for t in tables if self._can_drop_table(t)]
+ collection = list(reversed(
sort_tables_and_constraints(
- [t for t in tables if self._can_drop_table(t)],
- filter_fn=
- lambda constraint: True if not self.dialect.supports_alter
- else False if constraint.name is None
+ unsorted_tables,
+ filter_fn=lambda constraint: False
+ if not self.dialect.supports_alter
+ or constraint.name is None
else None
)
- )
+ ))
except exc.CircularDependencyError as err2:
- util.raise_from_cause(
- exc.CircularDependencyError(
- err2.args[0],
- err2.cycles, err2.edges,
- msg="Can't sort tables for DROP; an "
+ if not self.dialect.supports_alter:
+ util.warn(
+ "Can't sort tables for DROP; an "
"unresolvable foreign key "
- "dependency exists between tables: %s. Please ensure "
- "that the ForeignKey and ForeignKeyConstraint objects "
- "involved in the cycle have "
- "names so that they can be dropped using DROP CONSTRAINT."
+ "dependency exists between tables: %s, and backend does "
+ "not support ALTER. To restore at least a partial sort, "
+ "apply use_alter=True to ForeignKey and "
+ "ForeignKeyConstraint "
+ "objects involved in the cycle to mark these as known "
+ "cycles that will be ignored."
% (
", ".join(sorted([t.fullname for t in err2.cycles]))
)
+ )
+ collection = [(t, ()) for t in unsorted_tables]
+ else:
+ util.raise_from_cause(
+ exc.CircularDependencyError(
+ err2.args[0],
+ err2.cycles, err2.edges,
+ msg="Can't sort tables for DROP; an "
+ "unresolvable foreign key "
+ "dependency exists between tables: %s. Please ensure "
+ "that the ForeignKey and ForeignKeyConstraint objects "
+ "involved in the cycle have "
+ "names so that they can be dropped using "
+ "DROP CONSTRAINT."
+ % (
+ ", ".join(sorted([t.fullname for t in err2.cycles]))
+ )
+ )
)
- )
seq_coll = [
s
@@ -830,14 +860,18 @@ class SchemaDropper(DDLBase):
if s.column is None and self._can_drop_sequence(s)
]
+ event_collection = [
+ t for (t, fks) in collection if t is not None
+ ]
+
metadata.dispatch.before_drop(
- metadata, self.connection, tables=collection,
+ metadata, self.connection, tables=event_collection,
checkfirst=self.checkfirst, _ddl_runner=self)
for table, fkcs in collection:
if table is not None:
self.traverse_single(
- table, drop_ok=True)
+ table, drop_ok=True, _is_metadata_operation=True)
else:
for fkc in fkcs:
self.traverse_single(fkc)
@@ -846,17 +880,19 @@ class SchemaDropper(DDLBase):
self.traverse_single(seq, drop_ok=True)
metadata.dispatch.after_drop(
- metadata, self.connection, tables=collection,
+ metadata, self.connection, tables=event_collection,
checkfirst=self.checkfirst, _ddl_runner=self)
def _can_drop_table(self, table):
self.dialect.validate_identifier(table.name)
- if table.schema:
- self.dialect.validate_identifier(table.schema)
+ effective_schema = self.connection.schema_for_object(table)
+ if effective_schema:
+ self.dialect.validate_identifier(effective_schema)
return not self.checkfirst or self.dialect.has_table(
- self.connection, table.name, schema=table.schema)
+ self.connection, table.name, schema=effective_schema)
def _can_drop_sequence(self, sequence):
+ effective_schema = self.connection.schema_for_object(sequence)
return self.dialect.supports_sequences and \
((not self.dialect.sequences_optional or
not sequence.optional) and
@@ -864,19 +900,21 @@ class SchemaDropper(DDLBase):
self.dialect.has_sequence(
self.connection,
sequence.name,
- schema=sequence.schema))
+ schema=effective_schema))
)
def visit_index(self, index):
self.connection.execute(DropIndex(index))
- def visit_table(self, table, drop_ok=False):
+ def visit_table(self, table, drop_ok=False, _is_metadata_operation=False):
if not drop_ok and not self._can_drop_table(table):
return
- table.dispatch.before_drop(table, self.connection,
- checkfirst=self.checkfirst,
- _ddl_runner=self)
+ table.dispatch.before_drop(
+ table, self.connection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ _is_metadata_operation=_is_metadata_operation)
for column in table.columns:
if column.default is not None:
@@ -884,9 +922,11 @@ class SchemaDropper(DDLBase):
self.connection.execute(DropTable(table))
- table.dispatch.after_drop(table, self.connection,
- checkfirst=self.checkfirst,
- _ddl_runner=self)
+ table.dispatch.after_drop(
+ table, self.connection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ _is_metadata_operation=_is_metadata_operation)
def visit_foreign_key_constraint(self, constraint):
if not self.dialect.supports_alter:
@@ -1031,7 +1071,8 @@ def sort_tables_and_constraints(
try:
candidate_sort = list(
topological.sort(
- fixed_dependencies.union(mutable_dependencies), tables
+ fixed_dependencies.union(mutable_dependencies), tables,
+ deterministic_order=True
)
)
except exc.CircularDependencyError as err:
@@ -1048,7 +1089,8 @@ def sort_tables_and_constraints(
mutable_dependencies.discard((dependent_on, table))
candidate_sort = list(
topological.sort(
- fixed_dependencies.union(mutable_dependencies), tables
+ fixed_dependencies.union(mutable_dependencies), tables,
+ deterministic_order=True
)
)