|
@@ -17,6 +17,7 @@ import mosql.mysql
|
17
|
17
|
from DataSource.MySQL.MySQL import MySQL
|
18
|
18
|
from EditorialModel.classtypes import EmNature
|
19
|
19
|
|
|
20
|
+
|
20
|
21
|
## MySQL DataSource for LeObject
|
21
|
22
|
class LeDataSourceSQL(DummyDatasource):
|
22
|
23
|
|
|
@@ -32,62 +33,35 @@ class LeDataSourceSQL(DummyDatasource):
|
32
|
33
|
del conn_args['module']
|
33
|
34
|
self.connection = Database(self.module, **conn_args)
|
34
|
35
|
|
35
|
|
- ## @brief inserts a new object
|
36
|
|
- # @param letype LeType
|
37
|
|
- # @param leclass LeClass
|
38
|
|
- # @param datas dict : dictionnary of field:value pairs to save
|
39
|
|
- # @return int : lodel_id of the created object
|
40
|
|
- # @todo add the returning clause and the insertion in "object"
|
41
|
|
- def insert(self, letype, leclass, datas):
|
42
|
|
- if isinstance(datas, list):
|
43
|
|
- res = list()
|
44
|
|
- for data in datas:
|
45
|
|
- res.append(self.insert(letype, leclass, data))
|
46
|
|
- return res if len(res)>1 else res[0]
|
47
|
|
- elif isinstance(datas, dict):
|
48
|
|
-
|
49
|
|
- object_datas = {'class_id': leclass._class_id, 'type_id': letype._type_id}
|
50
|
|
-
|
51
|
|
- cur = self.datasource_utils.query(self.connection, insert(self.datasource_utils.objects_table_name, object_datas))
|
52
|
|
- lodel_id = cur.lastrowid
|
53
|
|
-
|
54
|
|
- datas[self.datasource_utils.field_lodel_id] = lodel_id
|
55
|
|
- query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
56
|
|
- self.datasource_utils.query(self.connection, insert(query_table_name, datas))
|
57
|
|
-
|
58
|
|
- return lodel_id
|
59
|
|
-
|
60
|
|
- ## @brief search for a collection of objects
|
61
|
|
- # @param leclass LeClass
|
62
|
|
- # @param letype LeType
|
63
|
|
- # @field_list list
|
64
|
|
- # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
65
|
|
- # @param relation_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
66
|
|
- # @return list
|
67
|
|
- def get(self, leclass, letype, field_list, filters, relational_filters=None):
|
68
|
|
-
|
69
|
|
- if leclass is None:
|
|
36
|
+ ## @brief select lodel editorial components using given filters
|
|
37
|
+ # @param target_cls LeCrud(class): The component class concerned by the select (a LeCrud child class (not instance !) )
|
|
38
|
+ # @param filters list: List of filters (see @ref leobject_filters)
|
|
39
|
+ # @param rel_filters list: List of relational filters (see @ref leobject_filters)
|
|
40
|
+ # @return a list of LeCrud child classes
|
|
41
|
+ def select(self, target_cls, filters, rel_filters=None):
|
|
42
|
+ if target_cls is None:
|
70
|
43
|
query_table_name = self.datasource_utils.objects_table_name
|
71
|
44
|
else:
|
72
|
|
- query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
45
|
+ query_table_name = self.datasource_utils.get_table_name_from_class(target_cls.__name__)
|
|
46
|
+
|
73
|
47
|
where_filters = self._prepare_filters(filters, query_table_name)
|
74
|
48
|
join_fields = {}
|
75
|
49
|
|
76
|
|
- if relational_filters is not None and len(relational_filters) > 0:
|
77
|
|
- rel_filters = self._prepare_rel_filters(relational_filters)
|
|
50
|
+ if rel_filters is not None and len(rel_filters) > 0:
|
|
51
|
+ rel_filters = self._prepare_rel_filters(rel_filters)
|
78
|
52
|
for rel_filter in rel_filters:
|
79
|
53
|
# join condition
|
80
|
54
|
relation_table_join_field = "%s.%s" % (self.datasource_utils.relations_table_name, self.RELATIONS_POSITIONS_FIELDS[rel_filter['position']])
|
81
|
|
- query_table_join_field = "%s.%s" % (query_table_name, self.datasource_utils.field_lodel_id)
|
|
55
|
+ query_table_join_field = "%s.%s" % (query_table_name, self.datasource_utils.relations_field_nature)
|
82
|
56
|
join_fields[query_table_join_field] = relation_table_join_field
|
83
|
|
- # Adding "where" filters
|
|
57
|
+ # adding "where" filters
|
84
|
58
|
where_filters['%s.%s' % (self.datasource_utils.relations_table_name, self.datasource_utils.relations_field_nature)] = rel_filter['nature']
|
85
|
59
|
where_filters[rel_filter['condition_key']] = rel_filter['condition_value']
|
86
|
60
|
|
87
|
61
|
# building the query
|
88
|
|
- query = select(query_table_name, where=where_filters, select=field_list, joins=join(self.datasource_utils.relations_table_name, join_fields))
|
|
62
|
+ query = select(query_table_name, where=where_filters, joins=join(self.datasource_utils.relations_table_name, join_fields))
|
89
|
63
|
else:
|
90
|
|
- query = select(query_table_name, where=where_filters, select=field_list)
|
|
64
|
+ query = select(query_table_name, where=where_filters)
|
91
|
65
|
|
92
|
66
|
# Executing the query
|
93
|
67
|
cur = self.datasource_utils.query(self.connection, query)
|
|
@@ -95,20 +69,19 @@ class LeDataSourceSQL(DummyDatasource):
|
95
|
69
|
|
96
|
70
|
return results
|
97
|
71
|
|
98
|
|
- ## @brief delete an existing object
|
99
|
|
- # @param letype LeType
|
100
|
|
- # @param leclass LeClass
|
101
|
|
- # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
102
|
|
- # @param relational_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
103
|
|
- # @return bool : True on success
|
104
|
|
- def delete(self, letype, leclass, filters, relational_filters):
|
105
|
|
- query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
72
|
+ ## @brief delete lodel editorial components given filters
|
|
73
|
+ # @param target_cls LeCrud(class): The component class concerned by the delete (a LeCrud child class (not instance !) )
|
|
74
|
+ # @param filters list : List of filters (see @ref leobject_filters)
|
|
75
|
+ # @param rel_filters list : List of relational filters (see @ref leobject_filters)
|
|
76
|
+ # @return the number of deleted components
|
|
77
|
+ # TODO Retourner le nombre de lignes supprimées
|
|
78
|
+ def delete(self, target_cls, filters, rel_filters):
|
|
79
|
+ query_table_name = self.datasource_utils.get_table_name_from_class(target_cls.__name__)
|
106
|
80
|
prep_filters = self._prepare_filters(filters, query_table_name)
|
107
|
|
- prep_rel_filters = self._prepare_rel_filters(relational_filters)
|
|
81
|
+ prep_rel_filters = self._prepare_rel_filters(rel_filters)
|
108
|
82
|
|
109
|
83
|
if len(prep_rel_filters) > 0:
|
110
|
|
- query = "DELETE %s FROM " % query_table_name
|
111
|
|
-
|
|
84
|
+ query = "DELETE %s FROM" % query_table_name
|
112
|
85
|
for prep_rel_filter in prep_rel_filters:
|
113
|
86
|
query += "%s INNER JOIN %s ON (%s.%s = %s.%s)" % (
|
114
|
87
|
self.datasource_utils.relations_table_name,
|
|
@@ -139,29 +112,52 @@ class LeDataSourceSQL(DummyDatasource):
|
139
|
112
|
|
140
|
113
|
return True
|
141
|
114
|
|
142
|
|
- ## @brief update an existing object's data
|
143
|
|
- # @param letype LeType
|
144
|
|
- # @param leclass LeClass
|
145
|
|
- # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
146
|
|
- # @param rel_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
147
|
|
- # @param data dict
|
148
|
|
- # @return bool
|
149
|
|
- # @todo prendre en compte les rel_filters
|
150
|
|
- def update(self, letype, leclass, filters, rel_filters, data):
|
151
|
|
-
|
152
|
|
- query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
115
|
+ ## @brief update an existing lodel editorial component
|
|
116
|
+ # @param target_cls LeCrud(class) : The component class concerned by the update (a LeCrud child class (not instance !) )
|
|
117
|
+ # @param filters list : List of filters (see @ref leobject_filters)
|
|
118
|
+ # @param rel_filters list : List of relationnal filters (see @ref leobject_filters)
|
|
119
|
+ # @param **datas : Datas in kwargs
|
|
120
|
+ # @return the number of updated components
|
|
121
|
+ # @TODO Retourner le nombre de lignes modifiées
|
|
122
|
+ # @TODO Prendre en charge les rel_filters
|
|
123
|
+ def update(self, target_cls, filters, rel_filters, **datas):
|
|
124
|
+ query_table_name = self.datasource_utils.get_table_name_from_class(target_cls.__name__)
|
153
|
125
|
where_filters = filters
|
154
|
|
- set_data = data
|
155
|
|
-
|
156
|
|
- prepared_rel_filters = self._prepare_rel_filters(rel_filters)
|
157
|
|
-
|
158
|
|
- # Building the query
|
|
126
|
+ set_data = datas
|
|
127
|
+ if rel_filters is not None:
|
|
128
|
+ prep_rel_filters = self._prepare_rel_filters(rel_filters)
|
159
|
129
|
query = update(table=query_table_name, where=where_filters, set=set_data)
|
160
|
|
- # Executing the query
|
161
|
130
|
with self.connection as cur:
|
162
|
131
|
cur.execute(query)
|
163
|
132
|
return True
|
164
|
133
|
|
|
134
|
+ ## @brief inserts a new lodel editorial component
|
|
135
|
+ # @param target_cls LeCrud(class) : The component class concerned by the insert (a LeCrud child class (not instance !) )
|
|
136
|
+ # @param **datas : The datas to insert
|
|
137
|
+ # @return The inserted component's id
|
|
138
|
+ def insert(self, target_cls, **datas):
|
|
139
|
+ class_id = ''
|
|
140
|
+ type_id = ''
|
|
141
|
+ object_datas = {'class_id': class_id, 'type_id': type_id}
|
|
142
|
+ cur = self.datasource_utils.query(self.connection, insert(self.datasource_utils.objects_table_name, object_datas))
|
|
143
|
+ lodel_id = cur.lastrowid
|
|
144
|
+
|
|
145
|
+ datas[self.datasource_utils.field_lodel_id] = lodel_id
|
|
146
|
+ query_table_name = self.datasource_utils.get_table_name_from_class(target_cls.__name__)
|
|
147
|
+ self.datasource_utils.query(self.connection, insert(query_table_name, datas))
|
|
148
|
+
|
|
149
|
+ return lodel_id
|
|
150
|
+
|
|
151
|
+ ## @brief insert multiple editorial component
|
|
152
|
+ # @param target_cls LeCrud(class) : The component class concerned by the insert (a LeCrud child class (not instance !) )
|
|
153
|
+ # @param datas_list list : A list of dict representing the datas to insert
|
|
154
|
+ # @return int the number of inserted component
|
|
155
|
+ def insert_multi(self, target_cls, datas_list):
|
|
156
|
+ res = list()
|
|
157
|
+ for data in datas_list:
|
|
158
|
+ res.append(self.insert(target_cls, data))
|
|
159
|
+ return len(res)
|
|
160
|
+
|
165
|
161
|
## @brief prepares the relational filters
|
166
|
162
|
# @params rel_filters : (("superior"|"subordinate"), operator, value)
|
167
|
163
|
# @return list
|
|
@@ -196,6 +192,9 @@ class LeDataSourceSQL(DummyDatasource):
|
196
|
192
|
|
197
|
193
|
return prepared_filters
|
198
|
194
|
|
|
195
|
+ # ================================================================================================================ #
|
|
196
|
+ # FONCTIONS A DEPLACER #
|
|
197
|
+ # ================================================================================================================ #
|
199
|
198
|
|
200
|
199
|
## @brief Make a relation between 2 LeType
|
201
|
200
|
# @note rel2type relations. Superior is the LeType from the EmClass and subordinate the LeType for the EmType
|
|
@@ -205,15 +204,14 @@ class LeDataSourceSQL(DummyDatasource):
|
205
|
204
|
def add_related(self, lesup, lesub, rank, **rel_attr):
|
206
|
205
|
with self.connection as cur:
|
207
|
206
|
#First step : relation table insert
|
208
|
|
- sql = insert(MySQL.relations_table_name,{
|
209
|
|
- 'id_sup': lesup.lodel_id,
|
210
|
|
- 'id_sub': lesub.lodel_id,
|
211
|
|
- 'rank': 0, #default value that will be set latter
|
212
|
|
- })
|
|
207
|
+ sql = insert(MySQL.relations_table_name, {
|
|
208
|
+ 'id_sup': lesup.lodel_id,
|
|
209
|
+ 'id_sub': lesub.lodel_id,
|
|
210
|
+ 'rank': 0, # default value that will be set latter
|
|
211
|
+ })
|
213
|
212
|
cur.execute(sql)
|
214
|
213
|
relation_id = cur.lastrowid
|
215
|
214
|
|
216
|
|
-
|
217
|
215
|
if len(rel_attr) > 0:
|
218
|
216
|
#There is some relation attribute to add in another table
|
219
|
217
|
attr_table = get_r2t2table_name(lesup._leclass.__name__, lesub.__class__.__name__)
|
|
@@ -244,7 +242,6 @@ class LeDataSourceSQL(DummyDatasource):
|
244
|
242
|
else:
|
245
|
243
|
delete_params = del_params
|
246
|
244
|
|
247
|
|
-
|
248
|
245
|
sql = delete(
|
249
|
246
|
self.datasource_utils.relations_table_name,
|
250
|
247
|
delete_params
|
|
@@ -262,20 +259,21 @@ class LeDataSourceSQL(DummyDatasource):
|
262
|
259
|
# @return a list of dict { 'id_relation':.., 'rank':.., 'lesup':.., 'lesub'.., 'rel_attrs': dict() }
|
263
|
260
|
def get_related(self, leo, letype, get_sub=True):
|
264
|
261
|
if leapi.letype.LeType not in letype.__bases__:
|
265
|
|
- raise ValueError("letype argument should be a LeType child class, but got %s"%type(letype))
|
|
262
|
+ raise ValueError("letype argument should be a LeType child class, but got %s" % type(letype))
|
|
263
|
+
|
266
|
264
|
if not isinstance(leo, LeType):
|
267
|
|
- raise ValueError("leo argument should be a LeType child class instance but got %s"%type(leo))
|
|
265
|
+ raise ValueError("leo argument should be a LeType child class instance but got %s" % type(leo))
|
268
|
266
|
with self.connection as cur:
|
269
|
267
|
id_leo, id_type = 'id_sup', 'id_sub' if get_sub else 'id_sub', 'id_sup'
|
270
|
|
-
|
|
268
|
+
|
271
|
269
|
joins = [
|
272
|
270
|
join(
|
273
|
271
|
(MySQL.objects_table_name, 'o'),
|
274
|
|
- on={'r.'+id_type: 'o.'+MySQL.field_lodel_id}
|
|
272
|
+ on={'r.' + id_type: 'o.' + MySQL.field_lodel_id}
|
275
|
273
|
),
|
276
|
274
|
join(
|
277
|
275
|
(MySQL.objects_table_name, 'p'),
|
278
|
|
- on={'r.'+id_leo: 'p.'+MySQL.field_lodel_id}
|
|
276
|
+ on={'r.' + id_leo: 'p.' + MySQL.field_lodel_id}
|
279
|
277
|
),
|
280
|
278
|
]
|
281
|
279
|
|
|
@@ -284,14 +282,14 @@ class LeDataSourceSQL(DummyDatasource):
|
284
|
282
|
if len(lesup._linked_types[lesub]) > 0:
|
285
|
283
|
#relationnal attributes, need to join with r2t table
|
286
|
284
|
cls_name = leo.__class__.__name__ if get_sub else letype.__name__
|
287
|
|
- type_name = letype.__name__ if get_sub else leo.__class__.__name__
|
|
285
|
+ type_name = letype.__name__ if get_sub else leo.__class__.__name__
|
288
|
286
|
joins.append(
|
289
|
287
|
join(
|
290
|
288
|
(MySQL.get_r2t2table_name(cls_name, type_name), 'r2t'),
|
291
|
|
- on={'r.'+MySQL.relations_pkname: 'r2t'+MySQL.relations_pkname}
|
|
289
|
+ on={'r.' + MySQL.relations_pkname: 'r2t' + MySQL.relations_pkname}
|
292
|
290
|
)
|
293
|
291
|
)
|
294
|
|
- select=('r.id_relation', 'r.id_sup', 'r.id_sub', 'r.rank', 'r.depth', 'r2t.*')
|
|
292
|
+ select = ('r.id_relation', 'r.id_sup', 'r.id_sub', 'r.rank', 'r.depth', 'r2t.*')
|
295
|
293
|
else:
|
296
|
294
|
select = common_infos
|
297
|
295
|
|
|
@@ -307,13 +305,13 @@ class LeDataSourceSQL(DummyDatasource):
|
307
|
305
|
|
308
|
306
|
cur.execute(sql)
|
309
|
307
|
res = all_to_dicts(cur)
|
310
|
|
-
|
|
308
|
+
|
311
|
309
|
#Building result
|
312
|
310
|
ret = list()
|
313
|
311
|
for datas in res:
|
314
|
|
- r_letype = letype(res['r.'+id_type])
|
|
312
|
+ r_letype = letype(res['r.' + id_type])
|
315
|
313
|
ret_item = {
|
316
|
|
- 'id_relation':+datas[MySQL.relations_pkname],
|
|
314
|
+ 'id_relation': +datas[MySQL.relations_pkname],
|
317
|
315
|
'lesup': r_leo if get_sub else r_letype,
|
318
|
316
|
'lesub': r_letype if get_sub else r_leo,
|
319
|
317
|
'rank': res['rank']
|
|
@@ -321,12 +319,12 @@ class LeDataSourceSQL(DummyDatasource):
|
321
|
319
|
|
322
|
320
|
rel_attr = copy.copy(datas)
|
323
|
321
|
for todel in common_infos:
|
324
|
|
- del(rel_attr[todel])
|
|
322
|
+ del rel_attr[todel]
|
325
|
323
|
ret_item['rel_attrs'] = rel_attr
|
326
|
324
|
ret.append(ret_item)
|
327
|
325
|
|
328
|
326
|
return ret
|
329
|
|
-
|
|
327
|
+
|
330
|
328
|
## @brief Set the rank of a relation identified by its ID
|
331
|
329
|
# @param id_relation int : relation ID
|
332
|
330
|
# @param rank int|str : 'first', 'last', or an integer value
|
|
@@ -345,9 +343,9 @@ class LeDataSourceSQL(DummyDatasource):
|
345
|
343
|
# @param rank int|str : 'first', 'last', or an integer value
|
346
|
344
|
# @throw leapi.leapi.LeObjectQueryError if id_relation don't exists
|
347
|
345
|
def _set_relation_rank(self, id_relation, rank):
|
348
|
|
- ret = self.get_relation(id_relation, no_attr = True)
|
|
346
|
+ ret = self.get_relation(id_relation, no_attr=True)
|
349
|
347
|
if not ret:
|
350
|
|
- raise leapi.leapi.LeObjectQueryError("No relation with id_relation = %d"%id_relation)
|
|
348
|
+ raise leapi.leapi.LeObjectQueryError("No relation with id_relation = %d" % id_relation)
|
351
|
349
|
lesup = ret['lesup']
|
352
|
350
|
lesub = ret['lesup']
|
353
|
351
|
cur_rank = ret['rank']
|
|
@@ -361,27 +359,26 @@ class LeDataSourceSQL(DummyDatasource):
|
361
|
359
|
rank = len(relations)
|
362
|
360
|
if cur_rank == rank:
|
363
|
361
|
return True
|
364
|
|
-
|
|
362
|
+
|
365
|
363
|
#insert the relation at the good position
|
366
|
364
|
our_relation = relations.pop(cur_rank)
|
367
|
365
|
relations.insert(our_relation, rank)
|
368
|
366
|
|
369
|
367
|
#gathering (relation_id, new_rank)
|
370
|
|
- rdatas = [ (attrs['relation_id'], new_rank+1) for new_rank,(sup, sub, attrs) in enumerate(relations) ]
|
371
|
|
- sql = insert(MySQL.relations_table_name, columns=(MySQL.relations_pkname, 'rank'), values = rdatas, on_duplicate_key_update={'rank',mosql.util.raw('VALUES(`rank`)')})
|
|
368
|
+ rdatas = [(attrs['relation_id'], new_rank + 1) for new_rank, (sup, sub, attrs) in enumerate(relations)]
|
|
369
|
+ sql = insert(MySQL.relations_table_name, columns=(MySQL.relations_pkname, 'rank'), values=rdatas, on_duplicate_key_update={'rank', mosql.util.raw('VALUES(`rank`)')})
|
372
|
370
|
|
373
|
|
-
|
374
|
371
|
## @brief Check a rank value
|
375
|
372
|
# @param rank int | str : Can be an integer >= 1 , 'first' or 'last'
|
376
|
373
|
# @throw ValueError if the rank is not valid
|
377
|
374
|
def _check_rank(self, rank):
|
378
|
375
|
if isinstance(rank, str) and rank != 'first' and rank != 'last':
|
379
|
|
- raise ValueError("Invalid rank value : %s"%rank)
|
|
376
|
+ raise ValueError("Invalid rank value : %s" % rank)
|
380
|
377
|
elif isinstance(rank, int) and rank < 1:
|
381
|
|
- raise ValueError("Invalid rank value : %d"%rank)
|
|
378
|
+ raise ValueError("Invalid rank value : %d" % rank)
|
382
|
379
|
else:
|
383
|
|
- raise ValueError("Invalid rank type : %s"%type(rank))
|
384
|
|
-
|
|
380
|
+ raise ValueError("Invalid rank type : %s" % type(rank))
|
|
381
|
+
|
385
|
382
|
## @brief Link two object given a relation nature, depth and rank
|
386
|
383
|
# @param lesup LeObject : a LeObject
|
387
|
384
|
# @param lesub LeObject : a LeObject
|
|
@@ -404,17 +401,17 @@ class LeDataSourceSQL(DummyDatasource):
|
404
|
401
|
raise NotImplementedError()
|
405
|
402
|
|
406
|
403
|
return True
|
407
|
|
-
|
|
404
|
+
|
408
|
405
|
## @brief Delete a relation
|
409
|
406
|
# @warning this method may not be efficient
|
410
|
407
|
# @param id_relation int : The relation identifier
|
411
|
408
|
# @return bool
|
412
|
409
|
def del_relation(self, id_relation):
|
413
|
410
|
with self.connection as cur:
|
414
|
|
- pk_where = {MySQL.relations_pkname:id_relation}
|
|
411
|
+ pk_where = {MySQL.relations_pkname: id_relation}
|
415
|
412
|
if not MySQL.fk_on_delete_cascade and len(lesup._linked_types[lesub.__class__]) > 0:
|
416
|
413
|
#Delete the row in the relation attribute table
|
417
|
|
- ret = self.get_relation(id_relation, no_attr = False)
|
|
414
|
+ ret = self.get_relation(id_relation, no_attr=False)
|
418
|
415
|
lesup = ret['lesup']
|
419
|
416
|
lesub = ret['lesub']
|
420
|
417
|
sql = delete(MySQL.relations_table_name, pk_where)
|
|
@@ -425,14 +422,14 @@ class LeDataSourceSQL(DummyDatasource):
|
425
|
422
|
raise RuntimeError("Unknown SQL Error")
|
426
|
423
|
|
427
|
424
|
return True
|
428
|
|
-
|
|
425
|
+
|
429
|
426
|
## @brief Fetch a relation
|
430
|
427
|
# @param id_relation int : The relation identifier
|
431
|
428
|
# @param no_attr bool : If true dont fetch rel_attr
|
432
|
429
|
# @return a dict{'id_relation':.., 'lesup':.., 'lesub':..,'rank':.., 'depth':.., #if not none#'nature':.., #if exists#'dict_attr':..>}
|
433
|
430
|
#
|
434
|
431
|
# @todo TESTS
|
435
|
|
- def get_relation(self, id_relation, no_attr = False):
|
|
432
|
+ def get_relation(self, id_relation, no_attr=False):
|
436
|
433
|
relation = dict()
|
437
|
434
|
with self.connection as cur:
|
438
|
435
|
sql = select(MySQL.relation_table_name, {MySQL.relations_pkname: id_relation})
|
|
@@ -444,8 +441,8 @@ class LeDataSourceSQL(DummyDatasource):
|
444
|
441
|
if len(res) > 1:
|
445
|
442
|
raise RuntimeError("When selecting on primary key, get more than one result. Bailout")
|
446
|
443
|
|
447
|
|
- if res['nature'] != None:
|
448
|
|
- raise ValueError("The relation with id %d is not a rel2type relation"%id_relation)
|
|
444
|
+ if res['nature'] is not None:
|
|
445
|
+ raise ValueError("The relation with id %d is not a rel2type relation" % id_relation)
|
449
|
446
|
|
450
|
447
|
leobj = leapi.lefactory.LeFactory.leobj_from_name('LeObject')
|
451
|
448
|
lesup = leobj.uid2leobj(res['id_sup'])
|
|
@@ -456,9 +453,9 @@ class LeDataSourceSQL(DummyDatasource):
|
456
|
453
|
relation['lesub'] = lesub
|
457
|
454
|
relation['rank'] = rank
|
458
|
455
|
relation['depth'] = depth
|
459
|
|
- if not (res['nature'] is None):
|
|
456
|
+ if res['nature'] is not None:
|
460
|
457
|
relation['nature'] = res['nature']
|
461
|
|
-
|
|
458
|
+
|
462
|
459
|
if not no_attr and res['nature'] is None and len(lesup._linked_types[lesub.__class__]) != 0:
|
463
|
460
|
#Fetch relation attributes
|
464
|
461
|
rel_attr_table = MySQL.get_r2t2table_name(lesup.__class__.__name__, lesub.__class__.__name__)
|
|
@@ -482,7 +479,7 @@ class LeDataSourceSQL(DummyDatasource):
|
482
|
479
|
# @return a list of tuple (lesup, lesub, dict_attr)
|
483
|
480
|
def get_relations(self, leo):
|
484
|
481
|
|
485
|
|
- sql = select(self.datasource_utils.relations_table_name, where=or_(({'id_sub':leo.lodel_id},{'id_sup':leo.lodel_id})))
|
|
482
|
+ sql = select(self.datasource_utils.relations_table_name, where=or_(({'id_sub': leo.lodel_id}, {'id_sup': leo.lodel_id})))
|
486
|
483
|
|
487
|
484
|
with self.connection as cur:
|
488
|
485
|
results = all_to_dicts(cur.execute(sql))
|
|
@@ -510,11 +507,10 @@ class LeDataSourceSQL(DummyDatasource):
|
510
|
507
|
# @return The relation ID or False if fails
|
511
|
508
|
def add_superior(self, lesup, lesub, nature, rank, depth=None):
|
512
|
509
|
|
513
|
|
- params = {'id_sup': lesup.lodel_id,'id_sub': lesub.lodel_id,'nature': nature,'rank': rank}
|
|
510
|
+ params = {'id_sup': lesup.lodel_id, 'id_sub': lesub.lodel_id, 'nature': nature, 'rank': rank}
|
514
|
511
|
if depth is not None:
|
515
|
512
|
params['depth'] = depth
|
516
|
513
|
|
517
|
|
-
|
518
|
514
|
sql_insert = insert(self.datasource_utils.relations_table_name, params)
|
519
|
515
|
with self.connection as cur:
|
520
|
516
|
if cur.execute(sql_insert) != 1:
|
|
@@ -551,7 +547,7 @@ class LeDataSourceSQL(DummyDatasource):
|
551
|
547
|
superiors = [LeType(result['id_sup']) for result in results]
|
552
|
548
|
|
553
|
549
|
return superiors
|
554
|
|
-
|
|
550
|
+
|
555
|
551
|
## @brief Fetch the list of the subordinates given a nature
|
556
|
552
|
# @param lesup LeType : superior LeType child class instance
|
557
|
553
|
# @param nature str : A relation nature @ref EditorialModel.classtypes
|
|
@@ -569,3 +565,137 @@ class LeDataSourceSQL(DummyDatasource):
|
569
|
565
|
res = all_to_dicts(cur)
|
570
|
566
|
|
571
|
567
|
return [LeType(r['id_sup']) for r in res]
|
|
568
|
+
|
|
569
|
+ # ================================================================================================================ #
|
|
570
|
+ # FONCTIONS A SUPPRIMER #
|
|
571
|
+ # ================================================================================================================ #
|
|
572
|
+
|
|
573
|
+ ## @brief inserts a new object
|
|
574
|
+ # @param letype LeType
|
|
575
|
+ # @param leclass LeClass
|
|
576
|
+ # @param datas dict : dictionnary of field:value pairs to save
|
|
577
|
+ # @return int : lodel_id of the created object
|
|
578
|
+ # @todo add the returning clause and the insertion in "object"
|
|
579
|
+ # def insert(self, letype, leclass, datas):
|
|
580
|
+ # if isinstance(datas, list):
|
|
581
|
+ # res = list()
|
|
582
|
+ # for data in datas:
|
|
583
|
+ # res.append(self.insert(letype, leclass, data))
|
|
584
|
+ # return res if len(res)>1 else res[0]
|
|
585
|
+ # elif isinstance(datas, dict):
|
|
586
|
+ #
|
|
587
|
+ # object_datas = {'class_id': leclass._class_id, 'type_id': letype._type_id}
|
|
588
|
+ #
|
|
589
|
+ # cur = self.datasource_utils.query(self.connection, insert(self.datasource_utils.objects_table_name, object_datas))
|
|
590
|
+ # lodel_id = cur.lastrowid
|
|
591
|
+ #
|
|
592
|
+ # datas[self.datasource_utils.field_lodel_id] = lodel_id
|
|
593
|
+ # query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
594
|
+ # self.datasource_utils.query(self.connection, insert(query_table_name, datas))
|
|
595
|
+ #
|
|
596
|
+ # return lodel_id
|
|
597
|
+
|
|
598
|
+ ## @brief search for a collection of objects
|
|
599
|
+ # @param leclass LeClass
|
|
600
|
+ # @param letype LeType
|
|
601
|
+ # @field_list list
|
|
602
|
+ # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
|
603
|
+ # @param relation_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
|
604
|
+ # @return list
|
|
605
|
+ # def get(self, leclass, letype, field_list, filters, relational_filters=None):
|
|
606
|
+ #
|
|
607
|
+ # if leclass is None:
|
|
608
|
+ # query_table_name = self.datasource_utils.objects_table_name
|
|
609
|
+ # else:
|
|
610
|
+ # query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
611
|
+ # where_filters = self._prepare_filters(filters, query_table_name)
|
|
612
|
+ # join_fields = {}
|
|
613
|
+ #
|
|
614
|
+ # if relational_filters is not None and len(relational_filters) > 0:
|
|
615
|
+ # rel_filters = self._prepare_rel_filters(relational_filters)
|
|
616
|
+ # for rel_filter in rel_filters:
|
|
617
|
+ # # join condition
|
|
618
|
+ # relation_table_join_field = "%s.%s" % (self.datasource_utils.relations_table_name, self.RELATIONS_POSITIONS_FIELDS[rel_filter['position']])
|
|
619
|
+ # query_table_join_field = "%s.%s" % (query_table_name, self.datasource_utils.field_lodel_id)
|
|
620
|
+ # join_fields[query_table_join_field] = relation_table_join_field
|
|
621
|
+ # # Adding "where" filters
|
|
622
|
+ # where_filters['%s.%s' % (self.datasource_utils.relations_table_name, self.datasource_utils.relations_field_nature)] = rel_filter['nature']
|
|
623
|
+ # where_filters[rel_filter['condition_key']] = rel_filter['condition_value']
|
|
624
|
+ #
|
|
625
|
+ # # building the query
|
|
626
|
+ # query = select(query_table_name, where=where_filters, select=field_list, joins=join(self.datasource_utils.relations_table_name, join_fields))
|
|
627
|
+ # else:
|
|
628
|
+ # query = select(query_table_name, where=where_filters, select=field_list)
|
|
629
|
+ #
|
|
630
|
+ # Executing the query
|
|
631
|
+ # cur = self.datasource_utils.query(self.connection, query)
|
|
632
|
+ # results = all_to_dicts(cur)
|
|
633
|
+ #
|
|
634
|
+ # return results
|
|
635
|
+
|
|
636
|
+ ## @brief delete an existing object
|
|
637
|
+ # @param letype LeType
|
|
638
|
+ # @param leclass LeClass
|
|
639
|
+ # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
|
640
|
+ # @param relational_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
|
641
|
+ # @return bool : True on success
|
|
642
|
+ # def delete(self, letype, leclass, filters, relational_filters):
|
|
643
|
+ # query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
644
|
+ # prep_filters = self._prepare_filters(filters, query_table_name)
|
|
645
|
+ # prep_rel_filters = self._prepare_rel_filters(relational_filters)
|
|
646
|
+ #
|
|
647
|
+ # if len(prep_rel_filters) > 0:
|
|
648
|
+ # query = "DELETE %s FROM " % query_table_name
|
|
649
|
+ #
|
|
650
|
+ # for prep_rel_filter in prep_rel_filters:
|
|
651
|
+ # query += "%s INNER JOIN %s ON (%s.%s = %s.%s)" % (
|
|
652
|
+ # self.datasource_utils.relations_table_name,
|
|
653
|
+ # query_table_name,
|
|
654
|
+ # self.datasource_utils.relations_table_name,
|
|
655
|
+ # prep_rel_filter['position'],
|
|
656
|
+ # query_table_name,
|
|
657
|
+ # self.datasource_utils.field_lodel_id
|
|
658
|
+ # )
|
|
659
|
+ #
|
|
660
|
+ # if prep_rel_filter['condition_key'][0] is not None:
|
|
661
|
+ # prep_filters[("%s.%s" % (self.datasource_utils.relations_table_name, prep_rel_filter['condition_key'][0]), prep_rel_filter['condition_key'][1])] = prep_rel_filter['condition_value']
|
|
662
|
+ #
|
|
663
|
+ # if prep_filters is not None and len(prep_filters) > 0:
|
|
664
|
+ # query += " WHERE "
|
|
665
|
+ # filter_counter = 0
|
|
666
|
+ # for filter_item in prep_filters:
|
|
667
|
+ # if filter_counter > 1:
|
|
668
|
+ # query += " AND "
|
|
669
|
+ # query += "%s %s %s" % (filter_item[0][0], filter_item[0][1], filter_item[1])
|
|
670
|
+ # else:
|
|
671
|
+ # query = delete(query_table_name, filters)
|
|
672
|
+ #
|
|
673
|
+ # query_delete_from_object = delete(self.datasource_utils.objects_table_name, {'lodel_id': filters['lodel_id']})
|
|
674
|
+ # with self.connection as cur:
|
|
675
|
+ # cur.execute(query)
|
|
676
|
+ # cur.execute(query_delete_from_object)
|
|
677
|
+ #
|
|
678
|
+ # return True
|
|
679
|
+
|
|
680
|
+ ## @brief update an existing object's data
|
|
681
|
+ # @param letype LeType
|
|
682
|
+ # @param leclass LeClass
|
|
683
|
+ # @param filters list : list of tuples formatted as (FIELD, OPERATOR, VALUE)
|
|
684
|
+ # @param rel_filters list : list of tuples formatted as (('superior'|'subordinate', FIELD), OPERATOR, VALUE)
|
|
685
|
+ # @param data dict
|
|
686
|
+ # @return bool
|
|
687
|
+ # @todo prendre en compte les rel_filters
|
|
688
|
+ # def update(self, letype, leclass, filters, rel_filters, data):
|
|
689
|
+ #
|
|
690
|
+ # query_table_name = self.datasource_utils.get_table_name_from_class(leclass.__name__)
|
|
691
|
+ # where_filters = filters
|
|
692
|
+ # set_data = data
|
|
693
|
+ #
|
|
694
|
+ # prepared_rel_filters = self._prepare_rel_filters(rel_filters)
|
|
695
|
+ #
|
|
696
|
+ # Building the query
|
|
697
|
+ # query = update(table=query_table_name, where=where_filters, set=set_data)
|
|
698
|
+ # Executing the query
|
|
699
|
+ # with self.connection as cur:
|
|
700
|
+ # cur.execute(query)
|
|
701
|
+ # return True
|