diff options
author | jan.dittberner <unknown> | 2008-02-06 18:39:07 +0000 |
---|---|---|
committer | jan.dittberner <unknown> | 2008-02-06 18:39:07 +0000 |
commit | 2cfe1fc31c0dfa8241200f635d8e7f6cfce2b507 (patch) | |
tree | 69541da758ab44652badc59ec0ce659364bdfe7f /migrate/changeset/databases | |
download | sqlalchemy-migrate-2cfe1fc31c0dfa8241200f635d8e7f6cfce2b507.tar.gz |
moved trunk, branches and tags to project root
fixes Issue #5
Diffstat (limited to 'migrate/changeset/databases')
-rw-r--r-- | migrate/changeset/databases/__init__.py | 6 | ||||
-rw-r--r-- | migrate/changeset/databases/mysql.py | 61 | ||||
-rw-r--r-- | migrate/changeset/databases/oracle.py | 79 | ||||
-rw-r--r-- | migrate/changeset/databases/postgres.py | 23 | ||||
-rw-r--r-- | migrate/changeset/databases/sqlite.py | 49 | ||||
-rw-r--r-- | migrate/changeset/databases/visitor.py | 20 |
6 files changed, 238 insertions, 0 deletions
diff --git a/migrate/changeset/databases/__init__.py b/migrate/changeset/databases/__init__.py new file mode 100644 index 0000000..34b4f9d --- /dev/null +++ b/migrate/changeset/databases/__init__.py @@ -0,0 +1,6 @@ +__all__=[ +'postgres', +'sqlite', +'mysql', +'oracle', +] diff --git a/migrate/changeset/databases/mysql.py b/migrate/changeset/databases/mysql.py new file mode 100644 index 0000000..3611f66 --- /dev/null +++ b/migrate/changeset/databases/mysql.py @@ -0,0 +1,61 @@ +from migrate.changeset import ansisql,exceptions +from sqlalchemy.databases import mysql as sa_base +#import sqlalchemy as sa + +MySQLSchemaGenerator = sa_base.MySQLSchemaGenerator + +class MySQLColumnGenerator(MySQLSchemaGenerator,ansisql.ANSIColumnGenerator): + pass +class MySQLColumnDropper(ansisql.ANSIColumnDropper): + pass +class MySQLSchemaChanger(MySQLSchemaGenerator,ansisql.ANSISchemaChanger): + def visit_column(self,delta): + keys = delta.keys() + if 'type' in keys or 'nullable' in keys or 'name' in keys: + self._run_subvisit(delta,self._visit_column_change) + if 'default' in keys: + # Column name might have changed above + col_name = delta.get('name',delta.current_name) + self._run_subvisit(delta,self._visit_column_default,col_name=col_name) + def _visit_column_change(self,table_name,col_name,delta): + if not hasattr(delta,'result_column'): + # Mysql needs the whole column definition, not just a lone name/type + raise exceptions.NotSupportedError( + "A column object is required to do this") + + column = delta.result_column + colspec = self.get_column_specification(column) + self.start_alter_table(table_name) + self.append("CHANGE COLUMN ") + self.append(col_name) + self.append(' ') + self.append(colspec) + def visit_index(self,param): + # If MySQL can do this, I can't find how + raise exceptions.NotSupportedError("MySQL cannot rename indexes") +class MySQLConstraintGenerator(ansisql.ANSIConstraintGenerator): + pass +class MySQLConstraintDropper(ansisql.ANSIConstraintDropper): + #def visit_constraint(self,constraint): + # if isinstance(constraint,sqlalchemy.schema.PrimaryKeyConstraint): + # return self._visit_constraint_pk(constraint) + # elif isinstance(constraint,sqlalchemy.schema.ForeignKeyConstraint): + # return self._visit_constraint_fk(constraint) + # return super(MySQLConstraintDropper,self).visit_constraint(constraint) + def visit_migrate_primary_key_constraint(self,constraint): + self.start_alter_table(constraint) + self.append("DROP PRIMARY KEY") + self.execute() + + def visit_migrate_foreign_key_constraint(self,constraint): + self.start_alter_table(constraint) + self.append("DROP FOREIGN KEY ") + self.append(constraint.name) + self.execute() + +class MySQLDialect(ansisql.ANSIDialect): + columngenerator = MySQLColumnGenerator + columndropper = MySQLColumnDropper + schemachanger = MySQLSchemaChanger + constraintgenerator = MySQLConstraintGenerator + constraintdropper = MySQLConstraintDropper diff --git a/migrate/changeset/databases/oracle.py b/migrate/changeset/databases/oracle.py new file mode 100644 index 0000000..f27245c --- /dev/null +++ b/migrate/changeset/databases/oracle.py @@ -0,0 +1,79 @@ +from migrate.changeset import ansisql,exceptions +from sqlalchemy.databases import oracle as sa_base +import sqlalchemy as sa + +OracleSchemaGenerator = sa_base.OracleSchemaGenerator + +class OracleColumnGenerator(OracleSchemaGenerator,ansisql.ANSIColumnGenerator): + pass +class OracleColumnDropper(ansisql.ANSIColumnDropper): + pass +class OracleSchemaChanger(OracleSchemaGenerator,ansisql.ANSISchemaChanger): + def get_column_specification(self,column,**kwargs): + # Ignore the NOT NULL generated + override_nullable = kwargs.pop('override_nullable',None) + if override_nullable: + orig = column.nullable + column.nullable = True + ret=super(OracleSchemaChanger,self).get_column_specification(column,**kwargs) + if override_nullable: + column.nullable = orig + return ret + + def visit_column(self,delta): + keys = delta.keys() + if 'type' in keys or 'nullable' in keys or 'default' in keys: + self._run_subvisit(delta,self._visit_column_change) + if 'name' in keys: + self._run_subvisit(delta,self._visit_column_name) + def _visit_column_change(self,table_name,col_name,delta): + if not hasattr(delta,'result_column'): + # Oracle needs the whole column definition, not just a lone name/type + raise exceptions.NotSupportedError( + "A column object is required to do this") + + column = delta.result_column + # Oracle cannot drop a default once created, but it can set it to null. + # We'll do that if default=None + # http://forums.oracle.com/forums/message.jspa?messageID=1273234#1273234 + dropdefault_hack = (column.default is None and 'default' in delta.keys()) + # Oracle apparently doesn't like it when we say "not null" if the + # column's already not null. Fudge it, so we don't need a new function + notnull_hack = ((not column.nullable) and ('nullable' not in delta.keys())) + # We need to specify NULL if we're removing a NOT NULL constraint + null_hack = (column.nullable and ('nullable' in delta.keys())) + + + if dropdefault_hack: + column.default = sa.PassiveDefault(sa.func.null()) + if notnull_hack: + column.nullable = True + colspec=self.get_column_specification(column,override_nullable=null_hack) + if null_hack: + colspec += ' NULL' + if notnull_hack: + column.nullable = False + if dropdefault_hack: + column.default = None + + self.start_alter_table(table_name) + self.append("MODIFY ") + self.append(colspec) +class OracleConstraintCommon(object): + def get_constraint_name(self,cons): + # Oracle constraints can't guess their name like other DBs + if not cons.name: + raise exceptions.NotSupportedError( + "Oracle constraint names must be explicitly stated") + return cons.name +class OracleConstraintGenerator(OracleConstraintCommon,ansisql.ANSIConstraintGenerator): + pass +class OracleConstraintDropper(OracleConstraintCommon,ansisql.ANSIConstraintDropper): + pass + +class OracleDialect(ansisql.ANSIDialect): + columngenerator = OracleColumnGenerator + columndropper = OracleColumnDropper + schemachanger = OracleSchemaChanger + constraintgenerator = OracleConstraintGenerator + constraintdropper = OracleConstraintDropper diff --git a/migrate/changeset/databases/postgres.py b/migrate/changeset/databases/postgres.py new file mode 100644 index 0000000..adbd3fb --- /dev/null +++ b/migrate/changeset/databases/postgres.py @@ -0,0 +1,23 @@ +from migrate.changeset import ansisql +from sqlalchemy.databases import postgres as sa_base +#import sqlalchemy as sa + +PGSchemaGenerator = sa_base.PGSchemaGenerator + +class PGColumnGenerator(PGSchemaGenerator,ansisql.ANSIColumnGenerator): + pass +class PGColumnDropper(ansisql.ANSIColumnDropper): + pass +class PGSchemaChanger(ansisql.ANSISchemaChanger): + pass +class PGConstraintGenerator(ansisql.ANSIConstraintGenerator): + pass +class PGConstraintDropper(ansisql.ANSIConstraintDropper): + pass + +class PGDialect(ansisql.ANSIDialect): + columngenerator = PGColumnGenerator + columndropper = PGColumnDropper + schemachanger = PGSchemaChanger + constraintgenerator = PGConstraintGenerator + constraintdropper = PGConstraintDropper diff --git a/migrate/changeset/databases/sqlite.py b/migrate/changeset/databases/sqlite.py new file mode 100644 index 0000000..5893201 --- /dev/null +++ b/migrate/changeset/databases/sqlite.py @@ -0,0 +1,49 @@ +from migrate.changeset import ansisql,constraint,exceptions +from sqlalchemy.databases import sqlite as sa_base +#import sqlalchemy as sa + +SQLiteSchemaGenerator = sa_base.SQLiteSchemaGenerator + +class SQLiteColumnGenerator(SQLiteSchemaGenerator,ansisql.ANSIColumnGenerator): + pass +class SQLiteColumnDropper(ansisql.ANSIColumnDropper): + def visit_column(self,column): + raise exceptions.NotSupportedError("SQLite does not support " + "DROP COLUMN; see http://www.sqlite.org/lang_altertable.html") +class SQLiteSchemaChanger(ansisql.ANSISchemaChanger): + def _not_supported(self,op): + raise exceptions.NotSupportedError("SQLite does not support " + "%s; see http://www.sqlite.org/lang_altertable.html"%op) + def _visit_column_nullable(self,table_name,col_name,delta): + return self._not_supported('ALTER TABLE') + def _visit_column_default(self,table_name,col_name,delta): + return self._not_supported('ALTER TABLE') + def _visit_column_type(self,table_name,col_name,delta): + return self._not_supported('ALTER TABLE') + def _visit_column_name(self,table_name,col_name,delta): + return self._not_supported('ALTER TABLE') + def visit_index(self,param): + self._not_supported('ALTER INDEX') +class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator): + def visit_migrate_primary_key_constraint(self,constraint): + tmpl = "CREATE UNIQUE INDEX %s ON %s ( %s )" + cols = ','.join([c.name for c in constraint.columns]) + tname = constraint.table.name + name = constraint.name + msg = tmpl%(name,tname,cols) + self.append(msg) + self.execute() +class SQLiteConstraintDropper(object): + def visit_migrate_primary_key_constraint(self,constraint): + tmpl = "DROP INDEX %s " + name = constraint.name + msg = tmpl%(name) + self.append(msg) + self.execute() + +class SQLiteDialect(ansisql.ANSIDialect): + columngenerator = SQLiteColumnGenerator + columndropper = SQLiteColumnDropper + schemachanger = SQLiteSchemaChanger + constraintgenerator = SQLiteConstraintGenerator + constraintdropper = SQLiteConstraintDropper diff --git a/migrate/changeset/databases/visitor.py b/migrate/changeset/databases/visitor.py new file mode 100644 index 0000000..437dc68 --- /dev/null +++ b/migrate/changeset/databases/visitor.py @@ -0,0 +1,20 @@ +import sqlalchemy as sa +from migrate.changeset.databases import sqlite,postgres,mysql,oracle +from migrate.changeset import ansisql + +# Map SA dialects to the corresponding Migrate extensions +dialects = { + sa.engine.default.DefaultDialect : ansisql.ANSIDialect, + sa.databases.sqlite.SQLiteDialect : sqlite.SQLiteDialect, + sa.databases.postgres.PGDialect : postgres.PGDialect, + sa.databases.mysql.MySQLDialect : mysql.MySQLDialect, + sa.databases.oracle.OracleDialect : oracle.OracleDialect, +} + +def get_engine_visitor(engine,name): + return get_dialect_visitor(engine.dialect,name) + +def get_dialect_visitor(sa_dialect,name): + sa_dialect_cls = sa_dialect.__class__ + migrate_dialect_cls = dialects[sa_dialect_cls] + return migrate_dialect_cls.visitor(name) |