firebird.py 3.46 KB
Newer Older
1 2 3
"""
   Firebird database specific implementations of changeset classes.
"""
4
from sqlalchemy.databases import firebird as sa_base
5
from sqlalchemy.schema import PrimaryKeyConstraint
6
from migrate import exceptions
7
from migrate.changeset import ansisql
8 9


10
FBSchemaGenerator = sa_base.FBDDLCompiler
11 12 13 14 15 16 17 18 19

class FBColumnGenerator(FBSchemaGenerator, ansisql.ANSIColumnGenerator):
    """Firebird column generator implementation."""


class FBColumnDropper(ansisql.ANSIColumnDropper):
    """Firebird column dropper implementation."""

    def visit_column(self, column):
20 21 22 23 24 25 26 27
        """Firebird supports 'DROP col' instead of 'DROP COLUMN col' syntax

        Drop primary key and unique constraints if dropped column is referencing it."""
        if column.primary_key:
            if column.table.primary_key.columns.contains_column(column):
                column.table.primary_key.drop()
                # TODO: recreate primary key if it references more than this column

28 29 30 31 32 33
        for index in column.table.indexes:
            # "column in index.columns" causes problems as all
            # column objects compare equal and return a SQL expression
            if column.name in [col.name for col in index.columns]:
                index.drop()
                # TODO: recreate index if it references more than this column
34

35 36 37 38 39
        for cons in column.table.constraints:
            if isinstance(cons,PrimaryKeyConstraint):
                # will be deleted only when the column its on
                # is deleted!
                continue
40

41
            should_drop = column.name in cons.columns
42
            if should_drop:
43 44 45 46 47 48 49
                self.start_alter_table(column)
                self.append("DROP CONSTRAINT ")
                self.append(self.preparer.format_constraint(cons))
                self.execute()
            # TODO: recreate unique constraint if it refenrences more than this column

        self.start_alter_table(column)
50 51 52 53 54 55 56 57 58 59 60 61
        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.")

62
    def _visit_column_name(self, table, column, delta):
63
        self.start_alter_table(table)
64
        col_name = self.preparer.quote(delta.current_name)
65 66
        new_name = self.preparer.format_column(delta.result_column)
        self.append('ALTER COLUMN %s TO %s' % (col_name, new_name))
67

68
    def _visit_column_nullable(self, table, column, delta):
69 70 71 72 73 74 75 76 77 78 79 80 81 82
        """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):
83
        """Cascading constraints is not supported"""
84 85 86 87 88 89 90 91 92 93
        raise exceptions.NotSupportedError(
            "Firebird does not support cascading constraints")


class FBDialect(ansisql.ANSIDialect):
    columngenerator = FBColumnGenerator
    columndropper = FBColumnDropper
    schemachanger = FBSchemaChanger
    constraintgenerator = FBConstraintGenerator
    constraintdropper = FBConstraintDropper