From 532566ba1f28ff8a6afa6eacc10c59eb918501f6 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 10 Jul 2018 09:41:21 -0400 Subject: Drop default-related structures after the Table is dropped. Fixed bug where a :class:`.Sequence` would be dropped explicitly before any :class:`.Table` that refers to it, which breaks in the case when the sequence is also involved in a server-side default for that table, when using :meth:`.MetaData.drop_all`. The step which processes sequences to be dropped via non server-side column default functions is now invoked after the table itself is dropped. Change-Id: I185f2cc76d2011ad4dd3ba9bde5d8aef0ec335ae Fixes: #4300 --- lib/sqlalchemy/sql/ddl.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'lib/sqlalchemy/sql') diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py index 8de6f9cdc..91e93efe7 100644 --- a/lib/sqlalchemy/sql/ddl.py +++ b/lib/sqlalchemy/sql/ddl.py @@ -948,17 +948,22 @@ class SchemaDropper(DDLBase): _ddl_runner=self, _is_metadata_operation=_is_metadata_operation) + self.connection.execute(DropTable(table)) + + # traverse client side defaults which may refer to server-side + # sequences. noting that some of these client side defaults may also be + # set up as server side defaults (see http://docs.sqlalchemy.org/en/ + # latest/core/defaults.html#associating-a-sequence-as-the-server-side- + # default), so have to be dropped after the table is dropped. for column in table.columns: if column.default is not None: self.traverse_single(column.default) - self.connection.execute(DropTable(table)) - table.dispatch.after_drop( table, self.connection, - checkfirst=self.checkfirst, - _ddl_runner=self, - _is_metadata_operation=_is_metadata_operation) + 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: @@ -966,6 +971,7 @@ class SchemaDropper(DDLBase): self.connection.execute(DropConstraint(constraint)) def visit_sequence(self, sequence, drop_ok=False): + if not drop_ok and not self._can_drop_sequence(sequence): return self.connection.execute(DropSequence(sequence)) -- cgit v1.2.1