metadata_col,
col_diff, autogen_context
)
- _compare_nullable(schema, tname, colname,
- conn_col,
- metadata_col.nullable,
- col_diff, autogen_context
- )
+ # work around SQLAlchemy issue #3023
+ if not metadata_col.primary_key:
+ _compare_nullable(schema, tname, colname,
+ conn_col,
+ metadata_col.nullable,
+ col_diff, autogen_context
+ )
_compare_server_default(schema, tname, colname,
conn_col,
metadata_col,
)
)
+ def compare_server_default(self, inspector_column,
+ metadata_column,
+ rendered_metadata_default,
+ rendered_inspector_default):
+ # partially a workaround for SQLAlchemy issue #3023; if the
+ # column were created without "NOT NULL", MySQL may have added
+ # an implicit default of '0' which we need to skip
+ if metadata_column.type._type_affinity is sqltypes.Integer and \
+ inspector_column.primary_key and \
+ not inspector_column.autoincrement and \
+ not rendered_metadata_default and \
+ rendered_inspector_default == "'0'":
+ return False
+ else:
+ return rendered_inspector_default != rendered_metadata_default
+
def correct_for_autogen_constraints(self, conn_unique_constraints,
conn_indexes,
metadata_unique_constraints,
.. changelog::
:version: 0.7.0
+ .. change::
+ :tags: bug, autogenerate
+ :tickets: 199
+
+ Added a workaround for SQLAlchemy issue #3023 (fixed in 0.9.5) where
+ a column that's part of an explicit PrimaryKeyConstraint would not
+ have its "nullable" flag set to False, thus producing a false
+ autogenerate. Also added a related correction to MySQL which will
+ correct for MySQL's implicit server default of '0' when a NULL integer
+ column is turned into a primary key column.
+
.. change::
:tags: bug, autogenerate, mysql
:tickets: 240
from sqlalchemy import MetaData, Column, Table, Integer, String, Text, \
Numeric, CHAR, ForeignKey, INTEGER, \
- TypeDecorator, CheckConstraint, text
+ TypeDecorator, CheckConstraint, text, PrimaryKeyConstraint
from sqlalchemy.types import NULLTYPE
from sqlalchemy.engine.reflection import Inspector
class AutogenTest(object):
- __only_on__ = 'sqlite'
@classmethod
def _get_bind(cls):
class AutogenerateDiffTest(ModelOne, AutogenTest, TestBase):
+ __only_on__ = 'sqlite'
def test_diffs(self):
"""test generation of diff rules"""
class AutogenerateCustomCompareTypeTest(AutogenTest, TestBase):
+ __only_on__ = 'sqlite'
@classmethod
def _get_db_schema(cls):
eq_(diffs[1][0][0], 'modify_type')
+class PKConstraintUpgradesIgnoresNullableTest(AutogenTest, TestBase):
+ __backend__ = True
+
+ # test workaround for SQLAlchemy issue #3023, alembic issue #199
+ @classmethod
+ def _get_db_schema(cls):
+ m = MetaData()
+
+ Table(
+ 'person_to_role', m,
+ Column('person_id', Integer, autoincrement=False),
+ Column('role_id', Integer, autoincrement=False),
+ PrimaryKeyConstraint('person_id', 'role_id')
+ )
+ return m
+
+ @classmethod
+ def _get_model_schema(cls):
+ return cls._get_db_schema()
+
+ def test_no_change(self):
+ metadata = self.m2
+ connection = self.context.bind
+
+ diffs = []
+
+ autogenerate._produce_net_changes(connection, metadata, diffs,
+ self.autogen_context
+ )
+ eq_(diffs, [])
+
+
class AutogenKeyTest(AutogenTest, TestBase):
+ __only_on__ = 'sqlite'
@classmethod
def _get_db_schema(cls):
class AutogenVersionTableTest(AutogenTest, TestBase):
+ __only_on__ = 'sqlite'
version_table_name = 'alembic_version'
version_table_schema = None
class AutogenerateDiffOrderTest(AutogenTest, TestBase):
+ __only_on__ = 'sqlite'
@classmethod
def _get_db_schema(cls):
class CompareMetadataTest(ModelOne, AutogenTest, TestBase):
+ __only_on__ = 'sqlite'
def test_compare_metadata(self):
metadata = self.m2