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.py306
1 files changed, 180 insertions, 126 deletions
diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py
index 91e93efe7..f21b3d7f0 100644
--- a/lib/sqlalchemy/sql/ddl.py
+++ b/lib/sqlalchemy/sql/ddl.py
@@ -56,8 +56,9 @@ class DDLElement(Executable, _DDLCompiles):
"""
- _execution_options = Executable.\
- _execution_options.union({'autocommit': True})
+ _execution_options = Executable._execution_options.union(
+ {"autocommit": True}
+ )
target = None
on = None
@@ -95,11 +96,13 @@ class DDLElement(Executable, _DDLCompiles):
if self._should_execute(target, bind):
return bind.execute(self.against(target))
else:
- bind.engine.logger.info(
- "DDL execution skipped, criteria not met.")
+ bind.engine.logger.info("DDL execution skipped, criteria not met.")
- @util.deprecated("0.7", "See :class:`.DDLEvents`, as well as "
- ":meth:`.DDLElement.execute_if`.")
+ @util.deprecated(
+ "0.7",
+ "See :class:`.DDLEvents`, as well as "
+ ":meth:`.DDLElement.execute_if`.",
+ )
def execute_at(self, event_name, target):
"""Link execution of this DDL to the DDL lifecycle of a SchemaItem.
@@ -129,11 +132,12 @@ class DDLElement(Executable, _DDLCompiles):
"""
def call_event(target, connection, **kw):
- if self._should_execute_deprecated(event_name,
- target, connection, **kw):
+ if self._should_execute_deprecated(
+ event_name, target, connection, **kw
+ ):
return connection.execute(self.against(target))
- event.listen(target, "" + event_name.replace('-', '_'), call_event)
+ event.listen(target, "" + event_name.replace("-", "_"), call_event)
@_generative
def against(self, target):
@@ -211,8 +215,9 @@ class DDLElement(Executable, _DDLCompiles):
self.state = state
def _should_execute(self, target, bind, **kw):
- if self.on is not None and \
- not self._should_execute_deprecated(None, target, bind, **kw):
+ if self.on is not None and not self._should_execute_deprecated(
+ None, target, bind, **kw
+ ):
return False
if isinstance(self.dialect, util.string_types):
@@ -221,9 +226,9 @@ class DDLElement(Executable, _DDLCompiles):
elif isinstance(self.dialect, (tuple, list, set)):
if bind.engine.name not in self.dialect:
return False
- if (self.callable_ is not None and
- not self.callable_(self, target, bind,
- state=self.state, **kw)):
+ if self.callable_ is not None and not self.callable_(
+ self, target, bind, state=self.state, **kw
+ ):
return False
return True
@@ -245,13 +250,15 @@ class DDLElement(Executable, _DDLCompiles):
return bind.execute(self.against(target))
def _check_ddl_on(self, on):
- if (on is not None and
- (not isinstance(on, util.string_types + (tuple, list, set)) and
- not util.callable(on))):
+ if on is not None and (
+ not isinstance(on, util.string_types + (tuple, list, set))
+ and not util.callable(on)
+ ):
raise exc.ArgumentError(
"Expected the name of a database dialect, a tuple "
"of names, or a callable for "
- "'on' criteria, got type '%s'." % type(on).__name__)
+ "'on' criteria, got type '%s'." % type(on).__name__
+ )
def bind(self):
if self._bind:
@@ -259,6 +266,7 @@ class DDLElement(Executable, _DDLCompiles):
def _set_bind(self, bind):
self._bind = bind
+
bind = property(bind, _set_bind)
def _generate(self):
@@ -375,8 +383,9 @@ class DDL(DDLElement):
if not isinstance(statement, util.string_types):
raise exc.ArgumentError(
- "Expected a string or unicode SQL statement, got '%r'" %
- statement)
+ "Expected a string or unicode SQL statement, got '%r'"
+ % statement
+ )
self.statement = statement
self.context = context or {}
@@ -386,12 +395,18 @@ class DDL(DDLElement):
self._bind = bind
def __repr__(self):
- return '<%s@%s; %s>' % (
- type(self).__name__, id(self),
- ', '.join([repr(self.statement)] +
- ['%s=%r' % (key, getattr(self, key))
- for key in ('on', 'context')
- if getattr(self, key)]))
+ return "<%s@%s; %s>" % (
+ type(self).__name__,
+ id(self),
+ ", ".join(
+ [repr(self.statement)]
+ + [
+ "%s=%r" % (key, getattr(self, key))
+ for key in ("on", "context")
+ if getattr(self, key)
+ ]
+ ),
+ )
class _CreateDropBase(DDLElement):
@@ -464,8 +479,8 @@ class CreateTable(_CreateDropBase):
__visit_name__ = "create_table"
def __init__(
- self, element, on=None, bind=None,
- include_foreign_key_constraints=None):
+ self, element, on=None, bind=None, include_foreign_key_constraints=None
+ ):
"""Create a :class:`.CreateTable` construct.
:param element: a :class:`.Table` that's the subject
@@ -481,9 +496,7 @@ class CreateTable(_CreateDropBase):
"""
super(CreateTable, self).__init__(element, on=on, bind=bind)
- self.columns = [CreateColumn(column)
- for column in element.columns
- ]
+ self.columns = [CreateColumn(column) for column in element.columns]
self.include_foreign_key_constraints = include_foreign_key_constraints
@@ -494,6 +507,7 @@ class _DropView(_CreateDropBase):
This object will eventually be part of a public "view" API.
"""
+
__visit_name__ = "drop_view"
@@ -602,7 +616,8 @@ class CreateColumn(_DDLCompiles):
to support custom column creation styles.
"""
- __visit_name__ = 'create_column'
+
+ __visit_name__ = "create_column"
def __init__(self, element):
self.element = element
@@ -646,7 +661,8 @@ class AddConstraint(_CreateDropBase):
def __init__(self, element, *args, **kw):
super(AddConstraint, self).__init__(element, *args, **kw)
element._create_rule = util.portable_instancemethod(
- self._create_rule_disable)
+ self._create_rule_disable
+ )
class DropConstraint(_CreateDropBase):
@@ -658,7 +674,8 @@ class DropConstraint(_CreateDropBase):
self.cascade = cascade
super(DropConstraint, self).__init__(element, **kw)
element._create_rule = util.portable_instancemethod(
- self._create_rule_disable)
+ self._create_rule_disable
+ )
class SetTableComment(_CreateDropBase):
@@ -691,9 +708,9 @@ class DDLBase(SchemaVisitor):
class SchemaGenerator(DDLBase):
-
- def __init__(self, dialect, connection, checkfirst=False,
- tables=None, **kwargs):
+ def __init__(
+ self, dialect, connection, checkfirst=False, tables=None, **kwargs
+ ):
super(SchemaGenerator, self).__init__(connection, **kwargs)
self.checkfirst = checkfirst
self.tables = tables
@@ -706,25 +723,22 @@ class SchemaGenerator(DDLBase):
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=effective_schema)
+ return not self.checkfirst or not self.dialect.has_table(
+ self.connection, 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
- not sequence.optional) and
- (
- not self.checkfirst or
- not self.dialect.has_sequence(
- self.connection,
- sequence.name,
- schema=effective_schema)
+ return self.dialect.supports_sequences and (
+ (not self.dialect.sequences_optional or not sequence.optional)
+ and (
+ not self.checkfirst
+ or not self.dialect.has_sequence(
+ self.connection, sequence.name, schema=effective_schema
)
)
+ )
def visit_metadata(self, metadata):
if self.tables is not None:
@@ -733,18 +747,23 @@ class SchemaGenerator(DDLBase):
tables = list(metadata.tables.values())
collection = sort_tables_and_constraints(
- [t for t in tables if self._can_create_table(t)])
-
- seq_coll = [s for s in metadata._sequences.values()
- if s.column is None and self._can_create_sequence(s)]
+ [t for t in tables if self._can_create_table(t)]
+ )
- event_collection = [
- t for (t, fks) in collection if t is not None
+ seq_coll = [
+ s
+ for s in metadata._sequences.values()
+ if s.column is None and self._can_create_sequence(s)
]
- metadata.dispatch.before_create(metadata, self.connection,
- tables=event_collection,
- checkfirst=self.checkfirst,
- _ddl_runner=self)
+
+ event_collection = [t for (t, fks) in collection if t is not None]
+ metadata.dispatch.before_create(
+ metadata,
+ self.connection,
+ tables=event_collection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ )
for seq in seq_coll:
self.traverse_single(seq, create_ok=True)
@@ -752,30 +771,40 @@ class SchemaGenerator(DDLBase):
for table, fkcs in collection:
if table is not None:
self.traverse_single(
- table, create_ok=True,
+ table,
+ create_ok=True,
include_foreign_key_constraints=fkcs,
- _is_metadata_operation=True)
+ _is_metadata_operation=True,
+ )
else:
for fkc in fkcs:
self.traverse_single(fkc)
- metadata.dispatch.after_create(metadata, self.connection,
- tables=event_collection,
- checkfirst=self.checkfirst,
- _ddl_runner=self)
+ metadata.dispatch.after_create(
+ metadata,
+ self.connection,
+ tables=event_collection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ )
def visit_table(
- self, table, create_ok=False,
- include_foreign_key_constraints=None,
- _is_metadata_operation=False):
+ self,
+ table,
+ create_ok=False,
+ 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,
+ table,
+ self.connection,
checkfirst=self.checkfirst,
_ddl_runner=self,
- _is_metadata_operation=_is_metadata_operation)
+ _is_metadata_operation=_is_metadata_operation,
+ )
for column in table.columns:
if column.default is not None:
@@ -788,10 +817,11 @@ class SchemaGenerator(DDLBase):
self.connection.execute(
CreateTable(
table,
- include_foreign_key_constraints=include_foreign_key_constraints
- ))
+ include_foreign_key_constraints=include_foreign_key_constraints,
+ )
+ )
- if hasattr(table, 'indexes'):
+ if hasattr(table, "indexes"):
for index in table.indexes:
self.traverse_single(index)
@@ -804,10 +834,12 @@ class SchemaGenerator(DDLBase):
self.connection.execute(SetColumnComment(column))
table.dispatch.after_create(
- table, self.connection,
+ table,
+ self.connection,
checkfirst=self.checkfirst,
_ddl_runner=self,
- _is_metadata_operation=_is_metadata_operation)
+ _is_metadata_operation=_is_metadata_operation,
+ )
def visit_foreign_key_constraint(self, constraint):
if not self.dialect.supports_alter:
@@ -824,9 +856,9 @@ class SchemaGenerator(DDLBase):
class SchemaDropper(DDLBase):
-
- def __init__(self, dialect, connection, checkfirst=False,
- tables=None, **kwargs):
+ def __init__(
+ self, dialect, connection, checkfirst=False, tables=None, **kwargs
+ ):
super(SchemaDropper, self).__init__(connection, **kwargs)
self.checkfirst = checkfirst
self.tables = tables
@@ -842,15 +874,17 @@ class SchemaDropper(DDLBase):
try:
unsorted_tables = [t for t in tables if self._can_drop_table(t)]
- collection = list(reversed(
- sort_tables_and_constraints(
- unsorted_tables,
- filter_fn=lambda constraint: False
- if not self.dialect.supports_alter
- or constraint.name is None
- else None
+ collection = list(
+ reversed(
+ sort_tables_and_constraints(
+ 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:
if not self.dialect.supports_alter:
util.warn(
@@ -862,16 +896,15 @@ class SchemaDropper(DDLBase):
"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]))
- )
+ % (", ".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,
+ err2.cycles,
+ err2.edges,
msg="Can't sort tables for DROP; an "
"unresolvable foreign key "
"dependency exists between tables: %s. Please ensure "
@@ -880,9 +913,10 @@ class SchemaDropper(DDLBase):
"names so that they can be dropped using "
"DROP CONSTRAINT."
% (
- ", ".join(sorted([t.fullname for t in err2.cycles]))
- )
-
+ ", ".join(
+ sorted([t.fullname for t in err2.cycles])
+ )
+ ),
)
)
@@ -892,18 +926,21 @@ 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
- ]
+ event_collection = [t for (t, fks) in collection if t is not None]
metadata.dispatch.before_drop(
- metadata, self.connection, tables=event_collection,
- checkfirst=self.checkfirst, _ddl_runner=self)
+ 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, _is_metadata_operation=True)
+ table, drop_ok=True, _is_metadata_operation=True
+ )
else:
for fkc in fkcs:
self.traverse_single(fkc)
@@ -912,8 +949,12 @@ class SchemaDropper(DDLBase):
self.traverse_single(seq, drop_ok=True)
metadata.dispatch.after_drop(
- metadata, self.connection, tables=event_collection,
- checkfirst=self.checkfirst, _ddl_runner=self)
+ metadata,
+ self.connection,
+ tables=event_collection,
+ checkfirst=self.checkfirst,
+ _ddl_runner=self,
+ )
def _can_drop_table(self, table):
self.dialect.validate_identifier(table.name)
@@ -921,19 +962,20 @@ class SchemaDropper(DDLBase):
if effective_schema:
self.dialect.validate_identifier(effective_schema)
return not self.checkfirst or self.dialect.has_table(
- self.connection, table.name, schema=effective_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
- (not self.checkfirst or
- self.dialect.has_sequence(
- self.connection,
- sequence.name,
- schema=effective_schema))
- )
+ return self.dialect.supports_sequences and (
+ (not self.dialect.sequences_optional or not sequence.optional)
+ and (
+ not self.checkfirst
+ or self.dialect.has_sequence(
+ self.connection, sequence.name, schema=effective_schema
+ )
+ )
+ )
def visit_index(self, index):
self.connection.execute(DropIndex(index))
@@ -943,10 +985,12 @@ class SchemaDropper(DDLBase):
return
table.dispatch.before_drop(
- table, self.connection,
+ table,
+ self.connection,
checkfirst=self.checkfirst,
_ddl_runner=self,
- _is_metadata_operation=_is_metadata_operation)
+ _is_metadata_operation=_is_metadata_operation,
+ )
self.connection.execute(DropTable(table))
@@ -960,10 +1004,12 @@ class SchemaDropper(DDLBase):
self.traverse_single(column.default)
table.dispatch.after_drop(
- table, self.connection,
+ table,
+ self.connection,
checkfirst=self.checkfirst,
_ddl_runner=self,
- _is_metadata_operation=_is_metadata_operation)
+ _is_metadata_operation=_is_metadata_operation,
+ )
def visit_foreign_key_constraint(self, constraint):
if not self.dialect.supports_alter:
@@ -1019,25 +1065,29 @@ def sort_tables(tables, skip_fn=None, extra_dependencies=None):
"""
if skip_fn is not None:
+
def _skip_fn(fkc):
for fk in fkc.elements:
if skip_fn(fk):
return True
else:
return None
+
else:
_skip_fn = None
return [
- t for (t, fkcs) in
- sort_tables_and_constraints(
- tables, filter_fn=_skip_fn, extra_dependencies=extra_dependencies)
+ t
+ for (t, fkcs) in sort_tables_and_constraints(
+ tables, filter_fn=_skip_fn, extra_dependencies=extra_dependencies
+ )
if t is not None
]
def sort_tables_and_constraints(
- tables, filter_fn=None, extra_dependencies=None):
+ tables, filter_fn=None, extra_dependencies=None
+):
"""sort a collection of :class:`.Table` / :class:`.ForeignKeyConstraint`
objects.
@@ -1109,8 +1159,9 @@ def sort_tables_and_constraints(
try:
candidate_sort = list(
topological.sort(
- fixed_dependencies.union(mutable_dependencies), tables,
- deterministic_order=True
+ fixed_dependencies.union(mutable_dependencies),
+ tables,
+ deterministic_order=True,
)
)
except exc.CircularDependencyError as err:
@@ -1118,8 +1169,10 @@ def sort_tables_and_constraints(
if edge in mutable_dependencies:
table = edge[1]
can_remove = [
- fkc for fkc in table.foreign_key_constraints
- if filter_fn is None or filter_fn(fkc) is not False]
+ fkc
+ for fkc in table.foreign_key_constraints
+ if filter_fn is None or filter_fn(fkc) is not False
+ ]
remaining_fkcs.update(can_remove)
for fkc in can_remove:
dependent_on = fkc.referred_table
@@ -1127,8 +1180,9 @@ def sort_tables_and_constraints(
mutable_dependencies.discard((dependent_on, table))
candidate_sort = list(
topological.sort(
- fixed_dependencies.union(mutable_dependencies), tables,
- deterministic_order=True
+ fixed_dependencies.union(mutable_dependencies),
+ tables,
+ deterministic_order=True,
)
)