##// 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 class SQLiteHelper(SQLiteCommon):
31 class SQLiteHelper(SQLiteCommon):
32
32
33 def _get_unique_constraints(self, table):
33 def _filter_columns(self, cols, table):
34 """Retrieve information about existing unique constraints of the 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 This feature is needed for recreate_table() to work properly.
52 This feature is needed for recreate_table() to work properly.
37 """
53 """
@@ -49,19 +65,21 b' class SQLiteHelper(SQLiteCommon):'
49 constraints = []
65 constraints = []
50 for name, cols in re.findall(UNIQUE_PATTERN, data):
66 for name, cols in re.findall(UNIQUE_PATTERN, data):
51 # Filter out any columns that were dropped from the table.
67 # Filter out any columns that were dropped from the table.
52 columns = []
68 columns = self._filter_columns(cols, table)
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(' "'))
59 if columns:
69 if columns:
60 constraints.extend(UniqueConstraint(*columns, name=name))
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 return constraints
79 return constraints
62
80
63 def recreate_table(self, table, column=None, delta=None,
81 def recreate_table(self, table, column=None, delta=None,
64 omit_uniques=None):
82 omit_constraints=None):
65 table_name = self.preparer.format_table(table)
83 table_name = self.preparer.format_table(table)
66
84
67 # we remove all indexes so as not to have
85 # we remove all indexes so as not to have
@@ -69,24 +87,27 b' class SQLiteHelper(SQLiteCommon):'
69 for index in table.indexes:
87 for index in table.indexes:
70 index.drop()
88 index.drop()
71
89
72 # reflect existing unique constraints
90 # reflect existing constraints
73 for uc in self._get_unique_constraints(table):
91 for constraint in self._get_constraints(table):
74 table.append_constraint(uc)
92 table.append_constraint(constraint)
75 # omit given unique constraints when creating a new table if required
93 # omit given constraints when creating a new table if required
76 table.constraints = set([
94 table.constraints = set([
77 cons for cons in table.constraints
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
98
81 if tup[0] > 3 or (tup[0] == 3 and tup[1] >= 26):
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 self.append('PRAGMA legacy_alter_table = ON')
103 self.append('PRAGMA legacy_alter_table = ON')
83 self.execute()
104 self.execute()
84
85 self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
105 self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
86 self.execute()
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 self.append('PRAGMA legacy_alter_table = OFF')
108 self.append('PRAGMA legacy_alter_table = OFF')
89 self.execute()
109 self.execute()
110
90 insertion_string = self._modify_table(table, column, delta)
111 insertion_string = self._modify_table(table, column, delta)
91
112
92 table.create(bind=self.connection)
113 table.create(bind=self.connection)
@@ -102,7 +123,6 b' class SQLiteHelper(SQLiteCommon):'
102 else:
123 else:
103 column = delta
124 column = delta
104 table = self._to_table(column.table)
125 table = self._to_table(column.table)
105
106 self.recreate_table(table,column,delta)
126 self.recreate_table(table,column,delta)
107
127
108 class SQLiteColumnGenerator(SQLiteSchemaGenerator,
128 class SQLiteColumnGenerator(SQLiteSchemaGenerator,
@@ -190,13 +210,14 b' class SQLiteConstraintDropper(ansisql.AN'
190 self.execute()
210 self.execute()
191
211
192 def visit_migrate_foreign_key_constraint(self, *p, **k):
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 def visit_migrate_check_constraint(self, *p, **k):
216 def visit_migrate_check_constraint(self, *p, **k):
196 self._not_supported('ALTER TABLE DROP CONSTRAINT')
217 self._not_supported('ALTER TABLE DROP CONSTRAINT')
197
218
198 def visit_migrate_unique_constraint(self, *p, **k):
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 # TODO: technically primary key is a NOT NULL + UNIQUE constraint, should add NOT NULL to index
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 self.process_column(self.result_column)
367 self.process_column(self.result_column)
368
368
369 # create an instance of class type if not yet
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 self.result_column.type = self.result_column.type()
371 if callable(self.result_column.type):
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 # add column to the table
379 # add column to the table
374 if self.table is not None and self.alter_metadata:
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