|
@@ -202,6 +202,9 @@ class MongoDbDatasource(object):
|
202
|
202
|
#Non abstract beahavior
|
203
|
203
|
mongo_filters = self.__process_filters(
|
204
|
204
|
target, filters, relational_filters)
|
|
205
|
+ #Updating backref before deletion
|
|
206
|
+ self.__update_backref_filtered(target, filters, relational_filters,
|
|
207
|
+ None)
|
205
|
208
|
res = self.__collection(target).delete_many(mongo_filters)
|
206
|
209
|
return res.deleted_count
|
207
|
210
|
|
|
@@ -220,7 +223,8 @@ class MongoDbDatasource(object):
|
220
|
223
|
mongo_filters = self.__process_filters(
|
221
|
224
|
target, filters, relational_filters)
|
222
|
225
|
res = self.__collection(target).update(mongo_filters, upd_datas)
|
223
|
|
- target.make_consistency(datas=upd_datas, type_query='update')
|
|
226
|
+ self.__update_backref_filtered(target, filters, relational_filters,
|
|
227
|
+ upd_datas)
|
224
|
228
|
return res['n']
|
225
|
229
|
|
226
|
230
|
## @brief Inserts a record in a given collection
|
|
@@ -229,7 +233,7 @@ class MongoDbDatasource(object):
|
229
|
233
|
# @return the inserted uid
|
230
|
234
|
def insert(self, target, new_datas):
|
231
|
235
|
res = self.__collection(target).insert(new_datas)
|
232
|
|
- target.make_consistency(datas=new_datas)
|
|
236
|
+ self.__update_backref(target, None, new_datas)
|
233
|
237
|
return str(res)
|
234
|
238
|
|
235
|
239
|
## @brief Inserts a list of records in a given collection
|
|
@@ -239,9 +243,23 @@ class MongoDbDatasource(object):
|
239
|
243
|
def insert_multi(self, target, datas_list):
|
240
|
244
|
res = self.__collection(target).insert_many(datas_list)
|
241
|
245
|
for new_datas in datas_list:
|
|
246
|
+ self.__update_backref(target, None, new_datas)
|
242
|
247
|
target.make_consistency(datas=new_datas)
|
243
|
248
|
return list(res.inserted_ids)
|
244
|
249
|
|
|
250
|
+ ##@brief Update backref giving an action
|
|
251
|
+ #@param target leObject child class
|
|
252
|
+ #@param filters
|
|
253
|
+ #@param relational_filters,
|
|
254
|
+ #@param datas None | dict : optional new datas if None mean we are deleting
|
|
255
|
+ #@return nothing (for the moment
|
|
256
|
+ def __update_backref_filtered(self, target, act,
|
|
257
|
+ filters, relational_filters, datas = None):
|
|
258
|
+ #gathering datas
|
|
259
|
+ old_datas_l = target.select(target, None, filters, relational_filters)
|
|
260
|
+ for old_datas in old_datas_l:
|
|
261
|
+ self.__update_backref(target, old_datas, datas)
|
|
262
|
+
|
245
|
263
|
##@brief Update back references of an object
|
246
|
264
|
#@ingroup plugin_mongodb_bref_op
|
247
|
265
|
#
|
|
@@ -284,16 +302,18 @@ class MongoDbDatasource(object):
|
284
|
302
|
# LeoClass2: {...
|
285
|
303
|
#
|
286
|
304
|
upd_dict = {}
|
287
|
|
- for fname, fdh in target.reference_handlers():
|
288
|
|
- oldd = fname in old_datas
|
289
|
|
- newd = fname in new_datas
|
|
305
|
+ for fname, fdh in target.reference_handlers().items():
|
|
306
|
+ oldd = old_datas is not None and fname in old_datas and \
|
|
307
|
+ hasattr(fdh, 'default') and old_datas[fname] != fdh.default
|
|
308
|
+ newd = new_datas is not None and fname in new_datas and \
|
|
309
|
+ hasattr(fdh, 'default') and new_datas[fname] != fdh.default
|
290
|
310
|
if (oldd and newd and old_datas[fname] == new_datas[fname])\
|
291
|
311
|
or not(oldd or newd):
|
292
|
312
|
#No changes or not concerned
|
293
|
313
|
continue
|
294
|
|
- bref_cls = fdh.data_handler[0]
|
295
|
|
- bref_fname = fdh.data_handler[1]
|
296
|
|
- if issubclass(fdh, MultipleRef):
|
|
314
|
+ bref_cls = fdh.back_reference[0]
|
|
315
|
+ bref_fname = fdh.back_reference[1]
|
|
316
|
+ if issubclass(fdh.__class__, MultipleRef):
|
297
|
317
|
#fdh is a multiple ref. So the update preparation will be
|
298
|
318
|
#divided into two loops :
|
299
|
319
|
#- one loop for deleting old datas
|
|
@@ -309,12 +329,12 @@ class MongoDbDatasource(object):
|
309
|
329
|
to_add = [ val
|
310
|
330
|
for val in new_values
|
311
|
331
|
if val not in old_values]
|
312
|
|
- elif oldd and not newdd:
|
313
|
|
- to_del = old_datas[fname]
|
|
332
|
+ elif oldd and not newd:
|
|
333
|
+ to_del = [old_datas[fname]]
|
314
|
334
|
to_add = []
|
315
|
|
- elif not oldd and newdd:
|
|
335
|
+ elif not oldd and newd:
|
316
|
336
|
to_del = []
|
317
|
|
- to_add = new_datas[fname]
|
|
337
|
+ to_add = [new_datas[fname]]
|
318
|
338
|
#Calling __back_ref_upd_one_value() with good arguments
|
319
|
339
|
for vtype, vlist in [('old',to_del), ('new', to_add)]:
|
320
|
340
|
for value in vlist:
|
|
@@ -402,7 +422,7 @@ class MongoDbDatasource(object):
|
402
|
422
|
old_value = old_datas[fname]
|
403
|
423
|
bref_cls, bref_leo, bref_dh, bref_val = self.__bref_get_check(
|
404
|
424
|
bref_cls, old_value, bref_fname)
|
405
|
|
- if issubclass(bref_dh, MultipleRef):
|
|
425
|
+ if issubclass(bref_dh.__class__, MultipleRef):
|
406
|
426
|
#
|
407
|
427
|
# Multiple ref update (iterable)
|
408
|
428
|
if old_value not in bref_val:
|
|
@@ -451,7 +471,7 @@ value : in %s field %s" % (bref_leo, ref_fname))
|
451
|
471
|
elif newd:
|
452
|
472
|
#It's an "insert"
|
453
|
473
|
new_value = new_datas[fname]
|
454
|
|
- if issubclass(bref_dh, MultipleRef):
|
|
474
|
+ if issubclass(bref_dh.__class__, MultipleRef):
|
455
|
475
|
if isinstance(bref_val, set):
|
456
|
476
|
bref_val |= set([new_value])
|
457
|
477
|
else:
|
|
@@ -463,6 +483,7 @@ value : in %s field %s" % (bref_leo, ref_fname))
|
463
|
483
|
|
464
|
484
|
|
465
|
485
|
##@brief Fetch back reference informations
|
|
486
|
+ #@warning thank's to __update_backref_act() this method is useless
|
466
|
487
|
#@param bref_cls LeObject child class : __back_reference[0]
|
467
|
488
|
#@param uidv mixed : UID value (the content of the reference field)
|
468
|
489
|
#@param bref_fname str : the name of the back_reference field
|
|
@@ -473,7 +494,7 @@ value : in %s field %s" % (bref_leo, ref_fname))
|
473
|
494
|
#@throw LodelFatalError if the back reference field is not a Reference
|
474
|
495
|
#subclass (major failure)
|
475
|
496
|
def __bref_get_check(self, bref_cls, uidv, bref_fname):
|
476
|
|
- bref_leo = bref_cls.get_from_uid(old_datas[fname])
|
|
497
|
+ bref_leo = bref_cls.get_from_uid(uidv)
|
477
|
498
|
if len(bref_leo) == 0:
|
478
|
499
|
raise MongoDbConsistencyError("Unable to get the object we make \
|
479
|
500
|
reference to : %s with uid = %s" % (bref_cls, repr(uidv)))
|
|
@@ -483,34 +504,6 @@ reference to : %s with uid = %s" % (bref_cls, repr(uidv)))
|
483
|
504
|
is not a reference : '%s' field '%s'" % (bref_leo, bref_fname))
|
484
|
505
|
bref_val = bref_leo.data(bref_fname)
|
485
|
506
|
return (bref_leo.__class__, bref_leo, bref_dh, bref_val)
|
486
|
|
-
|
487
|
|
-
|
488
|
|
-
|
489
|
|
-
|
490
|
|
- ##@defgroup plugin_mongodb_bref_op BackReferences operations
|
491
|
|
- #@brief Contains back_reference operations
|
492
|
|
- #@ingroup plugin_mongodb_datasource
|
493
|
|
- #
|
494
|
|
- #Back reference operations are implemented by privates functions
|
495
|
|
- # - __bref_op_update()
|
496
|
|
- # - __bref_op_delete()
|
497
|
|
- # - __bref_op_add()
|
498
|
|
- #
|
499
|
|
- #This 3 methods returns the same thing, a dict containing the field
|
500
|
|
- #name to update associated with the new value of this field.
|
501
|
|
- #
|
502
|
|
- #This 3 methods also expect that the following tests was done :
|
503
|
|
- # - the datahandler pointed by the back reference is a child class of
|
504
|
|
- #base_classes.Reference
|
505
|
|
- # - the value of this field contains or is the given old value (not for
|
506
|
|
- #the __bref_op_add() method)
|
507
|
|
- #
|
508
|
|
- #All this methods asserts that we allready checks that the given LeObject
|
509
|
|
- #instance concerned field (the one stored as back reference) is a child
|
510
|
|
- #class of base_classes.Reference
|
511
|
|
- #
|
512
|
|
- #@todo factorise __bref_op_update() and __bref_op_delete() and update this
|
513
|
|
- #comment
|
514
|
507
|
|
515
|
508
|
##@brief Act on abstract LeObject child
|
516
|
509
|
#
|
|
@@ -522,6 +515,7 @@ is not a reference : '%s' field '%s'" % (bref_leo, bref_fname))
|
522
|
515
|
#@param act function : the caller method
|
523
|
516
|
#@param **kwargs other arguments
|
524
|
517
|
#@return sum of results (if it's an array it will result in a concat)
|
|
518
|
+ #@todo optimization implementing a cache for __bref_get_check()
|
525
|
519
|
def __act_on_abstract(self,
|
526
|
520
|
target, filters, relational_filters, act, **kwargs):
|
527
|
521
|
|