| 1 | """ |
|---|
| 2 | `SQLite`_ database specific implementations of changeset classes. |
|---|
| 3 | |
|---|
| 4 | .. _`SQLite`: http://www.sqlite.org/ |
|---|
| 5 | """ |
|---|
| 6 | from migrate.changeset import ansisql, constraint, exceptions |
|---|
| 7 | from sqlalchemy.databases import sqlite as sa_base |
|---|
| 8 | from sqlalchemy import Table, MetaData |
|---|
| 9 | #import sqlalchemy as sa |
|---|
| 10 | |
|---|
| 11 | SQLiteSchemaGenerator = sa_base.SQLiteSchemaGenerator |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | class SQLiteHelper(object): |
|---|
| 15 | |
|---|
| 16 | def visit_column(self, param): |
|---|
| 17 | try: |
|---|
| 18 | table = self._to_table(param.table) |
|---|
| 19 | except: |
|---|
| 20 | table = self._to_table(param) |
|---|
| 21 | raise |
|---|
| 22 | table_name = self._to_table_name(table) |
|---|
| 23 | self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name) |
|---|
| 24 | self.execute() |
|---|
| 25 | |
|---|
| 26 | insertion_string = self._modify_table(table, param) |
|---|
| 27 | |
|---|
| 28 | table.create() |
|---|
| 29 | self.append(insertion_string % {'table_name': table_name}) |
|---|
| 30 | self.execute() |
|---|
| 31 | self.append('DROP TABLE migration_tmp') |
|---|
| 32 | self.execute() |
|---|
| 33 | |
|---|
| 34 | |
|---|
| 35 | class SQLiteColumnGenerator(SQLiteSchemaGenerator, |
|---|
| 36 | ansisql.ANSIColumnGenerator): |
|---|
| 37 | pass |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | class SQLiteColumnDropper(SQLiteHelper, ansisql.ANSIColumnDropper): |
|---|
| 41 | |
|---|
| 42 | def _modify_table(self, table, column): |
|---|
| 43 | del table.columns[column.name] |
|---|
| 44 | columns = ','.join([c.name for c in table.columns]) |
|---|
| 45 | return 'INSERT INTO %(table_name)s SELECT ' + columns + \ |
|---|
| 46 | ' from migration_tmp' |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger): |
|---|
| 50 | |
|---|
| 51 | def _not_supported(self, op): |
|---|
| 52 | raise exceptions.NotSupportedError("SQLite does not support " |
|---|
| 53 | "%s; see http://www.sqlite.org/lang_altertable.html"%op) |
|---|
| 54 | |
|---|
| 55 | def _modify_table(self, table, delta): |
|---|
| 56 | column = table.columns[delta.current_name] |
|---|
| 57 | for k, v in delta.items(): |
|---|
| 58 | setattr(column, k, v) |
|---|
| 59 | return 'INSERT INTO %(table_name)s SELECT * from migration_tmp' |
|---|
| 60 | |
|---|
| 61 | def visit_index(self, param): |
|---|
| 62 | self._not_supported('ALTER INDEX') |
|---|
| 63 | |
|---|
| 64 | def _do_quote_column_identifier(self, identifier): |
|---|
| 65 | return '"%s"'%identifier |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator): |
|---|
| 69 | |
|---|
| 70 | def visit_migrate_primary_key_constraint(self, constraint): |
|---|
| 71 | tmpl = "CREATE UNIQUE INDEX %s ON %s ( %s )" |
|---|
| 72 | cols = ','.join([c.name for c in constraint.columns]) |
|---|
| 73 | tname = constraint.table.name |
|---|
| 74 | name = constraint.name |
|---|
| 75 | msg = tmpl % (name, tname, cols) |
|---|
| 76 | self.append(msg) |
|---|
| 77 | self.execute() |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | class SQLiteFKGenerator(SQLiteSchemaChanger, ansisql.ANSIFKGenerator): |
|---|
| 81 | def visit_column(self, column): |
|---|
| 82 | """Create foreign keys for a column (table already exists); #32""" |
|---|
| 83 | |
|---|
| 84 | if self.fk: |
|---|
| 85 | self._not_supported("ALTER TABLE ADD FOREIGN KEY") |
|---|
| 86 | |
|---|
| 87 | if self.buffer.getvalue() !='': |
|---|
| 88 | self.execute() |
|---|
| 89 | |
|---|
| 90 | |
|---|
| 91 | class SQLiteConstraintDropper(ansisql.ANSIColumnDropper): |
|---|
| 92 | |
|---|
| 93 | def visit_migrate_primary_key_constraint(self, constraint): |
|---|
| 94 | tmpl = "DROP INDEX %s " |
|---|
| 95 | name = constraint.name |
|---|
| 96 | msg = tmpl % (name) |
|---|
| 97 | self.append(msg) |
|---|
| 98 | self.execute() |
|---|
| 99 | |
|---|
| 100 | |
|---|
| 101 | class SQLiteDialect(ansisql.ANSIDialect): |
|---|
| 102 | columngenerator = SQLiteColumnGenerator |
|---|
| 103 | columndropper = SQLiteColumnDropper |
|---|
| 104 | schemachanger = SQLiteSchemaChanger |
|---|
| 105 | constraintgenerator = SQLiteConstraintGenerator |
|---|
| 106 | constraintdropper = SQLiteConstraintDropper |
|---|
| 107 | columnfkgenerator = SQLiteFKGenerator |
|---|