|
@@ -64,6 +64,11 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
64
|
64
|
self._create_default_tables(self.drop_if_exists)
|
65
|
65
|
|
66
|
66
|
## @brief Modify the db given an EM change
|
|
67
|
+ #
|
|
68
|
+ # @note Here we don't care about the relation parameter of _add_column() method because the
|
|
69
|
+ # only case in wich we want to add a field that is linked with the relation table is for rel2type
|
|
70
|
+ # attr creation. The relation parameter is set to True in the add_relationnal_field() method
|
|
71
|
+ #
|
67
|
72
|
# @param em model : The EditorialModel.model object to provide the global context
|
68
|
73
|
# @param uid int : The uid of the change EmComponent
|
69
|
74
|
# @param initial_state dict | None : dict with field name as key and field value as value. Representing the original state. None mean creation of a new component.
|
|
@@ -120,12 +125,19 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
120
|
125
|
pkname, pkftype = self._relation_pk
|
121
|
126
|
|
122
|
127
|
#If not exists create a relational table
|
123
|
|
- self._create_table(tname, pkname, pkftype, self.db_engine, if_exists='nothing')
|
|
128
|
+ self._create_table(
|
|
129
|
+ tname,
|
|
130
|
+ pkname,
|
|
131
|
+ pkftype,
|
|
132
|
+ self.db_engine,
|
|
133
|
+ if_exists='nothing',
|
|
134
|
+ noauto_inc = True,
|
|
135
|
+ )
|
124
|
136
|
#Add a foreign key if wanted
|
125
|
137
|
if self.foreign_keys:
|
126
|
138
|
self._add_fk(tname, utils.common_tables['relation'], pkname, pkname)
|
127
|
139
|
#Add the column
|
128
|
|
- self._add_column(tname, emfield.name, emfield.fieldtype_instance())
|
|
140
|
+ self._add_column(tname, emfield.name, emfield.fieldtype_instance(), relation=True)
|
129
|
141
|
#Update table triggers
|
130
|
142
|
self._generate_triggers(tname, self._r2type2cols(edmod, r2tf))
|
131
|
143
|
|
|
@@ -175,9 +187,13 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
175
|
187
|
raise ValueError("The given uid is not an EmClass uid")
|
176
|
188
|
pkname, pktype = self._object_pk
|
177
|
189
|
table_name = utils.object_table_name(emclass.name)
|
178
|
|
-
|
179
|
|
- self._create_table(table_name, pkname, pktype, engine=engine)
|
180
|
|
-
|
|
190
|
+ self._create_table(
|
|
191
|
+ table_name,
|
|
192
|
+ pkname,
|
|
193
|
+ pktype,
|
|
194
|
+ engine=engine,
|
|
195
|
+ noauto_inc = True
|
|
196
|
+ )
|
181
|
197
|
if self.foreign_keys:
|
182
|
198
|
self._add_fk(table_name, utils.common_tables['object'], pkname, pkname)
|
183
|
199
|
|
|
@@ -258,7 +274,7 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
258
|
274
|
cols = {fname: self._common_field_to_ftype(fname) for fname in EditorialModel.classtypes.common_fields}
|
259
|
275
|
for fname, ftype in cols.items():
|
260
|
276
|
if fname != pk_name:
|
261
|
|
- self._add_column(tname, fname, ftype)
|
|
277
|
+ self._add_column(tname, fname, ftype, relation=False)
|
262
|
278
|
#Creating triggers
|
263
|
279
|
self._generate_triggers(tname, cols)
|
264
|
280
|
object_tname = tname
|
|
@@ -269,7 +285,7 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
269
|
285
|
self._create_table(tname, pk_name, pk_ftype, engine=self.db_engine, if_exists=if_exists)
|
270
|
286
|
#Adding columns
|
271
|
287
|
for fname, ftype in self._relation_cols.items():
|
272
|
|
- self._add_column(tname, fname, ftype)
|
|
288
|
+ self._add_column(tname, fname, ftype, relation=True)
|
273
|
289
|
#Creating triggers
|
274
|
290
|
self._generate_triggers(tname, self._relation_cols)
|
275
|
291
|
|
|
@@ -297,7 +313,8 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
297
|
313
|
# @param engine str : The engine to use with this table
|
298
|
314
|
# @param charset str : The charset of this table
|
299
|
315
|
# @param if_exist str : takes values in ['nothing', 'drop']
|
300
|
|
- def _create_table(self, table_name, pk_name, pk_ftype, engine, charset='utf8', if_exists='nothing'):
|
|
316
|
+ # @param noauto_inc bool : if True forbids autoincrement on PK
|
|
317
|
+ def _create_table(self, table_name, pk_name, pk_ftype, engine, charset='utf8', if_exists='nothing', noauto_inc = False):
|
301
|
318
|
#Escaped table name
|
302
|
319
|
etname = utils.escape_idname(table_name)
|
303
|
320
|
if not isinstance(pk_name, tuple):
|
|
@@ -308,17 +325,17 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
308
|
325
|
raise ValueError("You have to give as many pk_name as pk_ftype")
|
309
|
326
|
|
310
|
327
|
pk_instr_cols = ''
|
311
|
|
- pk_format = '{pk_name} {pk_type} {pk_specs},'
|
|
328
|
+ pk_format = "{pk_name} {pk_type} {pk_specs},\n"
|
312
|
329
|
for i in range(len(pk_name)):
|
313
|
|
- instr_type, pk_type, pk_specs = fieldtypes_utils.fieldtype_db_init(pk_ftype[i])
|
|
330
|
+ instr_type, pk_type, pk_specs = fieldtypes_utils.fieldtype_db_init(pk_ftype[i], noauto_inc)
|
314
|
331
|
if instr_type != 'column':
|
315
|
332
|
raise ValueError("Migration handler doesn't support MultiValueFieldType as primary keys")
|
316
|
333
|
pk_instr_cols += pk_format.format(
|
317
|
|
- pk_name = pk_name[i],
|
|
334
|
+ pk_name = utils.escape_idname(pk_name[i]),
|
318
|
335
|
pk_type = pk_type,
|
319
|
336
|
pk_specs = pk_specs
|
320
|
337
|
)
|
321
|
|
- pk_instr_cols += "\nPRIMARY KEY("+(','.join([utils.escape_idname(pkn) for pkn in pk_name]))+')\n'
|
|
338
|
+ pk_instr_cols += "PRIMARY KEY("+(','.join([utils.escape_idname(pkn) for pkn in pk_name]))+')'
|
322
|
339
|
|
323
|
340
|
if if_exists == 'drop':
|
324
|
341
|
self._query("""DROP TABLE IF EXISTS {table_name};""".format(table_name=etname))
|
|
@@ -337,19 +354,21 @@ class MysqlMigrationHandler(DummyMigrationHandler):
|
337
|
354
|
# @param table_name str : The table name
|
338
|
355
|
# @param col_name str : The columns name
|
339
|
356
|
# @param col_fieldtype EmFieldype the fieldtype
|
|
357
|
+ # @param relation bool | None : a flag to indicate if we add a column in a table linked with an bject or with a relation (used only when the column is MultiValueFieldType )
|
340
|
358
|
# @return True if the column was added else return False
|
341
|
|
- def _add_column(self, table_name, col_name, col_fieldtype, drop_if_exists=False):
|
342
|
|
-
|
|
359
|
+ def _add_column(self, table_name, col_name, col_fieldtype, drop_if_exists=False, relation=False):
|
343
|
360
|
instr, col_type, col_specs = fieldtypes_utils.fieldtype_db_init(col_fieldtype)
|
344
|
361
|
|
345
|
362
|
if instr == 'table':
|
346
|
363
|
# multivalue field. We are not going to add a column in this table
|
347
|
364
|
# but in corresponding multivalue table
|
348
|
365
|
self._add_column_multivalue(
|
349
|
|
- table_name,
|
|
366
|
+ ref_table_name = table_name,
|
350
|
367
|
key_infos = col_type,
|
351
|
|
- column_infos = (col_name, col_specs)
|
|
368
|
+ column_infos = (col_name, col_specs),
|
|
369
|
+ relation = relation
|
352
|
370
|
)
|
|
371
|
+ return True
|
353
|
372
|
|
354
|
373
|
col_name = utils.column_name(col_name)
|
355
|
374
|
|
|
@@ -414,21 +433,25 @@ ADD COLUMN {col_name} {col_type} {col_specs};"""
|
414
|
433
|
# @param ref_table_name str : Referenced table name
|
415
|
434
|
# @param key_infos tuple : tuple(key_name, key_fieldtype)
|
416
|
435
|
# @param column_infos tuple : tuple(col_name, col_fieldtype)
|
417
|
|
- def _add_column_multivalue(ref_table_name, key_info, column_infos):
|
|
436
|
+ def _add_column_multivalue(self, ref_table_name, key_infos, column_infos, relation):
|
418
|
437
|
key_name, key_ftype = key_infos
|
419
|
438
|
col_name, col_ftype = column_infos
|
420
|
439
|
table_name = utils.multivalue_table_name(ref_table_name, key_name)
|
|
440
|
+ if relation:
|
|
441
|
+ pk_infos = self._relation_pk
|
|
442
|
+ else:
|
|
443
|
+ pk_infos = self._object_pk
|
421
|
444
|
# table creation
|
422
|
445
|
self._create_table(
|
423
|
|
- table_name,
|
424
|
|
- key_name,
|
425
|
|
- key_ftype,
|
426
|
|
- self.db_engine,
|
427
|
|
- if_exists = 'nothing'
|
|
446
|
+ table_name = table_name,
|
|
447
|
+ pk_name = (key_name, pk_infos[0]),
|
|
448
|
+ pk_ftype = (key_ftype, pk_infos[1]),
|
|
449
|
+ engine = self.db_engine,
|
|
450
|
+ if_exists = 'nothing',
|
|
451
|
+ noauto_inc = True
|
428
|
452
|
)
|
429
|
453
|
# with FK
|
430
|
|
- self._del_fk(table_name, dst_table_name)
|
431
|
|
- self._add_fk(table_name, dst_table_name, key_name, utils._object_pk[0])
|
|
454
|
+ self._add_fk(table_name, ref_table_name, pk_infos[0], pk_infos[0])
|
432
|
455
|
# adding the column
|
433
|
456
|
self._add_column(table_name, col_name, col_ftype)
|
434
|
457
|
|
|
@@ -465,12 +488,13 @@ FOREIGN KEY ({src_col}) references {dst_table}({dst_col});""".format(
|
465
|
488
|
# @warning fails silently
|
466
|
489
|
def _del_fk(self, src_table_name, dst_table_name, fk_name=None):
|
467
|
490
|
if fk_name is None:
|
468
|
|
- fk_name = utils.escape_idname(utils.get_fk_name(src_table_name, dst_table_name))
|
|
491
|
+ fk_name = utils.get_fk_name(src_table_name, dst_table_name)
|
|
492
|
+ fk_name = utils.escape_idname(fk_name)
|
469
|
493
|
try:
|
470
|
494
|
self._query("""ALTER TABLE {src_table}
|
471
|
495
|
DROP FOREIGN KEY {fk_name}""".format(
|
472
|
496
|
src_table=utils.escape_idname(src_table_name),
|
473
|
|
- fk_name=utils.escape_idname(fk_name)
|
|
497
|
+ fk_name=fk_name
|
474
|
498
|
))
|
475
|
499
|
except self._dbmodule.err.InternalError:
|
476
|
500
|
# If the FK don't exists we do not care
|