|
@@ -29,7 +29,7 @@ from DataSource.MySQL.MySQL import MySQL
|
29
|
29
|
# - EmFieldType changes
|
30
|
30
|
#
|
31
|
31
|
# @todo Unified datasources and migration handlers via utils functions
|
32
|
|
-#
|
|
32
|
+
|
33
|
33
|
|
34
|
34
|
## @brief Modify a MySQL database given editorial model changes
|
35
|
35
|
class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigrationHandler):
|
|
@@ -39,7 +39,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
39
|
39
|
# @param user str : The db user
|
40
|
40
|
# @param password str : The db password
|
41
|
41
|
# @param db str : The db name
|
42
|
|
- def __init__(self, host, user, password, db, db_engine = 'InnoDB', foreign_keys = True, debug = False, dryrun = False, drop_if_exists = False):
|
|
42
|
+ def __init__(self, host, user, password, db, db_engine='InnoDB', foreign_keys=True, debug=False, dryrun=False, drop_if_exists=False):
|
43
|
43
|
self.datasource = MySQL
|
44
|
44
|
#Connect to MySQL
|
45
|
45
|
self.db = pymysql.connect(host=host, user=user, passwd=password, db=db)
|
|
@@ -50,8 +50,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
50
|
50
|
self.drop_if_exists = drop_if_exists
|
51
|
51
|
#Create default tables
|
52
|
52
|
self._create_default_tables(self.drop_if_exists)
|
53
|
|
- pass
|
54
|
|
-
|
|
53
|
+
|
55
|
54
|
## @brief Delete all table created by the MH
|
56
|
55
|
# @param model Model : the Editorial model
|
57
|
56
|
def __purge_db(self, model):
|
|
@@ -60,28 +59,26 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
60
|
59
|
self.delete_emclass_table(model, uid)
|
61
|
60
|
except pymysql.err.InternalError as e:
|
62
|
61
|
print(e)
|
63
|
|
-
|
64
|
|
- for tname in [ MySQL.get_r2t2table_name(f.em_class.name, model.component(f.rel_to_type_id).name) for f in model.components('EmField') if f.fieldtype == 'rel2type' ]:
|
|
62
|
+
|
|
63
|
+ for tname in [MySQL.get_r2t2table_name(f.em_class.name, model.component(f.rel_to_type_id).name) for f in model.components('EmField') if f.fieldtype == 'rel2type']:
|
65
|
64
|
try:
|
66
|
|
- self._query("DROP TABLE %s;"%tname)
|
|
65
|
+ self._query("DROP TABLE %s;" % tname)
|
67
|
66
|
except pymysql.err.InternalError as e:
|
68
|
67
|
print(e)
|
69
|
68
|
|
70
|
|
- for tname in [ MySQL.relations_table_name, MySQL.objects_table_name ]:
|
|
69
|
+ for tname in [MySQL.relations_table_name, MySQL.objects_table_name]:
|
71
|
70
|
try:
|
72
|
|
- self._query("DROP TABLE %s;"%tname)
|
|
71
|
+ self._query("DROP TABLE %s;" % tname)
|
73
|
72
|
except pymysql.err.InternalError as e:
|
74
|
73
|
print(e)
|
75
|
|
-
|
76
|
74
|
|
77
|
75
|
## @brief Modify the db given an EM change
|
78
|
|
- #
|
79
|
76
|
# @param em model : The EditorialModel.model object to provide the global context
|
80
|
77
|
# @param uid int : The uid of the change EmComponent
|
81
|
78
|
# @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.
|
82
|
79
|
# @param new_state dict | None : dict with field name as key and field value as value. Representing the new state. None mean component deletion
|
83
|
80
|
# @throw EditorialModel.exceptions.MigrationHandlerChangeError if the change was refused
|
84
|
|
- def register_change(self, em, uid, initial_state, new_state, engine = None):
|
|
81
|
+ def register_change(self, em, uid, initial_state, new_state, engine=None):
|
85
|
82
|
if engine is None:
|
86
|
83
|
engine = self.db_engine
|
87
|
84
|
if isinstance(em.component(uid), EditorialModel.classes.EmClass):
|
|
@@ -97,11 +94,11 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
97
|
94
|
#non relationnal field
|
98
|
95
|
if initial_state is None:
|
99
|
96
|
#non relationnal EmField creation
|
100
|
|
- if not(emfield.name in EditorialModel.classtypes.common_fields.keys()):
|
101
|
|
- self.add_col_from_emfield(em,uid)
|
|
97
|
+ if emfield.name not in EditorialModel.classtypes.common_fields.keys():
|
|
98
|
+ self.add_col_from_emfield(em, uid)
|
102
|
99
|
elif new_state is None:
|
103
|
100
|
#non relationnal EmField deletion
|
104
|
|
- if not (emfield.name in EditorialModel.classtypes.common_fields.keys()):
|
|
101
|
+ if emfield.name not in EditorialModel.classtypes.common_fields.keys():
|
105
|
102
|
self.del_col_from_emfield(em, uid)
|
106
|
103
|
else:
|
107
|
104
|
#relationnal field
|
|
@@ -121,14 +118,13 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
121
|
118
|
# @param query str : SQL query
|
122
|
119
|
def _query(self, query):
|
123
|
120
|
if self.debug:
|
124
|
|
- print(query+"\n")
|
|
121
|
+ print(query + "\n")
|
125
|
122
|
if not self.dryrun:
|
126
|
123
|
with self.db.cursor() as cur:
|
127
|
124
|
cur.execute(query)
|
128
|
|
- self.db.commit() #autocommit
|
129
|
|
-
|
|
125
|
+ self.db.commit() # autocommit
|
|
126
|
+
|
130
|
127
|
## @brief Add a relationnal field
|
131
|
|
- #
|
132
|
128
|
# Add a rel2type attribute
|
133
|
129
|
# @note this function handles the table creation
|
134
|
130
|
# @param em Model : EditorialModel.model.Model instance
|
|
@@ -141,9 +137,9 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
141
|
137
|
r2tf = em.component(emfield.rel_field_id)
|
142
|
138
|
tname = self._r2t2table_name(em, r2tf)
|
143
|
139
|
pkname, pkftype = self._relation_pk
|
144
|
|
-
|
|
140
|
+
|
145
|
141
|
#If not exists create a relational table
|
146
|
|
- self._create_table(tname, pkname, pkftype, self.db_engine, if_exists = 'nothing')
|
|
142
|
+ self._create_table(tname, pkname, pkftype, self.db_engine, if_exists='nothing')
|
147
|
143
|
#Add a foreign key if wanted
|
148
|
144
|
if self.foreign_keys:
|
149
|
145
|
self._add_fk(tname, self.datasource.relations_table_name, pkname, pkname)
|
|
@@ -151,7 +147,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
151
|
147
|
self._add_column(tname, emfield.name, emfield.fieldtype_instance())
|
152
|
148
|
#Update table triggers
|
153
|
149
|
self._generate_triggers(tname, self._r2type2cols(em, r2tf))
|
154
|
|
-
|
|
150
|
+
|
155
|
151
|
## @brief Delete a rel2type attribute
|
156
|
152
|
#
|
157
|
153
|
# Delete a rel2type attribute
|
|
@@ -165,10 +161,10 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
165
|
161
|
|
166
|
162
|
r2tf = em.component(emfield.rel_field_id)
|
167
|
163
|
tname = self._r2t2table_name(em, r2tf)
|
168
|
|
-
|
|
164
|
+
|
169
|
165
|
if len(self._r2type2cols(em, r2tf)) == 1:
|
170
|
166
|
#The table can be deleted (no more attribute for this rel2type)
|
171
|
|
- self._query("""DROP TABLE {table_name}""".format(table_name = tname))
|
|
167
|
+ self._query("""DROP TABLE {table_name}""".format(table_name=tname))
|
172
|
168
|
else:
|
173
|
169
|
self._del_column(tname, emfield.name)
|
174
|
170
|
#Update table triggers
|
|
@@ -199,10 +195,10 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
199
|
195
|
pkname, pktype = self._common_field_pk
|
200
|
196
|
table_name = self._emclass2table_name(emclass)
|
201
|
197
|
self._create_table(table_name, pkname, pktype, engine=engine)
|
202
|
|
-
|
|
198
|
+
|
203
|
199
|
if self.foreign_keys:
|
204
|
200
|
self._add_fk(table_name, self.datasource.objects_table_name, pkname, pkname)
|
205
|
|
-
|
|
201
|
+
|
206
|
202
|
## @brief Given an EmClass uid delete the corresponding table
|
207
|
203
|
# @param em Model : A Model instance
|
208
|
204
|
# @param uid int : An EmField uid
|
|
@@ -216,7 +212,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
216
|
212
|
|
217
|
213
|
tname = self.datasource.escape_idname(tname)
|
218
|
214
|
|
219
|
|
- self._query("""DROP TABLE {table_name};""".format(table_name = tname))
|
|
215
|
+ self._query("""DROP TABLE {table_name};""".format(table_name=tname))
|
220
|
216
|
|
221
|
217
|
## @brief Given an EmField delete the corresponding column
|
222
|
218
|
# @param em Model : an @ref EditorialModel.model.Model instance
|
|
@@ -235,7 +231,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
235
|
231
|
# Refresh the table triggers
|
236
|
232
|
cols_ls = self._class2cols(emclass)
|
237
|
233
|
self._generate_triggers(tname, cols_l)
|
238
|
|
-
|
|
234
|
+
|
239
|
235
|
## @brief Delete a column from a table
|
240
|
236
|
# @param tname str : The table name
|
241
|
237
|
# @param fname str : The column name
|
|
@@ -243,15 +239,15 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
243
|
239
|
tname = self.datasource.escape_idname(tname)
|
244
|
240
|
fname = self.datasource.escape_idname(fname)
|
245
|
241
|
|
246
|
|
- self._query("""ALTER TABLE {table_name} DROP COLUMN {col_name};""".format(table_name = tname, col_name = fname))
|
247
|
|
-
|
|
242
|
+ self._query("""ALTER TABLE {table_name} DROP COLUMN {col_name};""".format(table_name=tname, col_name=fname))
|
|
243
|
+
|
248
|
244
|
## @brief Construct a table name given an EmClass instance
|
249
|
245
|
# @param emclass EmClass : An EmClass instance
|
250
|
246
|
# @return a table name
|
251
|
247
|
def _emclass2table_name(self, emclass):
|
252
|
248
|
return self.datasource.get_table_name_from_class(emclass.name)
|
253
|
249
|
#return "class_%s"%emclass.name
|
254
|
|
-
|
|
250
|
+
|
255
|
251
|
## @brief Construct a table name given a rela2type EmField instance
|
256
|
252
|
# @param em Model : A Model instance
|
257
|
253
|
# @param emfield EmField : An EmField instance
|
|
@@ -261,31 +257,31 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
261
|
257
|
emtype = em.component(emfield.rel_to_type_id)
|
262
|
258
|
return self.datasource.get_r2t2table_name(emclass.name, emtype.name)
|
263
|
259
|
#return "%s_%s_%s"%(emclass.name, emtype.name, emfield.name)
|
264
|
|
-
|
|
260
|
+
|
265
|
261
|
## @brief Generate a columns_fieldtype dict given a rel2type EmField
|
266
|
262
|
# @param em Model : an @ref EditorialModel.model.Model instance
|
267
|
263
|
# @param emfield EmField : and @ref EditorialModel.fields.EmField instance
|
268
|
264
|
def _r2type2cols(self, em, emfield):
|
269
|
|
- return { f.name: f.fieldtype_instance() for f in em.components('EmField') if f.rel_field_id == emfield.uid }
|
270
|
|
-
|
|
265
|
+ return {f.name: f.fieldtype_instance() for f in em.components('EmField') if f.rel_field_id == emfield.uid}
|
|
266
|
+
|
271
|
267
|
## @brief Generate a columns_fieldtype dict given an EmClass
|
272
|
268
|
# @param emclass EmClass : An EmClass instance
|
273
|
269
|
# @return A dict with column name as key and EmFieldType instance as value
|
274
|
270
|
def _class2cols(self, emclass):
|
275
|
271
|
if not isinstance(emclass, EditorialModel.classes.EmClass):
|
276
|
272
|
raise ValueError("The given uid is not an EmClass uid")
|
277
|
|
- return { f.name: f.fieldtype_instance() for f in emclass.fields() if f.name not in EditorialModel.classtypes.common_fields.keys() }
|
|
273
|
+ return {f.name: f.fieldtype_instance() for f in emclass.fields() if f.name not in EditorialModel.classtypes.common_fields.keys()}
|
278
|
274
|
|
279
|
275
|
## @brief Create object and relations tables
|
280
|
276
|
# @param drop_if_exist bool : If true drop tables if exists
|
281
|
|
- def _create_default_tables(self, drop_if_exist = False):
|
|
277
|
+ def _create_default_tables(self, drop_if_exist=False):
|
282
|
278
|
if_exists = 'drop' if drop_if_exist else 'nothing'
|
283
|
279
|
#Object tablea
|
284
|
280
|
tname = self.datasource.objects_table_name
|
285
|
281
|
pk_name, pk_ftype = self._common_field_pk
|
286
|
|
- self._create_table(tname, pk_name, pk_ftype, engine=self.db_engine, if_exists = if_exists)
|
|
282
|
+ self._create_table(tname, pk_name, pk_ftype, engine=self.db_engine, if_exists=if_exists)
|
287
|
283
|
#Adding columns
|
288
|
|
- cols = { fname: self._common_field_to_ftype(fname) for fname in EditorialModel.classtypes.common_fields }
|
|
284
|
+ cols = {fname: self._common_field_to_ftype(fname) for fname in EditorialModel.classtypes.common_fields}
|
289
|
285
|
for fname, ftype in cols.items():
|
290
|
286
|
if fname != pk_name:
|
291
|
287
|
self._add_column(tname, fname, ftype)
|
|
@@ -295,7 +291,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
295
|
291
|
#Relation table
|
296
|
292
|
tname = self.datasource.relations_table_name
|
297
|
293
|
pk_name, pk_ftype = self._relation_pk
|
298
|
|
- self._create_table(tname, pk_name, pk_ftype, engine = self.db_engine, if_exists = if_exists)
|
|
294
|
+ self._create_table(tname, pk_name, pk_ftype, engine=self.db_engine, if_exists=if_exists)
|
299
|
295
|
#Adding columns
|
300
|
296
|
for fname, ftype in self._relation_cols.items():
|
301
|
297
|
self._add_column(tname, fname, ftype)
|
|
@@ -305,7 +301,7 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
305
|
301
|
## @return true if the name changes
|
306
|
302
|
def _name_change(self, initial_state, new_state):
|
307
|
303
|
return 'name' in initial_state and initial_state['name'] != new_state['name']
|
308
|
|
-
|
|
304
|
+
|
309
|
305
|
## @brief Create a table with primary key
|
310
|
306
|
# @param table_name str : table name
|
311
|
307
|
# @param pk_name str : pk column name
|
|
@@ -313,14 +309,14 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
|
313
|
309
|
# @param engine str : The engine to use with this table
|
314
|
310
|
# @param charset str : The charset of this table
|
315
|
311
|
# @param if_exist str : takes values in ['nothing', 'drop']
|
316
|
|
- def _create_table(self, table_name, pk_name, pk_ftype, engine, charset = 'utf8', if_exists = 'nothing'):
|
|
312
|
+ def _create_table(self, table_name, pk_name, pk_ftype, engine, charset='utf8', if_exists='nothing'):
|
317
|
313
|
#Escaped table name
|
318
|
314
|
etname = self.datasource.escape_idname(table_name)
|
319
|
315
|
pk_type = self._field_to_type(pk_ftype)
|
320
|
316
|
pk_specs = self._field_to_specs(pk_ftype)
|
321
|
317
|
|
322
|
318
|
if if_exists == 'drop':
|
323
|
|
- self._query("""DROP TABLE IF EXISTS {table_name};""".format(table_name = etname))
|
|
319
|
+ self._query("""DROP TABLE IF EXISTS {table_name};""".format(table_name=etname))
|
324
|
320
|
qres = """
|
325
|
321
|
CREATE TABLE {table_name} (
|
326
|
322
|
{pk_name} {pk_type} {pk_specs},
|
|
@@ -332,33 +328,33 @@ PRIMARY KEY({pk_name})
|
332
|
328
|
PRIMARY KEY({pk_name})
|
333
|
329
|
) ENGINE={engine} DEFAULT CHARSET={charset};"""
|
334
|
330
|
else:
|
335
|
|
- raise ValueError("Unexpected value for argument if_exists '%s'."%if_exists)
|
|
331
|
+ raise ValueError("Unexpected value for argument if_exists '%s'." % if_exists)
|
336
|
332
|
|
337
|
333
|
self._query(qres.format(
|
338
|
|
- table_name = self.datasource.escape_idname(table_name),
|
339
|
|
- pk_name = self.datasource.escape_idname(pk_name),
|
340
|
|
- pk_type = pk_type,
|
341
|
|
- pk_specs = pk_specs,
|
342
|
|
- engine = engine,
|
343
|
|
- charset = charset
|
|
334
|
+ table_name=self.datasource.escape_idname(table_name),
|
|
335
|
+ pk_name=self.datasource.escape_idname(pk_name),
|
|
336
|
+ pk_type=pk_type,
|
|
337
|
+ pk_specs=pk_specs,
|
|
338
|
+ engine=engine,
|
|
339
|
+ charset=charset
|
344
|
340
|
))
|
345
|
341
|
|
346
|
342
|
## @brief Add a column to a table
|
347
|
343
|
# @param table_name str : The table name
|
348
|
344
|
# @param col_name str : The columns name
|
349
|
345
|
# @param col_fieldtype EmFieldype the fieldtype
|
350
|
|
- def _add_column(self, table_name, col_name, col_fieldtype, drop_if_exists = False):
|
|
346
|
+ def _add_column(self, table_name, col_name, col_fieldtype, drop_if_exists=False):
|
351
|
347
|
add_col = """ALTER TABLE {table_name}
|
352
|
348
|
ADD COLUMN {col_name} {col_type} {col_specs};"""
|
353
|
|
-
|
|
349
|
+
|
354
|
350
|
etname = self.datasource.escape_idname(table_name)
|
355
|
351
|
ecname = self.datasource.escape_idname(col_name)
|
356
|
352
|
|
357
|
353
|
add_col = add_col.format(
|
358
|
|
- table_name = etname,
|
359
|
|
- col_name = ecname,
|
360
|
|
- col_type = self._field_to_type(col_fieldtype),
|
361
|
|
- col_specs = self._field_to_specs(col_fieldtype),
|
|
354
|
+ table_name=etname,
|
|
355
|
+ col_name=ecname,
|
|
356
|
+ col_type=self._field_to_type(col_fieldtype),
|
|
357
|
+ col_specs=self._field_to_specs(col_fieldtype),
|
362
|
358
|
)
|
363
|
359
|
try:
|
364
|
360
|
self._query(add_col)
|
|
@@ -368,8 +364,8 @@ ADD COLUMN {col_name} {col_type} {col_specs};"""
|
368
|
364
|
self._add_column(table_name, col_name, col_fieldtype, drop_if_exists)
|
369
|
365
|
else:
|
370
|
366
|
#LOG
|
371
|
|
- print("Aborded, column `%s` exists"%col_name)
|
372
|
|
-
|
|
367
|
+ print("Aborded, column `%s` exists" % col_name)
|
|
368
|
+
|
373
|
369
|
## @brief Add a foreign key
|
374
|
370
|
# @param src_table_name str : The name of the table where we will add the FK
|
375
|
371
|
# @param dst_table_name str : The name of the table the FK will point on
|
|
@@ -382,19 +378,19 @@ ADD COLUMN {col_name} {col_type} {col_specs};"""
|
382
|
378
|
dcname = self.datasource.escape_idname(dst_col_name)
|
383
|
379
|
|
384
|
380
|
fk_name = self.datasource.get_fk_name(src_table_name, dst_table_name)
|
385
|
|
-
|
|
381
|
+
|
386
|
382
|
self._del_fk(src_table_name, dst_table_name)
|
387
|
383
|
|
388
|
384
|
self._query("""ALTER TABLE {src_table}
|
389
|
385
|
ADD CONSTRAINT {fk_name}
|
390
|
386
|
FOREIGN KEY ({src_col}) references {dst_table}({dst_col});""".format(
|
391
|
|
- fk_name = self.datasource.escape_idname(fk_name),
|
392
|
|
- src_table = stname,
|
393
|
|
- src_col = scname,
|
394
|
|
- dst_table = dtname,
|
395
|
|
- dst_col = dcname
|
|
387
|
+ fk_name=self.datasource.escape_idname(fk_name),
|
|
388
|
+ src_table=stname,
|
|
389
|
+ src_col=scname,
|
|
390
|
+ dst_table=dtname,
|
|
391
|
+ dst_col=dcname
|
396
|
392
|
))
|
397
|
|
-
|
|
393
|
+
|
398
|
394
|
## @brief Given a source and a destination table, delete the corresponding FK
|
399
|
395
|
# @param src_table_name str : The name of the table where the FK is
|
400
|
396
|
# @param dst_table_name str : The name of the table the FK point on
|
|
@@ -403,19 +399,19 @@ FOREIGN KEY ({src_col}) references {dst_table}({dst_col});""".format(
|
403
|
399
|
try:
|
404
|
400
|
self._query("""ALTER TABLE {src_table}
|
405
|
401
|
DROP FOREIGN KEY {fk_name}""".format(
|
406
|
|
- src_table = self.datasource.escape_idname(src_table_name),
|
407
|
|
- fk_name = self.datasource.escape_idname(self.datasource.get_fk_name(src_table_name, dst_table_name))
|
|
402
|
+ src_table=self.datasource.escape_idname(src_table_name),
|
|
403
|
+ fk_name=self.datasource.escape_idname(self.datasource.get_fk_name(src_table_name, dst_table_name))
|
408
|
404
|
))
|
409
|
405
|
except pymysql.err.InternalError:
|
410
|
406
|
# If the FK don't exists we do not care
|
411
|
407
|
pass
|
412
|
|
-
|
|
408
|
+
|
413
|
409
|
## @brief Generate triggers given a table_name and its columns fieldtypes
|
414
|
410
|
# @param table_name str : Table name
|
415
|
411
|
# @param cols_ftype dict : with col name as key and column fieldtype as value
|
416
|
412
|
def _generate_triggers(self, table_name, cols_ftype):
|
417
|
|
- colval_l_upd = dict() #param for update trigger
|
418
|
|
- colval_l_ins = dict() #param for insert trigger
|
|
413
|
+ colval_l_upd = dict() # param for update trigger
|
|
414
|
+ colval_l_ins = dict() # param for insert trigger
|
419
|
415
|
|
420
|
416
|
for cname, cftype in cols_ftype.items():
|
421
|
417
|
if cftype.ftype == 'datetime':
|
|
@@ -426,13 +422,12 @@ DROP FOREIGN KEY {fk_name}""".format(
|
426
|
422
|
|
427
|
423
|
self._table_trigger(table_name, 'UPDATE', colval_l_upd)
|
428
|
424
|
self._table_trigger(table_name, 'INSERT', colval_l_ins)
|
429
|
|
-
|
430
|
425
|
|
431
|
426
|
## @brief Create trigger for a table
|
432
|
427
|
#
|
433
|
428
|
# Primarly designed to create trigger for DATETIME types
|
434
|
429
|
# The method generates triggers of the form
|
435
|
|
- #
|
|
430
|
+ #
|
436
|
431
|
# CREATE TRIGGER BEFORE <moment> ON <table_name>
|
437
|
432
|
# FOR EACH ROW SET <for colname, colval in cols_val>
|
438
|
433
|
# NEW.<colname> = <colval>,
|
|
@@ -441,20 +436,19 @@ DROP FOREIGN KEY {fk_name}""".format(
|
441
|
436
|
# @param moment str : can be 'update' or 'insert'
|
442
|
437
|
# @param cols_val dict : Dict with column name as key and column value as value
|
443
|
438
|
def _table_trigger(self, table_name, moment, cols_val):
|
444
|
|
- trigger_name = self.datasource.escape_idname("%s_%s_trig"%(table_name, moment))
|
|
439
|
+ trigger_name = self.datasource.escape_idname("%s_%s_trig" % (table_name, moment))
|
445
|
440
|
#Try to delete the trigger
|
446
|
|
- drop_trig = """DROP TRIGGER IF EXISTS {trigger_name};""".format(trigger_name = trigger_name)
|
|
441
|
+ drop_trig = """DROP TRIGGER IF EXISTS {trigger_name};""".format(trigger_name=trigger_name)
|
447
|
442
|
self._query(drop_trig)
|
448
|
443
|
|
449
|
|
- col_val_l = ', '.join([ "NEW.%s = %s"%(self.datasource.escape_idname(cname), cval)for cname, cval in cols_val.items() ])
|
|
444
|
+ col_val_l = ', '.join(["NEW.%s = %s" % (self.datasource.escape_idname(cname), cval)for cname, cval in cols_val.items()])
|
450
|
445
|
#Create a trigger if needed
|
451
|
446
|
if len(col_val_l) > 0:
|
452
|
447
|
trig_q = """CREATE TRIGGER {trigger_name} BEFORE {moment} ON {table_name}
|
453
|
448
|
FOR EACH ROW SET {col_val_list};""".format(
|
454
|
|
- trigger_name = trigger_name,
|
455
|
|
- table_name = self.datasource.escape_idname(table_name),
|
456
|
|
- moment = moment,
|
457
|
|
- col_val_list = col_val_l
|
|
449
|
+ trigger_name=trigger_name,
|
|
450
|
+ table_name=self.datasource.escape_idname(table_name),
|
|
451
|
+ moment=moment, col_val_list=col_val_l
|
458
|
452
|
)
|
459
|
453
|
self._query(trig_q)
|
460
|
454
|
|
|
@@ -477,34 +471,33 @@ FOR EACH ROW SET {col_val_list};""".format(
|
477
|
471
|
if emfieldtype.default is None:
|
478
|
472
|
colspec += 'NULL '
|
479
|
473
|
else:
|
480
|
|
- colspec += emfieldtype.default #ESCAPE VALUE HERE !!!!
|
|
474
|
+ colspec += emfieldtype.default # ESCAPE VALUE HERE !!!!
|
481
|
475
|
|
482
|
476
|
if emfieldtype.name == 'pk':
|
483
|
477
|
colspec += ' AUTO_INCREMENT'
|
484
|
478
|
|
485
|
479
|
return colspec
|
486
|
480
|
|
487
|
|
-
|
488
|
481
|
## @brief Given a fieldtype return a MySQL type specifier
|
489
|
482
|
# @param emfieldtype EmFieldType : A fieldtype
|
490
|
483
|
# @return the corresponding MySQL type
|
491
|
484
|
def _field_to_type(self, emfieldtype):
|
492
|
485
|
ftype = emfieldtype.ftype
|
493
|
|
-
|
|
486
|
+
|
494
|
487
|
if ftype == 'char' or ftype == 'str':
|
495
|
|
- res = "VARCHAR(%d)"%emfieldtype.max_length
|
|
488
|
+ res = "VARCHAR(%d)" % emfieldtype.max_length
|
496
|
489
|
elif ftype == 'text':
|
497
|
490
|
res = "TEXT"
|
498
|
491
|
elif ftype == 'datetime':
|
499
|
492
|
res = "DATETIME"
|
500
|
493
|
# client side workaround for only one column with CURRENT_TIMESTAMP : giving NULL to timestamp that don't allows NULL
|
501
|
494
|
# cf. https://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html#idm139961275230400
|
502
|
|
- # The solution for the migration handler is to create triggers :
|
|
495
|
+ # The solution for the migration handler is to create triggers :
|
503
|
496
|
# CREATE TRIGGER trigger_name BEFORE INSERT ON `my_super_table`
|
504
|
497
|
# FOR EACH ROW SET NEW.my_date_column = NOW();
|
505
|
498
|
# and
|
506
|
499
|
# CREATE TRIGGER trigger_name BEFORE UPDATE ON
|
507
|
|
-
|
|
500
|
+
|
508
|
501
|
elif ftype == 'bool':
|
509
|
502
|
res = "BOOL"
|
510
|
503
|
elif ftype == 'int':
|
|
@@ -512,10 +505,10 @@ FOR EACH ROW SET {col_val_list};""".format(
|
512
|
505
|
elif ftype == 'rel2type':
|
513
|
506
|
res = "INT"
|
514
|
507
|
else:
|
515
|
|
- raise ValueError("Unsuported fieldtype ftype : %s"%ftype)
|
|
508
|
+ raise ValueError("Unsuported fieldtype ftype : %s" % ftype)
|
516
|
509
|
|
517
|
510
|
return res
|
518
|
|
-
|
|
511
|
+
|
519
|
512
|
## @brief Returns a tuple (pkname, pk_ftype)
|
520
|
513
|
@property
|
521
|
514
|
def _common_field_pk(self):
|
|
@@ -523,13 +516,13 @@ FOR EACH ROW SET {col_val_list};""".format(
|
523
|
516
|
if fta['fieldtype'] == 'pk':
|
524
|
517
|
return (fname, self._common_field_to_ftype(fname))
|
525
|
518
|
return (None, None)
|
526
|
|
-
|
|
519
|
+
|
527
|
520
|
## @brief Returns a tuple (rel_pkname, rel_ftype)
|
528
|
521
|
# @todo do it
|
529
|
522
|
@property
|
530
|
523
|
def _relation_pk(self):
|
531
|
524
|
return (MySQL.relations_pkname, EditorialModel.fieldtypes.pk.EmFieldType())
|
532
|
|
-
|
|
525
|
+
|
533
|
526
|
## @brief Returns a dict { colname:fieldtype } of relation table columns
|
534
|
527
|
@property
|
535
|
528
|
def _relation_cols(self):
|
|
@@ -548,6 +541,5 @@ FOR EACH ROW SET {col_val_list};""".format(
|
548
|
541
|
def _common_field_to_ftype(self, cname):
|
549
|
542
|
fta = copy.copy(EditorialModel.classtypes.common_fields[cname])
|
550
|
543
|
fto = EditorialModel.fieldtypes.generic.GenericFieldType.from_name(fta['fieldtype'])
|
551
|
|
- del(fta['fieldtype'])
|
|
544
|
+ del fta['fieldtype']
|
552
|
545
|
return fto(**fta)
|
553
|
|
-
|