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))
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),
--- /dev/null
+.. 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.
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
eq_(diffs[5][0][5], False)
eq_(diffs[5][0][6], True)
-
class OrigObjectTest(TestBase):
def setUp(self):
self.metadata = m = MetaData()
")"
)
+ 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,
"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"),