|
@@ -0,0 +1,122 @@
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+## @package EditorialModel.migrationhandler.sql
|
|
4
|
+# @brief A dummy migration handler
|
|
5
|
+#
|
|
6
|
+# According to it every modifications are possible
|
|
7
|
+#
|
|
8
|
+
|
|
9
|
+from EditorialModel.migrationhandler.dummy import DummyMigrationHandler
|
|
10
|
+from EditorialModel.model import Model
|
|
11
|
+from mosql.db import Database
|
|
12
|
+from Lodel.utils.mosql import create, alter_add
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+## Manage Model changes
|
|
16
|
+class SQLMigrationHandler(DummyMigrationHandler):
|
|
17
|
+
|
|
18
|
+ fieldtype_to_sql = {
|
|
19
|
+ 'char': "CHAR(255)",
|
|
20
|
+ 'int': 'INT'
|
|
21
|
+ }
|
|
22
|
+
|
|
23
|
+ def __init__(self, module=None, *conn_args, **conn_kargs):
|
|
24
|
+ self.db = Database(module, *conn_args, **conn_kargs)
|
|
25
|
+ super(SQLMigrationHandler, self).__init__(False)
|
|
26
|
+ # @todo vérification de l'existance de la table objects et de la table relation
|
|
27
|
+ self._install_tables()
|
|
28
|
+
|
|
29
|
+ ## @brief Record a change in the EditorialModel and indicate wether or not it is possible to make it
|
|
30
|
+ # @note The states ( initial_state and new_state ) contains only fields that changes
|
|
31
|
+ # @param model model : The EditorialModel.model object to provide the global context
|
|
32
|
+ # @param uid int : The uid of the change EmComponent
|
|
33
|
+ # @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.
|
|
34
|
+ # @param new_state dict | None : dict with field name as key and field value as value. Representing the new state. None mean component deletion
|
|
35
|
+ # @throw EditorialModel.exceptions.MigrationHandlerChangeError if the change was refused
|
|
36
|
+ def register_change(self, model, uid, initial_state, new_state):
|
|
37
|
+ #print(uid, initial_state, new_state)
|
|
38
|
+ # find type of component change
|
|
39
|
+ component = Model.name_from_emclass(type(model.component(uid)))
|
|
40
|
+ #print ("ça", component, type(model.component(uid)))
|
|
41
|
+ if initial_state is None:
|
|
42
|
+ state_change = 'new'
|
|
43
|
+ elif new_state is None:
|
|
44
|
+ state_change = 'del'
|
|
45
|
+ else:
|
|
46
|
+ state_change = 'upgrade'
|
|
47
|
+
|
|
48
|
+ if component == 'EmType' and len(new_state) == 1:
|
|
49
|
+ if 'superiors_list' in new_state:
|
|
50
|
+ what = 'superiors_list'
|
|
51
|
+ elif 'fields_list' in new_state:
|
|
52
|
+ what = 'fields_list'
|
|
53
|
+ else:
|
|
54
|
+ what = component
|
|
55
|
+
|
|
56
|
+ handler_func = what + '_' + state_change
|
|
57
|
+ #print (handler_func)
|
|
58
|
+ if hasattr(self, handler_func):
|
|
59
|
+ getattr(self, handler_func)(model, uid, initial_state, new_state)
|
|
60
|
+ #print(handler_func, uid, initial_state, new_state)
|
|
61
|
+
|
|
62
|
+ # New Class, a table must be created
|
|
63
|
+ def EmClass_new(self, model, uid, initial_state, new_state):
|
|
64
|
+ class_table_name = self._class_table_name(new_state['name'])
|
|
65
|
+ self._query_bd(
|
|
66
|
+ create(table=class_table_name, column='id_lodel INT PRIMARY_KEY AUTOINCREMENT NOT NULL')
|
|
67
|
+ )
|
|
68
|
+
|
|
69
|
+ # New Field, must create a column in Class table or in Class_Type relational attribute table
|
|
70
|
+ def EmField_new(self, model, uid, initial_state, new_state):
|
|
71
|
+ # field is internal, create a column in the objects table
|
|
72
|
+ if new_state['internal']:
|
|
73
|
+ return
|
|
74
|
+ # field is of type rel2type, create the relational class_type table
|
|
75
|
+ elif new_state['fieldtype'] == 'rel2type':
|
|
76
|
+ # find relational_type name, and class name of the field
|
|
77
|
+ class_name = self._class_table_name_from_field(model, new_state)
|
|
78
|
+ type_name = model.component(new_state['rel_to_type_id']).name
|
|
79
|
+ table_name = class_name + '_' + type_name
|
|
80
|
+ self._query_bd(
|
|
81
|
+ create(table=table_name, column='id_lodel INT PRIMARY_KEY AUTOINCREMENT NOT NULL'),
|
|
82
|
+ )
|
|
83
|
+ #print('create rel2type table', class_name, type_name)
|
|
84
|
+ return
|
|
85
|
+ # field is relational (rel_field_id), create a column in the class_type table
|
|
86
|
+ elif new_state['rel_field_id']:
|
|
87
|
+ class_name = self._class_table_name_from_field(model, new_state)
|
|
88
|
+ rel_type_id = model.component(new_state['rel_field_id']).rel_to_type_id
|
|
89
|
+ type_name = model.component(rel_type_id).name
|
|
90
|
+ table_name = class_name + '_' + type_name
|
|
91
|
+ #print('create field in rel2type table', new_state, class_name, rel_type_id, type_name)
|
|
92
|
+ # else create a column in the class table
|
|
93
|
+ else:
|
|
94
|
+ # find name of the class table, and type of the field
|
|
95
|
+ table_name = self._class_table_name_from_field(model, new_state)
|
|
96
|
+
|
|
97
|
+ fieldtype = SQLMigrationHandler.fieldtype_to_sql[new_state['fieldtype']]
|
|
98
|
+ self._query_bd(
|
|
99
|
+ alter_add(table=table_name, column=new_state['name'] + ' ' + fieldtype)
|
|
100
|
+ )
|
|
101
|
+
|
|
102
|
+ # Test if internal tables must be created, create it if it must
|
|
103
|
+ def _install_tables(self):
|
|
104
|
+ self._query_bd(
|
|
105
|
+ create(table='object', column='id_lodel INT PRIMARY_KEY AUTOINCREMENT NOT NULL'),
|
|
106
|
+ create(table='relation', column=('id_relation INT PRIMARY_KEY AUTOINCREMENT NOT NULL', 'id_superior INT', 'id_subdordinate INT', 'nature CHAR(255)', 'depth INT', 'rank INT'))
|
|
107
|
+ )
|
|
108
|
+
|
|
109
|
+ def _query_bd(self, *queries):
|
|
110
|
+ with self.db as cur:
|
|
111
|
+ for query in queries:
|
|
112
|
+ print(query)
|
|
113
|
+ cur.execute(query)
|
|
114
|
+
|
|
115
|
+ def _class_table_name(self, class_name):
|
|
116
|
+ return class_name
|
|
117
|
+
|
|
118
|
+ def _class_table_name_from_field(self, model, field):
|
|
119
|
+ fieldgroup_id = model.component(field['fieldgroup_id']).class_id
|
|
120
|
+ class_name = model.component(fieldgroup_id).name
|
|
121
|
+ class_table_name = self._class_table_name(class_name)
|
|
122
|
+ return class_table_name
|