Browse Source

Add rel2type attribute handling

Yann Weber 9 years ago
parent
commit
95c1870f17
1 changed files with 92 additions and 34 deletions
  1. 92
    34
      EditorialModel/migrationhandler/mysql.py

+ 92
- 34
EditorialModel/migrationhandler/mysql.py View File

@@ -18,15 +18,22 @@ import EditorialModel
18 18
 # - EmClass deletion (untested)
19 19
 # - EmField creation
20 20
 # - EmField deletion (untested)
21
+# - rel2type attribute creation
22
+# - rel2type attribute deletion (unstested)
21 23
 #
22 24
 # Unsupported operations :
23 25
 # - EmClass rename
24 26
 # - EmField rename
27
+# - rel2type field rename
28
+# - rel2type attribute rename
29
+# 
25 30
 
26 31
 ## @brief Modify a MySQL database given editorial model changes
27 32
 class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigrationHandler):
28 33
     
34
+    ## @brief Object table name
29 35
     _object_tname = 'object'
36
+    ## @brief Relation table name
30 37
     _relation_tname = 'relation'
31 38
 
32 39
     ## @brief Construct a MysqlMigrationHandler
@@ -59,17 +66,25 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
59 66
                 self.delete_emclass_table(em, uid)
60 67
         elif isinstance(em.component(uid), EditorialModel.fields.EmField):
61 68
             emfield = em.component(uid)
62
-            if initial_state is None:
63
-                #EmField creation
64
-                if not(emfield.name in EditorialModel.classtypes.common_fields.keys()):
65
-                    self.add_col_from_emfield(em,uid)
66
-            elif new_state is None:
67
-                #EmField deletion
68
-                if not (emfield.name in EditorialModel.classtypes.common_fields.keys()):
69
-                    self.del_col_from_emfield(em, uid)
70
-                pass
71
-        pass
72
-
69
+            if emfield.rel_field_id is None:
70
+                #non rlationnal field
71
+                if initial_state is None:
72
+                    #non relationnal EmField creation
73
+                    if not(emfield.name in EditorialModel.classtypes.common_fields.keys()):
74
+                        self.add_col_from_emfield(em,uid)
75
+                elif new_state is None:
76
+                    #non relationnal EmField deletion
77
+                    if not (emfield.name in EditorialModel.classtypes.common_fields.keys()):
78
+                        self.del_col_from_emfield(em, uid)
79
+            else:
80
+                #relationnal field
81
+                if initial_state is None:
82
+                    #Rel2type attr creation
83
+                    self.add_relationnal_field(em, uid)
84
+                elif new_state is None:
85
+                    #Rel2type attr deletion
86
+                    self.del_relationnal_field(em, uid)
87
+    ## @brief dumdumdummy
73 88
     def register_model_state(self, em, state_hash):
74 89
         pass
75 90
 
@@ -80,6 +95,53 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
80 95
         if not self.dryrun:
81 96
             self.db.query(query)
82 97
     
98
+    ## @brief Add a relationnal field
99
+    #
100
+    # Add a rel2type attribute
101
+    # @note this function handles the table creation
102
+    # @param em Model : EditorialModel.model.Model instance
103
+    # @param rfuid int : Relationnal field uid
104
+    def add_relationnal_field(self, em, rfuid):
105
+        emfield = em.component(rfuid)
106
+        if not isinstance(emfield, EditorialModel.fields.EmField):
107
+            raise ValueError("The given uid is not an EmField uid")
108
+
109
+        r2tf = em.component(emfield.rel_field_id)
110
+        tname = self._r2t2table_name(em, r2tf)
111
+        pkname, pkftype = self._relation_pk
112
+    
113
+        #If not exists create a relational table
114
+        self._create_table(tname, pkname, pkftype, self.db_engine, if_exists = 'nothing')
115
+        #Add a foreign key if wanted
116
+        if self.foreign_keys:
117
+            self._add_fk(tname, self._relation_tname, pkname, pkname)
118
+        #Add the column
119
+        self._add_column(tname, emfield.name, emfield.fieldtype_instance())
120
+        #Update table triggers
121
+        self._generate_triggers(tname, self._r2type2cols(em, r2tf))
122
+    
123
+    ## @brief Delete a rel2type attribute
124
+    #
125
+    # Delete a rel2type attribute
126
+    # @note this method handles the table deletion
127
+    # @param em Model : EditorialModel.model.Model instance
128
+    # @param rfuid int : Relationnal field uid
129
+    def del_relationnal_field(self, em, rfuid):
130
+        emfield = em.component(rfuid)
131
+        if not isinstance(emfield, EditorialModel.fields.EmField):
132
+            raise ValueError("The given uid is not an EmField uid")
133
+
134
+        r2tf = em.component(emfield.rel_field_id)
135
+        tname = self._r2t2table_name(em, r2tf)
136
+        
137
+        if len(self._r2type2cols(em, r2tf)) == 1:
138
+            #The table can be deleted (no more attribute for this rel2type)
139
+            self._query("""DROP TABLE {table_name}""".format(table_name = tname))
140
+        else:
141
+            self._del_column(tname, emfield.name)
142
+            #Update table triggers
143
+            self._generate_triggers(tname, self._r2type2cols(em, r2tf))
144
+
83 145
     ## @brief Given an EmField uid add a column to the corresponding table
84 146
     # @param em Model : A Model instance
85 147
     # @param uid int : An EmField uid
@@ -152,8 +214,23 @@ class MysqlMigrationHandler(EditorialModel.migrationhandler.dummy.DummyMigration
152 214
     # @return a table name
153 215
     def _emclass2table_name(self, emclass):
154 216
         return "class_%s"%emclass.name
217
+    
218
+    ## @brief Construct a table name given a rela2type EmField instance
219
+    # @param em Model : A Model instance
220
+    # @param emfield EmField : An EmField instance
221
+    # @return a table name
222
+    def _r2t2table_name(self, em, emfield):
223
+        emclass = emfield.em_class
224
+        emtype = em.component(emfield.rel_to_type_id)
225
+        return "%s_%s_%s"%(emclass.name, emtype.name, emfield.name)
226
+     
227
+    ## @brief Generate a columns_fieldtype dict given a rel2type EmField
228
+    # @param em Model : an @ref EditorialModel.model.Model instance
229
+    # @param emfield EmField : and @ref EditorialModel.fields.EmField instance
230
+    def _r2type2cols(self, em, emfield):
231
+        return { f.name: f.fieldtype_instance() for f in em.components('EmField') if f.rel_field_id == emfield.uid }
155 232
         
156
-    ## @brief Generate a columns_fieldtype dict given an EmClass uid
233
+    ## @brief Generate a columns_fieldtype dict given an EmClass
157 234
     # @param emclass EmClass : An EmClass instance
158 235
     # @return A dict with column name as key and EmFieldType instance as value
159 236
     def _class2cols(self, emclass):
@@ -350,32 +427,12 @@ FOR EACH ROW SET {col_val_list};""".format(
350 427
             self._query(trig_q)
351 428
 
352 429
     ## @brief Identifier escaping
430
+    # @param idname str : An SQL identifier
353 431
     def _idname_escape(self, idname):
354 432
         if '`' in idname:
355 433
             raise ValueError("Invalid name : '%s'"%idname)
356 434
         return '`%s`'%idname
357 435
 
358
-    ## @brief Forge a create table query
359
-    # @param table_name str : The name of the table we want to create
360
-    # @param colspecs list : List of tuple (fieldname, EmFieldTypes)
361
-    # @return A MySQL create table query
362
-    #def _create_table_query(self, table_name, colspecs):
363
-    #    pass
364
-    
365
-    ## @brief Forge a drop column query
366
-    # @param table_name str : The name of the concerned table
367
-    # @param colname str : The name of the column we want to drop
368
-    # @return A MySQL drop column query
369
-    def _drop_column_query(self, table_name, colname):
370
-        pass
371
-
372
-    ## @brief Forge an add column query
373
-    # @param table_name str : The name of the concerned table
374
-    # @param colspec tuple : A tuple (colname, EmFieldType)
375
-    # @return A MySQL add column query
376
-    def _add_colum_query(self, table_name, colspec):
377
-        pass
378
-
379 436
     ## @brief Returns column specs from fieldtype
380 437
     # @param emfieldtype EmFieldType : An EmFieldType insance
381 438
     # @todo escape default value
@@ -440,7 +497,8 @@ FOR EACH ROW SET {col_val_list};""".format(
440 497
     @property
441 498
     def _relation_pk(self):
442 499
         return ('id_relation', EditorialModel.fieldtypes.pk.EmFieldType())
443
-
500
+    
501
+    ## @brief Returns a dict { colname:fieldtype } of relation table columns
444 502
     @property
445 503
     def _relation_cols(self):
446 504
         from_name = EditorialModel.fieldtypes.generic.GenericFieldType.from_name

Loading…
Cancel
Save