comparison rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py @ 833:9753e0907827 beta

added dbmigrate package, added model changes moved out upgrade db command to that package
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 11 Dec 2010 01:54:12 +0100
parents
children 08d2dcd71666
comparison
equal deleted inserted replaced
832:634596f81cfd 833:9753e0907827
1 """
2 `SQLite`_ database specific implementations of changeset classes.
3
4 .. _`SQLite`: http://www.sqlite.org/
5 """
6 from UserDict import DictMixin
7 from copy import copy
8
9 from sqlalchemy.databases import sqlite as sa_base
10
11 from migrate import exceptions
12 from migrate.changeset import ansisql, SQLA_06
13
14
15 if not SQLA_06:
16 SQLiteSchemaGenerator = sa_base.SQLiteSchemaGenerator
17 else:
18 SQLiteSchemaGenerator = sa_base.SQLiteDDLCompiler
19
20 class SQLiteCommon(object):
21
22 def _not_supported(self, op):
23 raise exceptions.NotSupportedError("SQLite does not support "
24 "%s; see http://www.sqlite.org/lang_altertable.html" % op)
25
26
27 class SQLiteHelper(SQLiteCommon):
28
29 def recreate_table(self,table,column=None,delta=None):
30 table_name = self.preparer.format_table(table)
31
32 # we remove all indexes so as not to have
33 # problems during copy and re-create
34 for index in table.indexes:
35 index.drop()
36
37 self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
38 self.execute()
39
40 insertion_string = self._modify_table(table, column, delta)
41
42 table.create()
43 self.append(insertion_string % {'table_name': table_name})
44 self.execute()
45 self.append('DROP TABLE migration_tmp')
46 self.execute()
47
48 def visit_column(self, delta):
49 if isinstance(delta, DictMixin):
50 column = delta.result_column
51 table = self._to_table(delta.table)
52 else:
53 column = delta
54 table = self._to_table(column.table)
55 self.recreate_table(table,column,delta)
56
57 class SQLiteColumnGenerator(SQLiteSchemaGenerator,
58 ansisql.ANSIColumnGenerator,
59 # at the end so we get the normal
60 # visit_column by default
61 SQLiteHelper,
62 SQLiteCommon
63 ):
64 """SQLite ColumnGenerator"""
65
66 def _modify_table(self, table, column, delta):
67 columns = ' ,'.join(map(
68 self.preparer.format_column,
69 [c for c in table.columns if c.name!=column.name]))
70 return ('INSERT INTO %%(table_name)s (%(cols)s) '
71 'SELECT %(cols)s from migration_tmp')%{'cols':columns}
72
73 def visit_column(self,column):
74 if column.foreign_keys:
75 SQLiteHelper.visit_column(self,column)
76 else:
77 super(SQLiteColumnGenerator,self).visit_column(column)
78
79 class SQLiteColumnDropper(SQLiteHelper, ansisql.ANSIColumnDropper):
80 """SQLite ColumnDropper"""
81
82 def _modify_table(self, table, column, delta):
83 columns = ' ,'.join(map(self.preparer.format_column, table.columns))
84 return 'INSERT INTO %(table_name)s SELECT ' + columns + \
85 ' from migration_tmp'
86
87
88 class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
89 """SQLite SchemaChanger"""
90
91 def _modify_table(self, table, column, delta):
92 return 'INSERT INTO %(table_name)s SELECT * from migration_tmp'
93
94 def visit_index(self, index):
95 """Does not support ALTER INDEX"""
96 self._not_supported('ALTER INDEX')
97
98
99 class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator, SQLiteHelper, SQLiteCommon):
100
101 def visit_migrate_primary_key_constraint(self, constraint):
102 tmpl = "CREATE UNIQUE INDEX %s ON %s ( %s )"
103 cols = ', '.join(map(self.preparer.format_column, constraint.columns))
104 tname = self.preparer.format_table(constraint.table)
105 name = self.get_constraint_name(constraint)
106 msg = tmpl % (name, tname, cols)
107 self.append(msg)
108 self.execute()
109
110 def _modify_table(self, table, column, delta):
111 return 'INSERT INTO %(table_name)s SELECT * from migration_tmp'
112
113 def visit_migrate_foreign_key_constraint(self, *p, **k):
114 self.recreate_table(p[0].table)
115
116 def visit_migrate_unique_constraint(self, *p, **k):
117 self.recreate_table(p[0].table)
118
119
120 class SQLiteConstraintDropper(ansisql.ANSIColumnDropper,
121 SQLiteCommon,
122 ansisql.ANSIConstraintCommon):
123
124 def visit_migrate_primary_key_constraint(self, constraint):
125 tmpl = "DROP INDEX %s "
126 name = self.get_constraint_name(constraint)
127 msg = tmpl % (name)
128 self.append(msg)
129 self.execute()
130
131 def visit_migrate_foreign_key_constraint(self, *p, **k):
132 self._not_supported('ALTER TABLE DROP CONSTRAINT')
133
134 def visit_migrate_check_constraint(self, *p, **k):
135 self._not_supported('ALTER TABLE DROP CONSTRAINT')
136
137 def visit_migrate_unique_constraint(self, *p, **k):
138 self._not_supported('ALTER TABLE DROP CONSTRAINT')
139
140
141 # TODO: technically primary key is a NOT NULL + UNIQUE constraint, should add NOT NULL to index
142
143 class SQLiteDialect(ansisql.ANSIDialect):
144 columngenerator = SQLiteColumnGenerator
145 columndropper = SQLiteColumnDropper
146 schemachanger = SQLiteSchemaChanger
147 constraintgenerator = SQLiteConstraintGenerator
148 constraintdropper = SQLiteConstraintDropper