##// END OF EJS Templates
dbmigrate: sync with latest ver
super-admin -
r5165:e6085588 default
parent child Browse files
Show More
@@ -30,8 +30,24 b' class SQLiteCommon(object):'
30 30
31 31 class SQLiteHelper(SQLiteCommon):
32 32
33 def _get_unique_constraints(self, table):
34 """Retrieve information about existing unique constraints of the table
33 def _filter_columns(self, cols, table):
34 """Splits the string of columns and returns those only in the table.
35
36 :param cols: comma-delimited string of table columns
37 :param table: the table to check
38 :return: list of columns in the table
39 """
40 columns = []
41 for c in cols.split(","):
42 if c in table.columns:
43 # There was a bug in reflection of SQLite columns with
44 # reserved identifiers as names (SQLite can return them
45 # wrapped with double quotes), so strip double quotes.
46 columns.extend(c.strip(' "'))
47 return columns
48
49 def _get_constraints(self, table):
50 """Retrieve information about existing constraints of the table
35 51
36 52 This feature is needed for recreate_table() to work properly.
37 53 """
@@ -49,19 +65,21 b' class SQLiteHelper(SQLiteCommon):'
49 65 constraints = []
50 66 for name, cols in re.findall(UNIQUE_PATTERN, data):
51 67 # Filter out any columns that were dropped from the table.
52 columns = []
53 for c in cols.split(","):
54 if c in table.columns:
55 # There was a bug in reflection of SQLite columns with
56 # reserved identifiers as names (SQLite can return them
57 # wrapped with double quotes), so strip double quotes.
58 columns.extend(c.strip(' "'))
68 columns = self._filter_columns(cols, table)
59 69 if columns:
60 70 constraints.extend(UniqueConstraint(*columns, name=name))
71
72 FKEY_PATTERN = "CONSTRAINT (\w+) FOREIGN KEY \(([^\)]+)\)"
73 for name, cols in re.findall(FKEY_PATTERN, data):
74 # Filter out any columns that were dropped from the table.
75 columns = self._filter_columns(cols, table)
76 if columns:
77 constraints.extend(ForeignKeyConstraint(*columns, name=name))
78
61 79 return constraints
62 80
63 81 def recreate_table(self, table, column=None, delta=None,
64 omit_uniques=None):
82 omit_constraints=None):
65 83 table_name = self.preparer.format_table(table)
66 84
67 85 # we remove all indexes so as not to have
@@ -69,24 +87,27 b' class SQLiteHelper(SQLiteCommon):'
69 87 for index in table.indexes:
70 88 index.drop()
71 89
72 # reflect existing unique constraints
73 for uc in self._get_unique_constraints(table):
74 table.append_constraint(uc)
75 # omit given unique constraints when creating a new table if required
90 # reflect existing constraints
91 for constraint in self._get_constraints(table):
92 table.append_constraint(constraint)
93 # omit given constraints when creating a new table if required
76 94 table.constraints = set([
77 95 cons for cons in table.constraints
78 if omit_uniques is None or cons.name not in omit_uniques
96 if omit_constraints is None or cons.name not in omit_constraints
79 97 ])
80 tup = sqlite3.sqlite_version_info
81 if tup[0] > 3 or (tup[0] == 3 and tup[1] >= 26):
98
99 # Use "PRAGMA legacy_alter_table = ON" with sqlite >= 3.26 when
100 # using "ALTER TABLE RENAME TO migration_tmp" to maintain legacy
101 # behavior. See: https://www.sqlite.org/src/info/ae9638e9c0ad0c36
102 if self.connection.engine.dialect.server_version_info >= (3, 26):
82 103 self.append('PRAGMA legacy_alter_table = ON')
83 104 self.execute()
84
85 105 self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
86 106 self.execute()
87 if tup[0] > 3 or (tup[0] == 3 and tup[1] >= 26):
107 if self.connection.engine.dialect.server_version_info >= (3, 26):
88 108 self.append('PRAGMA legacy_alter_table = OFF')
89 109 self.execute()
110
90 111 insertion_string = self._modify_table(table, column, delta)
91 112
92 113 table.create(bind=self.connection)
@@ -102,7 +123,6 b' class SQLiteHelper(SQLiteCommon):'
102 123 else:
103 124 column = delta
104 125 table = self._to_table(column.table)
105
106 126 self.recreate_table(table,column,delta)
107 127
108 128 class SQLiteColumnGenerator(SQLiteSchemaGenerator,
@@ -190,13 +210,14 b' class SQLiteConstraintDropper(ansisql.AN'
190 210 self.execute()
191 211
192 212 def visit_migrate_foreign_key_constraint(self, *p, **k):
193 self._not_supported('ALTER TABLE DROP CONSTRAINT')
213 #self._not_supported('ALTER TABLE DROP CONSTRAINT')
214 self.recreate_table(p[0].table, omit_constraints=[p[0].name])
194 215
195 216 def visit_migrate_check_constraint(self, *p, **k):
196 217 self._not_supported('ALTER TABLE DROP CONSTRAINT')
197 218
198 219 def visit_migrate_unique_constraint(self, *p, **k):
199 self.recreate_table(p[0].table, omit_uniques=[p[0].name])
220 self.recreate_table(p[0].table, omit_constraints=[p[0].name])
200 221
201 222
202 223 # TODO: technically primary key is a NOT NULL + UNIQUE constraint, should add NOT NULL to index
@@ -367,8 +367,14 b' class ColumnDelta(DictMixin, sqlalchemy.'
367 367 self.process_column(self.result_column)
368 368
369 369 # create an instance of class type if not yet
370 if 'type' in diffs and callable(self.result_column.type):
370 if 'type' in diffs:
371 if callable(self.result_column.type):
371 372 self.result_column.type = self.result_column.type()
373 if self.result_column.autoincrement and \
374 not issubclass(
375 self.result_column.type._type_affinity,
376 sqlalchemy.Integer):
377 self.result_column.autoincrement = False
372 378
373 379 # add column to the table
374 380 if self.table is not None and self.alter_metadata:
General Comments 0
You need to be logged in to leave comments. Login now