adding basic support for firebird, fixes #55
This commit is contained in:
parent
17cc5f36e6
commit
a8c31eb25f
10
docs/api.rst
10
docs/api.rst
@ -39,6 +39,16 @@ Module :mod:`mysql <migrate.changeset.databases.mysql>`
|
||||
:members:
|
||||
:synopsis: MySQL database specific changeset implementations
|
||||
|
||||
.. _firebird-d:
|
||||
|
||||
Module :mod:`firebird <migrate.changeset.databases.firebird>`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
.. automodule:: migrate.changeset.databases.firebird
|
||||
:members:
|
||||
:synopsis: Firebird database specific changeset implementations
|
||||
|
||||
.. _oracle-d:
|
||||
|
||||
Module :mod:`oracle <migrate.changeset.databases.oracle>`
|
||||
|
@ -1,6 +1,7 @@
|
||||
0.5.5
|
||||
-----
|
||||
|
||||
- added support for :ref:`firebird <firebird-d>`
|
||||
- server_defaults passed to column.create are now issued correctly
|
||||
- constraints passed to column.create are correctly interpreted (ALTER TABLE ADD CONSTRAINT is issued after ADD COLUMN)
|
||||
- column.create accepts `primary_key_name`, `unique_name` and `index_name` as string value which is used as contraint name when adding a column
|
||||
|
@ -43,40 +43,40 @@ Download and Development
|
||||
Dialect support
|
||||
---------------
|
||||
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| Operation / Dialect | :ref:`sqlite <sqlite-d>` | :ref:`postgres <postgres-d>` | :ref:`mysql <mysql-d>` | :ref:`oracle <oracle-d>` | firebird | mssql |
|
||||
| | | | | | | |
|
||||
+=========================================================+==========================+==============================+========================+===========================+==========+=======+
|
||||
| :ref:`ALTER TABLE RENAME TABLE <table-rename>` | yes | yes | yes | yes | | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`ALTER TABLE RENAME COLUMN <column-alter>` | yes | yes | yes | yes | | |
|
||||
| | (workaround) [#1]_ | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`ALTER TABLE ADD COLUMN <column-create>` | yes | yes | yes | yes | | |
|
||||
| | (with limitations) [#2]_ | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`ALTER TABLE DROP COLUMN <column-drop>` | yes | yes | yes | yes | | |
|
||||
| | (workaround) [#1]_ | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`ALTER TABLE ALTER COLUMN <column-alter>` | no | yes | yes | yes | | |
|
||||
| | | | | (with limitations) [#3]_ | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`ALTER TABLE ADD CONSTRAINT <constraint-tutorial>` | no | yes | yes | yes | | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`ALTER TABLE DROP CONSTRAINT <constraint-tutorial>`| no | yes | yes | yes | | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
| :ref:`RENAME INDEX <index-rename>` | no | yes | no | yes | | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+----------+-------+
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| Operation / Dialect | :ref:`sqlite <sqlite-d>` | :ref:`postgres <postgres-d>` | :ref:`mysql <mysql-d>` | :ref:`oracle <oracle-d>` | :ref:`firebird <firebird-d>` | mssql |
|
||||
| | | | | | | |
|
||||
+=========================================================+==========================+==============================+========================+===========================+===============================+=======+
|
||||
| :ref:`ALTER TABLE RENAME TABLE <table-rename>` | yes | yes | yes | yes | no | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`ALTER TABLE RENAME COLUMN <column-alter>` | yes | yes | yes | yes | yes | |
|
||||
| | (workaround) [#1]_ | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`ALTER TABLE ADD COLUMN <column-create>` | yes | yes | yes | yes | yes | |
|
||||
| | (with limitations) [#2]_ | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`ALTER TABLE DROP COLUMN <column-drop>` | yes | yes | yes | yes | yes | |
|
||||
| | (workaround) [#1]_ | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`ALTER TABLE ALTER COLUMN <column-alter>` | no | yes | yes | yes | yes [#4]_ | |
|
||||
| | | | | (with limitations) [#3]_ | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`ALTER TABLE ADD CONSTRAINT <constraint-tutorial>` | no | yes | yes | yes | yes | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`ALTER TABLE DROP CONSTRAINT <constraint-tutorial>`| no | yes | yes | yes | yes | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
| :ref:`RENAME INDEX <index-rename>` | no | yes | no | yes | yes | |
|
||||
| | | | | | | |
|
||||
+---------------------------------------------------------+--------------------------+------------------------------+------------------------+---------------------------+-------------------------------+-------+
|
||||
|
||||
|
||||
.. [#1] Table is renamed to temporary table, new table is created followed by INSERT statements.
|
||||
.. [#2] Visit http://www.sqlite.org/lang_altertable.html for more information.
|
||||
.. [#3] You can not change datatype or rename column if table has NOT NULL data, see http://blogs.x2line.com/al/archive/2005/08/30/1231.aspx for more information.
|
||||
|
||||
.. [#4] Changing nullable is not supported
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
@ -189,7 +189,7 @@ class ANSISchemaChanger(AlterTableVisitor, SchemaGenerator):
|
||||
"""Starts ALTER COLUMN"""
|
||||
self.start_alter_table(table)
|
||||
# TODO: use preparer.format_column
|
||||
self.append("ALTER COLUMN %s " % self.preparer.quote_identifier(col_name))
|
||||
self.append("ALTER COLUMN %s " % self.preparer.quote(col_name, table.quote))
|
||||
|
||||
def _visit_column_nullable(self, table, col_name, delta):
|
||||
nullable = delta['nullable']
|
||||
@ -306,9 +306,12 @@ class ANSIConstraintDropper(ANSIConstraintCommon, SchemaDropper):
|
||||
constraint.name = self.get_constraint_name(constraint)
|
||||
self.append(self.preparer.format_constraint(constraint))
|
||||
if constraint.cascade:
|
||||
self.append(" CASCADE")
|
||||
self.cascade_constraint(constraint)
|
||||
self.execute()
|
||||
|
||||
def cascade_constraint(self, constraint):
|
||||
self.append(" CASCADE")
|
||||
|
||||
|
||||
class ANSIDialect(DefaultDialect):
|
||||
columngenerator = ANSIColumnGenerator
|
||||
|
@ -39,6 +39,7 @@ class ConstraintChangeset(object):
|
||||
:keyword:`None` the instance's engine will be used
|
||||
:type engine: :class:`sqlalchemy.engine.base.Engine`
|
||||
"""
|
||||
# TODO: set the parent here instead of in __init__
|
||||
self.__do_imports('constraintgenerator', *a, **kw)
|
||||
|
||||
def drop(self, *a, **kw):
|
||||
|
62
migrate/changeset/databases/firebird.py
Normal file
62
migrate/changeset/databases/firebird.py
Normal file
@ -0,0 +1,62 @@
|
||||
"""
|
||||
Firebird database specific implementations of changeset classes.
|
||||
"""
|
||||
from sqlalchemy.databases import firebird as sa_base
|
||||
|
||||
from migrate.changeset import ansisql, exceptions
|
||||
|
||||
|
||||
FBSchemaGenerator = sa_base.FBSchemaGenerator
|
||||
|
||||
|
||||
class FBColumnGenerator(FBSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
"""Firebird column generator implementation."""
|
||||
|
||||
|
||||
class FBColumnDropper(ansisql.ANSIColumnDropper):
|
||||
"""Firebird column dropper implementation."""
|
||||
|
||||
def visit_column(self, column):
|
||||
table = self.start_alter_table(column)
|
||||
self.append('DROP %s' % self.preparer.format_column(column))
|
||||
self.execute()
|
||||
|
||||
|
||||
class FBSchemaChanger(ansisql.ANSISchemaChanger):
|
||||
"""Firebird schema changer implementation."""
|
||||
|
||||
def visit_table(self, table):
|
||||
"""Rename table not supported"""
|
||||
raise exceptions.NotSupportedError(
|
||||
"Firebird does not support renaming tables.")
|
||||
|
||||
def _visit_column_name(self, table, col_name, delta):
|
||||
new_name = delta['name']
|
||||
self.start_alter_table(table)
|
||||
self.append('ALTER COLUMN %s TO %s' % ((col_name), (new_name)))
|
||||
|
||||
def _visit_column_nullable(self, table, col_name, delta):
|
||||
"""Changing NULL is not supported"""
|
||||
# TODO: http://www.firebirdfaq.org/faq103/
|
||||
raise exceptions.NotSupportedError(
|
||||
"Firebird does not support altering NULL bevahior.")
|
||||
|
||||
|
||||
class FBConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
"""Firebird constraint generator implementation."""
|
||||
|
||||
|
||||
class FBConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
"""Firebird constaint dropper implementation."""
|
||||
|
||||
def cascade_constraint(self, constraint):
|
||||
raise exceptions.NotSupportedError(
|
||||
"Firebird does not support cascading constraints")
|
||||
|
||||
|
||||
class FBDialect(ansisql.ANSIDialect):
|
||||
columngenerator = FBColumnGenerator
|
||||
columndropper = FBColumnDropper
|
||||
schemachanger = FBSchemaChanger
|
||||
constraintgenerator = FBConstraintGenerator
|
||||
constraintdropper = FBConstraintDropper
|
@ -4,7 +4,11 @@
|
||||
import sqlalchemy as sa
|
||||
|
||||
from migrate.changeset import ansisql
|
||||
from migrate.changeset.databases import sqlite, postgres, mysql, oracle
|
||||
from migrate.changeset.databases import (sqlite,
|
||||
postgres,
|
||||
mysql,
|
||||
oracle,
|
||||
firebird)
|
||||
|
||||
|
||||
# Map SA dialects to the corresponding Migrate extensions
|
||||
@ -14,6 +18,7 @@ DIALECTS = {
|
||||
sa.databases.postgres.PGDialect: postgres.PGDialect,
|
||||
sa.databases.mysql.MySQLDialect: mysql.MySQLDialect,
|
||||
sa.databases.oracle.OracleDialect: oracle.OracleDialect,
|
||||
sa.databases.firebird.FBDialect: firebird.FBDialect,
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ from sqlalchemy.util import OrderedDict
|
||||
|
||||
__all__ = ['databases', 'operations']
|
||||
|
||||
databases = ('sqlite', 'postgres', 'mysql', 'oracle', 'mssql')
|
||||
databases = ('sqlite', 'postgres', 'mysql', 'oracle', 'mssql', 'firebird')
|
||||
|
||||
# Map operation names to function names
|
||||
operations = OrderedDict()
|
||||
|
@ -163,7 +163,7 @@ class ControlledSchema(object):
|
||||
|
||||
table = Table(
|
||||
tname, meta,
|
||||
Column('repository_id', String(255), primary_key=True),
|
||||
Column('repository_id', String(250), primary_key=True),
|
||||
Column('repository_path', Text),
|
||||
Column('version', Integer), )
|
||||
|
||||
|
@ -183,7 +183,7 @@ class TestAddDropColumn(fixture.DB):
|
||||
@fixture.usedb(not_supported='sqlite')
|
||||
def test_pk(self):
|
||||
"""Can create columns with primary key"""
|
||||
col = Column('data', Integer)
|
||||
col = Column('data', Integer, nullable=False)
|
||||
self.assertRaises(changeset.exceptions.InvalidConstraintError,
|
||||
col.create, self.table, primary_key_name=True)
|
||||
col.create(self.table, primary_key_name='data_pkey')
|
||||
@ -192,7 +192,8 @@ class TestAddDropColumn(fixture.DB):
|
||||
self.table.insert(values={'data': 4}).execute()
|
||||
try:
|
||||
self.table.insert(values={'data': 4}).execute()
|
||||
except sqlalchemy.exc.IntegrityError:
|
||||
except (sqlalchemy.exc.IntegrityError,
|
||||
sqlalchemy.exc.ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
@ -211,7 +212,8 @@ class TestAddDropColumn(fixture.DB):
|
||||
self.table.insert(values={'data': 5}).execute()
|
||||
try:
|
||||
self.table.insert(values={'data': 3}).execute()
|
||||
except sqlalchemy.exc.IntegrityError:
|
||||
except (sqlalchemy.exc.IntegrityError,
|
||||
sqlalchemy.exc.ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
@ -230,7 +232,8 @@ class TestAddDropColumn(fixture.DB):
|
||||
self.table.insert(values={'data': 5}).execute()
|
||||
try:
|
||||
self.table.insert(values={'data': 5}).execute()
|
||||
except sqlalchemy.exc.IntegrityError:
|
||||
except (sqlalchemy.exc.IntegrityError,
|
||||
sqlalchemy.exc.ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
@ -249,11 +252,13 @@ class TestAddDropColumn(fixture.DB):
|
||||
self.table.insert(values={'data': 5}).execute()
|
||||
try:
|
||||
self.table.insert(values={'data': 5}).execute()
|
||||
except sqlalchemy.exc.IntegrityError:
|
||||
except (sqlalchemy.exc.IntegrityError,
|
||||
sqlalchemy.exc.ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
Index('ix_data', col).drop(bind=self.engine)
|
||||
col.drop()
|
||||
|
||||
@fixture.usedb()
|
||||
@ -272,6 +277,7 @@ class TestAddDropColumn(fixture.DB):
|
||||
# TODO: test that if column is appended on creation and removed on deletion
|
||||
# TODO: test column.alter with all changes at one time
|
||||
# TODO: test quoting
|
||||
# TODO: test drop default
|
||||
|
||||
|
||||
class TestRename(fixture.DB):
|
||||
@ -283,7 +289,7 @@ class TestRename(fixture.DB):
|
||||
super(TestRename, self)._setup(url)
|
||||
self.meta.bind = self.engine
|
||||
|
||||
@fixture.usedb()
|
||||
@fixture.usedb(not_supported='firebird')
|
||||
def test_rename_table(self):
|
||||
"""Tables can be renamed"""
|
||||
c_name = 'col_1'
|
||||
@ -463,21 +469,29 @@ class TestColumnChange(fixture.DB):
|
||||
self.table.c.data.alter(Column('data', String(42)))
|
||||
self.refresh_table(self.table.name)
|
||||
self.assert_(isinstance(self.table.c.data.type, String))
|
||||
self.assertEquals(self.table.c.data.type.length, 42)
|
||||
if self.engine.name == 'firebird':
|
||||
self.assertEquals(self.table.c.data.type.length, 42 * 4)
|
||||
else:
|
||||
self.assertEquals(self.table.c.data.type.length, 42)
|
||||
|
||||
# Just the new type
|
||||
self.table.c.data.alter(type=String(21))
|
||||
self.table.c.data.alter(type=String(43))
|
||||
self.refresh_table(self.table.name)
|
||||
self.assert_(isinstance(self.table.c.data.type, String))
|
||||
self.assertEquals(self.table.c.data.type.length, 21)
|
||||
if self.engine.name == 'firebird':
|
||||
self.assertEquals(self.table.c.data.type.length, 43 * 4)
|
||||
else:
|
||||
self.assertEquals(self.table.c.data.type.length, 43)
|
||||
|
||||
# Different type
|
||||
self.assert_(isinstance(self.table.c.id.type, Integer))
|
||||
self.assertEquals(self.table.c.id.nullable, False)
|
||||
self.table.c.id.alter(type=String(20))
|
||||
self.assertEquals(self.table.c.id.nullable, False)
|
||||
self.refresh_table(self.table.name)
|
||||
self.assert_(isinstance(self.table.c.id.type, String))
|
||||
|
||||
if not self.engine.name == 'firebird':
|
||||
self.table.c.id.alter(type=String(20))
|
||||
self.assertEquals(self.table.c.id.nullable, False)
|
||||
self.refresh_table(self.table.name)
|
||||
self.assert_(isinstance(self.table.c.id.type, String))
|
||||
|
||||
@fixture.usedb()
|
||||
def test_default(self):
|
||||
@ -511,14 +525,14 @@ class TestColumnChange(fixture.DB):
|
||||
self.assert_(row['data'] is None, row['data'])
|
||||
|
||||
|
||||
@fixture.usedb()
|
||||
@fixture.usedb(not_supported='firebird')
|
||||
def test_null(self):
|
||||
"""Can change a column's null constraint"""
|
||||
self.assertEquals(self.table.c.data.nullable, True)
|
||||
|
||||
# Column object
|
||||
self.table.c.data.alter(Column('data', String(40), nullable=False))
|
||||
self.table.nullable=None
|
||||
self.table.nullable = None
|
||||
self.refresh_table(self.table.name)
|
||||
self.assertEquals(self.table.c.data.nullable, False)
|
||||
|
||||
|
@ -6,6 +6,7 @@ from sqlalchemy.util import *
|
||||
from sqlalchemy.exc import *
|
||||
|
||||
from migrate.changeset import *
|
||||
from migrate.changeset.exceptions import *
|
||||
|
||||
from test import fixture
|
||||
|
||||
@ -31,8 +32,8 @@ class CommonTestConstraint(fixture.DB):
|
||||
self.meta = MetaData(self.engine)
|
||||
self.tablename = 'mytable'
|
||||
self.table = Table(self.tablename, self.meta,
|
||||
Column('id', Integer),
|
||||
Column('fkey', Integer),
|
||||
Column('id', Integer, nullable=False),
|
||||
Column('fkey', Integer, nullable=False),
|
||||
mysql_engine='InnoDB')
|
||||
if self.engine.has_table(self.table.name):
|
||||
self.table.drop()
|
||||
@ -49,20 +50,21 @@ class TestConstraint(CommonTestConstraint):
|
||||
|
||||
def _define_pk(self, *cols):
|
||||
# Add a pk by creating a PK constraint
|
||||
pk = PrimaryKeyConstraint(table=self.table, *cols)
|
||||
self.assertEquals(list(pk.columns), list(cols))
|
||||
if self.url.startswith('oracle'):
|
||||
if (self.engine.name in ('oracle', 'firebird')):
|
||||
# Can't drop Oracle PKs without an explicit name
|
||||
pk.name = 'fgsfds'
|
||||
pk = PrimaryKeyConstraint(table=self.table, name='temp_pk_key', *cols)
|
||||
else:
|
||||
pk = PrimaryKeyConstraint(table=self.table, *cols)
|
||||
self.assertEquals(list(pk.columns), list(cols))
|
||||
pk.create()
|
||||
self.refresh_table()
|
||||
if not self.url.startswith('sqlite'):
|
||||
self.assertEquals(list(self.table.primary_key), list(cols))
|
||||
|
||||
# Drop the PK constraint
|
||||
if not self.url.startswith('oracle'):
|
||||
# Apparently Oracle PK names aren't introspected
|
||||
pk.name = self.table.primary_key.name
|
||||
#if (self.engine.name in ('oracle', 'firebird')):
|
||||
# # Apparently Oracle PK names aren't introspected
|
||||
# pk.name = self.table.primary_key.name
|
||||
pk.drop()
|
||||
self.refresh_table()
|
||||
self.assertEquals(len(self.table.primary_key), 0)
|
||||
@ -113,18 +115,23 @@ class TestConstraint(CommonTestConstraint):
|
||||
@fixture.usedb()
|
||||
def test_define_pk_multi(self):
|
||||
"""Multicolumn PK constraints can be defined, created, and dropped"""
|
||||
#self.engine.echo=True
|
||||
self._define_pk(self.table.c.id, self.table.c.fkey)
|
||||
|
||||
@fixture.usedb()
|
||||
def test_drop_cascade(self):
|
||||
"""Drop constraint cascaded"""
|
||||
|
||||
pk = PrimaryKeyConstraint('fkey', table=self.table, name="id_pkey")
|
||||
pk.create()
|
||||
self.refresh_table()
|
||||
|
||||
# Drop the PK constraint forcing cascade
|
||||
pk.drop(cascade=True)
|
||||
try:
|
||||
pk.drop(cascade=True)
|
||||
except NotSupportedError:
|
||||
if self.engine.name == 'firebird':
|
||||
pass
|
||||
|
||||
# TODO: add real assertion if it was added
|
||||
|
||||
@fixture.usedb(supported=['mysql'])
|
||||
@ -149,10 +156,10 @@ class TestConstraint(CommonTestConstraint):
|
||||
cons.create()
|
||||
self.refresh_table()
|
||||
|
||||
self.table.insert(values={'id': 4}).execute()
|
||||
self.table.insert(values={'id': 4, 'fkey': 1}).execute()
|
||||
try:
|
||||
self.table.insert(values={'id': 1}).execute()
|
||||
except IntegrityError:
|
||||
self.table.insert(values={'id': 1, 'fkey': 1}).execute()
|
||||
except (IntegrityError, ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
@ -160,8 +167,8 @@ class TestConstraint(CommonTestConstraint):
|
||||
# Remove the name, drop the constraint; it should succeed
|
||||
cons.drop()
|
||||
self.refresh_table()
|
||||
self.table.insert(values={'id': 2}).execute()
|
||||
self.table.insert(values={'id': 1}).execute()
|
||||
self.table.insert(values={'id': 2, 'fkey': 2}).execute()
|
||||
self.table.insert(values={'id': 1, 'fkey': 2}).execute()
|
||||
|
||||
|
||||
class TestAutoname(CommonTestConstraint):
|
||||
@ -170,7 +177,7 @@ class TestAutoname(CommonTestConstraint):
|
||||
"""
|
||||
level = fixture.DB.CONNECT
|
||||
|
||||
@fixture.usedb(not_supported='oracle')
|
||||
@fixture.usedb(not_supported=['oracle', 'firebird'])
|
||||
def test_autoname_pk(self):
|
||||
"""PrimaryKeyConstraints can guess their name if None is given"""
|
||||
# Don't supply a name; it should create one
|
||||
@ -197,7 +204,7 @@ class TestAutoname(CommonTestConstraint):
|
||||
cons.name = None
|
||||
cons.drop()
|
||||
|
||||
@fixture.usedb(not_supported=['oracle', 'sqlite'])
|
||||
@fixture.usedb(not_supported=['oracle', 'sqlite', 'firebird'])
|
||||
def test_autoname_fk(self):
|
||||
"""ForeignKeyConstraints can guess their name if None is given"""
|
||||
cons = PrimaryKeyConstraint(self.table.c.id)
|
||||
@ -230,13 +237,12 @@ class TestAutoname(CommonTestConstraint):
|
||||
cons = CheckConstraint('id > 3', columns=[self.table.c.id])
|
||||
cons.create()
|
||||
self.refresh_table()
|
||||
|
||||
|
||||
if not self.engine.name == 'mysql':
|
||||
self.table.insert(values={'id': 4}).execute()
|
||||
self.table.insert(values={'id': 4, 'fkey': 1}).execute()
|
||||
try:
|
||||
self.table.insert(values={'id': 1}).execute()
|
||||
except IntegrityError:
|
||||
self.table.insert(values={'id': 1, 'fkey': 2}).execute()
|
||||
except (IntegrityError, ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
@ -245,8 +251,8 @@ class TestAutoname(CommonTestConstraint):
|
||||
cons.name = None
|
||||
cons.drop()
|
||||
self.refresh_table()
|
||||
self.table.insert(values={'id': 2}).execute()
|
||||
self.table.insert(values={'id': 1}).execute()
|
||||
self.table.insert(values={'id': 2, 'fkey': 2}).execute()
|
||||
self.table.insert(values={'id': 1, 'fkey': 3}).execute()
|
||||
|
||||
@fixture.usedb(not_supported=['oracle', 'sqlite'])
|
||||
def test_autoname_unique(self):
|
||||
@ -254,12 +260,12 @@ class TestAutoname(CommonTestConstraint):
|
||||
cons = UniqueConstraint(self.table.c.fkey)
|
||||
cons.create()
|
||||
self.refresh_table()
|
||||
|
||||
|
||||
self.table.insert(values={'fkey': 4}).execute()
|
||||
self.table.insert(values={'fkey': 4, 'id': 1}).execute()
|
||||
try:
|
||||
self.table.insert(values={'fkey': 4}).execute()
|
||||
except IntegrityError:
|
||||
self.table.insert(values={'fkey': 4, 'id': 2}).execute()
|
||||
except (sqlalchemy.exc.IntegrityError,
|
||||
sqlalchemy.exc.ProgrammingError):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
@ -268,5 +274,5 @@ class TestAutoname(CommonTestConstraint):
|
||||
cons.name = None
|
||||
cons.drop()
|
||||
self.refresh_table()
|
||||
self.table.insert(values={'fkey': 4}).execute()
|
||||
self.table.insert(values={'fkey': 4}).execute()
|
||||
self.table.insert(values={'fkey': 4, 'id': 2}).execute()
|
||||
self.table.insert(values={'fkey': 4, 'id': 1}).execute()
|
||||
|
@ -139,20 +139,20 @@ class TestSchemaDiff(fixture.DB):
|
||||
# Not even using sqlalchemy.PassiveDefault helps because we're doing explicit column select.
|
||||
self.engine.execute(self.table.delete(), id=dataId)
|
||||
|
||||
# Change column nullable in model.
|
||||
self.meta.remove(self.table)
|
||||
self.table = Table(self.table_name,self.meta,
|
||||
Column('id',Integer(),primary_key=True),
|
||||
Column('name',UnicodeText(length=None)),
|
||||
Column('data2',String(255),nullable=False),
|
||||
)
|
||||
assertDiff(True, [], [], [self.table_name]) # TODO test nullable diff
|
||||
|
||||
# Apply latest model changes and find no more diffs.
|
||||
self._applyLatestModel()
|
||||
assertDiff(False, [], [], [])
|
||||
|
||||
# Remove table from model.
|
||||
self.meta.remove(self.table)
|
||||
assertDiff(True, [], [self.table_name], [])
|
||||
|
||||
if not self.engine.name == 'firebird':
|
||||
# Change column nullable in model.
|
||||
self.meta.remove(self.table)
|
||||
self.table = Table(self.table_name,self.meta,
|
||||
Column('id',Integer(),primary_key=True),
|
||||
Column('name',UnicodeText(length=None)),
|
||||
Column('data2',String(255),nullable=False),
|
||||
)
|
||||
assertDiff(True, [], [], [self.table_name]) # TODO test nullable diff
|
||||
|
||||
# Apply latest model changes and find no more diffs.
|
||||
self._applyLatestModel()
|
||||
assertDiff(False, [], [], [])
|
||||
|
||||
# Remove table from model.
|
||||
self.meta.remove(self.table)
|
||||
assertDiff(True, [], [self.table_name], [])
|
||||
|
Loading…
x
Reference in New Issue
Block a user