From: Mike Bayer Date: Wed, 11 Oct 2017 14:08:19 +0000 (-0400) Subject: Append table name to batch temp name X-Git-Tag: rel_0_9_6~2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b80d35e977b8482efa5c54ee1281091eac76d46;p=thirdparty%2Fsqlalchemy%2Falembic.git Append table name to batch temp name The name of the temporary table in batch mode is now generated off of the original table name itself, to avoid conflicts for the unusual case of multiple batch operations running against the same database schema at the same time. Change-Id: Idbeabf9558887d3f5525e7045d5de33bab6805a5 Fixes: #457 --- diff --git a/alembic/operations/batch.py b/alembic/operations/batch.py index fa7899e0..84d29d95 100644 --- a/alembic/operations/batch.py +++ b/alembic/operations/batch.py @@ -117,6 +117,7 @@ class ApplyBatchImpl(object): self.table = table # this is a Table object self.table_args = table_args self.table_kwargs = table_kwargs + self.temp_table_name = self._calc_temp_name(table.name) self.new_table = None self.column_transfers = OrderedDict( (c.name, {'expr': c}) for c in self.table.c @@ -124,6 +125,10 @@ class ApplyBatchImpl(object): self.reflected = reflected self._grab_table_elements() + @classmethod + def _calc_temp_name(cls, tablename): + return ("_alembic_tmp_%s" % tablename)[0:50] + def _grab_table_elements(self): schema = self.table.schema self.columns = OrderedDict() @@ -164,7 +169,7 @@ class ApplyBatchImpl(object): schema = self.table.schema self.new_table = new_table = Table( - '_alembic_batch_temp', m, + self.temp_table_name, m, *(list(self.columns.values()) + list(self.table_args)), schema=schema, **self.table_kwargs) @@ -221,7 +226,7 @@ class ApplyBatchImpl(object): else: referent_schema = None - if tname != '_alembic_batch_temp': + if tname != self.temp_table_name: key = sql_schema._get_table_key(tname, referent_schema) if key in metadata.tables: t = metadata.tables[key] @@ -263,7 +268,7 @@ class ApplyBatchImpl(object): raise else: op_impl.rename_table( - "_alembic_batch_temp", + self.temp_table_name, self.table.name, schema=self.table.schema ) @@ -272,7 +277,7 @@ class ApplyBatchImpl(object): for idx in self._gather_indexes_from_both_tables(): op_impl.create_index(idx) finally: - self.new_table.name = "_alembic_batch_temp" + self.new_table.name = self.temp_table_name def alter_column(self, table_name, column_name, nullable=None, diff --git a/docs/build/unreleased/457.rst b/docs/build/unreleased/457.rst new file mode 100644 index 00000000..92f88af7 --- /dev/null +++ b/docs/build/unreleased/457.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, batch + :tickets: 457 + + The name of the temporary table in batch mode is now generated + off of the original table name itself, to avoid conflicts for the + unusual case of multiple batch operations running against the same + database schema at the same time. \ No newline at end of file diff --git a/tests/test_batch.py b/tests/test_batch.py index afffa356..03be9f98 100644 --- a/tests/test_batch.py +++ b/tests/test_batch.py @@ -205,7 +205,8 @@ class BatchApplyTest(TestBase): for idx in impl.new_indexes.values(): impl.new_table.name = impl.table.name idx_stmt += str(CreateIndex(idx).compile(dialect=context.dialect)) - impl.new_table.name = '_alembic_batch_temp' + impl.new_table.name = ApplyBatchImpl._calc_temp_name( + impl.table.name) idx_stmt = re.sub(r'[\n\t]', '', idx_stmt) if ddl_contains: @@ -222,6 +223,8 @@ class BatchApplyTest(TestBase): else: args = {"schema": ""} + args["temp_name"] = impl.new_table.name + args['colnames'] = ", ".join([ impl.new_table.c[name].name for name in colnames @@ -242,10 +245,10 @@ class BatchApplyTest(TestBase): ) expected.extend([ - 'INSERT INTO %(schema)s_alembic_batch_temp (%(colnames)s) ' + 'INSERT INTO %(schema)s%(temp_name)s (%(colnames)s) ' 'SELECT %(tname_colnames)s FROM %(schema)stname' % args, 'DROP TABLE %(schema)stname' % args, - 'ALTER TABLE %(schema)s_alembic_batch_temp ' + 'ALTER TABLE %(schema)s%(temp_name)s ' 'RENAME TO %(schema)stname' % args ]) if idx_stmt: @@ -772,12 +775,12 @@ class CopyFromTest(TestBase): "foo", copy_from=self.table) as batch_op: batch_op.alter_column('data', type_=Integer) context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data INTEGER, x INTEGER, PRIMARY KEY (id))', - 'INSERT INTO _alembic_batch_temp (id, data, x) SELECT foo.id, ' + 'INSERT INTO _alembic_tmp_foo (id, data, x) SELECT foo.id, ' 'CAST(foo.data AS INTEGER) AS anon_1, foo.x FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo' + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo' ) def test_change_type_from_schematype(self): @@ -793,12 +796,12 @@ class CopyFromTest(TestBase): existing_type=Boolean( create_constraint=True, name="ck1")) context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data VARCHAR(50), x INTEGER, y INTEGER, PRIMARY KEY (id))', - 'INSERT INTO _alembic_batch_temp (id, data, x, y) SELECT foo.id, ' + 'INSERT INTO _alembic_tmp_foo (id, data, x, y) SELECT foo.id, ' 'foo.data, foo.x, CAST(foo.y AS INTEGER) AS anon_1 FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo' + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo' ) def test_change_type_to_schematype(self): @@ -813,13 +816,13 @@ class CopyFromTest(TestBase): type_=Boolean( create_constraint=True, name="ck1")) context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data VARCHAR(50), x INTEGER, y BOOLEAN, PRIMARY KEY (id), ' 'CONSTRAINT ck1 CHECK (y IN (0, 1)))', - 'INSERT INTO _alembic_batch_temp (id, data, x, y) SELECT foo.id, ' + 'INSERT INTO _alembic_tmp_foo (id, data, x, y) SELECT foo.id, ' 'foo.data, foo.x, CAST(foo.y AS BOOLEAN) AS anon_1 FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo' + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo' ) def test_create_drop_index_w_always(self): @@ -830,13 +833,13 @@ class CopyFromTest(TestBase): 'ix_data', ['data'], unique=True) context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data VARCHAR(50), ' 'x INTEGER, PRIMARY KEY (id))', - 'INSERT INTO _alembic_batch_temp (id, data, x) ' + 'INSERT INTO _alembic_tmp_foo (id, data, x) ' 'SELECT foo.id, foo.data, foo.x FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo', + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo', 'CREATE UNIQUE INDEX ix_data ON foo (data)', ) @@ -848,12 +851,12 @@ class CopyFromTest(TestBase): batch_op.drop_index('ix_data') context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data VARCHAR(50), x INTEGER, PRIMARY KEY (id))', - 'INSERT INTO _alembic_batch_temp (id, data, x) ' + 'INSERT INTO _alembic_tmp_foo (id, data, x) ' 'SELECT foo.id, foo.data, foo.x FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo' + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo' ) def test_create_drop_index_wo_always(self): @@ -887,12 +890,12 @@ class CopyFromTest(TestBase): 'ix_data', ['data'], unique=True) context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data INTEGER, x INTEGER, PRIMARY KEY (id))', - 'INSERT INTO _alembic_batch_temp (id, data, x) SELECT foo.id, ' + 'INSERT INTO _alembic_tmp_foo (id, data, x) SELECT foo.id, ' 'CAST(foo.data AS INTEGER) AS anon_1, foo.x FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo', + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo', 'CREATE UNIQUE INDEX ix_data ON foo (data)', ) @@ -905,12 +908,12 @@ class CopyFromTest(TestBase): batch_op.alter_column('data', type_=String) context.assert_( - 'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, ' + 'CREATE TABLE _alembic_tmp_foo (id INTEGER NOT NULL, ' 'data VARCHAR, x INTEGER, PRIMARY KEY (id))', - 'INSERT INTO _alembic_batch_temp (id, data, x) SELECT foo.id, ' + 'INSERT INTO _alembic_tmp_foo (id, data, x) SELECT foo.id, ' 'foo.data, foo.x FROM foo', 'DROP TABLE foo', - 'ALTER TABLE _alembic_batch_temp RENAME TO foo' + 'ALTER TABLE _alembic_tmp_foo RENAME TO foo' ) @@ -1104,7 +1107,7 @@ class BatchRoundTripTest(TestBase): # in particular, this tests that the failures # on PG and MySQL result in recovery of the batch system, - # e.g. that the _alembic_batch_temp table is dropped + # e.g. that the _alembic_tmp_temp table is dropped @config.requirements.no_referential_integrity def test_fk_points_to_me_recreate(self): self._test_fk_points_to_me("always")