From: Mike Bayer Date: Wed, 24 Oct 2018 17:44:09 +0000 (-0400) Subject: Dont autogenerate "system=True", render flag correctly X-Git-Tag: rel_1_0_2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af5586762905aa9115cbcd2af26bcd7087c264ed;p=thirdparty%2Fsqlalchemy%2Falembic.git Dont autogenerate "system=True", render flag correctly The ``system=True`` flag on :class:`.Column`, used primarily in conjunction with the Postgresql "xmin" column, now renders within the autogenerate render process, allowing the column to be excluded from DDL. Additionally, adding a system=True column to a model will produce no autogenerate diff as this column is implicitly present in the database. Change-Id: Ie3aab9d489ebb9aecccbdf9d5b3ce8ccc42554bf Fixes: #515 --- diff --git a/alembic/autogenerate/compare.py b/alembic/autogenerate/compare.py index 1b660613..8b416475 100644 --- a/alembic/autogenerate/compare.py +++ b/alembic/autogenerate/compare.py @@ -241,7 +241,8 @@ def _make_foreign_key(params, conn_table): def _compare_columns(schema, tname, conn_table, metadata_table, modify_table_ops, autogen_context, inspector): name = '%s.%s' % (schema, tname) if schema else tname - metadata_cols_by_name = dict((c.name, c) for c in metadata_table.c) + metadata_cols_by_name = dict( + (c.name, c) for c in metadata_table.c if not c.system) conn_col_names = dict((c.name, c) for c in conn_table.c) metadata_col_names = OrderedSet(sorted(metadata_cols_by_name)) diff --git a/alembic/autogenerate/render.py b/alembic/autogenerate/render.py index ed289a6c..4fbe91fd 100644 --- a/alembic/autogenerate/render.py +++ b/alembic/autogenerate/render.py @@ -534,6 +534,9 @@ def _render_column(column, autogen_context): if column.nullable is not None: opts.append(("nullable", column.nullable)) + if column.system: + opts.append(("system", column.system)) + # TODO: for non-ascii colname, assign a "key" return "%(prefix)sColumn(%(name)r, %(type)s, %(kw)s)" % { 'prefix': _sqlalchemy_autogenerate_prefix(autogen_context), diff --git a/docs/build/unreleased/515.rst b/docs/build/unreleased/515.rst new file mode 100644 index 00000000..73cf85d3 --- /dev/null +++ b/docs/build/unreleased/515.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, autogenerate + :tickets: 515 + + The ``system=True`` flag on :class:`.Column`, used primarily in conjunction + with the Postgresql "xmin" column, now renders within the autogenerate + render process, allowing the column to be excluded from DDL. Additionally, + adding a system=True column to a model will produce no autogenerate diff as + this column is implicitly present in the database. diff --git a/tests/test_autogen_diffs.py b/tests/test_autogen_diffs.py index 85f87a31..38e06b6c 100644 --- a/tests/test_autogen_diffs.py +++ b/tests/test_autogen_diffs.py @@ -675,6 +675,40 @@ class CompareTypeSpecificityTest(TestBase): is_(impl.compare_type(Column('x', t2), Column('x', t3)), True) +class AutogenSystemColTest(AutogenTest, TestBase): + __only_on__ = 'postgresql' + + @classmethod + def _get_db_schema(cls): + m = MetaData() + + Table( + 'sometable', m, + Column('id', Integer, primary_key=True), + ) + return m + + @classmethod + def _get_model_schema(cls): + m = MetaData() + + # 'xmin' is implicitly present, when added to a model should produce + # no change + Table( + 'sometable', m, + Column('id', Integer, primary_key=True), + Column('xmin', Integer, system=True) + ) + return m + + def test_dont_add_system(self): + uo = ops.UpgradeOps(ops=[]) + autogenerate._produce_net_changes(self.autogen_context, uo) + + diffs = uo.as_diffs() + eq_(diffs, []) + + class AutogenerateVariantCompareTest(AutogenTest, TestBase): __backend__ = True @@ -1134,7 +1168,6 @@ class PGCompareMetaData(ModelOne, AutogenTest, TestBase): eq_(diffs[5][0][5], False) eq_(diffs[5][0][6], True) - class OrigObjectTest(TestBase): def setUp(self): self.metadata = m = MetaData() diff --git a/tests/test_autogen_render.py b/tests/test_autogen_render.py index 2bc8d825..b32358fa 100644 --- a/tests/test_autogen_render.py +++ b/tests/test_autogen_render.py @@ -688,6 +688,21 @@ class AutogenRenderTest(TestBase): ")" ) + def test_render_table_w_system(self): + m = MetaData() + t = Table('sometable', m, + Column('id', Integer, primary_key=True), + Column('xmin', Integer, system=True, nullable=False) + ) + op_obj = ops.CreateTableOp.from_table(t) + eq_ignore_whitespace( + autogenerate.render_op_text(self.autogen_context, op_obj), + "op.create_table('sometable'," + "sa.Column('id', sa.Integer(), nullable=False)," + "sa.Column('xmin', sa.Integer(), nullable=False, system=True)," + "sa.PrimaryKeyConstraint('id'))" + ) + def test_render_table_w_unicode_name(self): m = MetaData() t = Table(compat.ue('\u0411\u0435\u0437'), m, @@ -937,6 +952,18 @@ class AutogenRenderTest(TestBase): "server_default='5', nullable=True))" ) + def test_render_add_column_system(self): + # this would never actually happen since "system" columns + # can't be added in any case. Howver it will render as + # part of op.CreateTableOp. + op_obj = ops.AddColumnOp( + "foo", Column("xmin", Integer, system=True)) + eq_ignore_whitespace( + autogenerate.render_op_text(self.autogen_context, op_obj), + "op.add_column('foo', sa.Column('xmin', sa.Integer(), " + "nullable=True, system=True))" + ) + def test_render_add_column_w_schema(self): op_obj = ops.AddColumnOp( "bar", Column("x", Integer, server_default="5"),