Browse Source

Bugfixes in backref handling in mongodb datasrouce refs #131

Now backref seems to work at creation of a Person linked with a text the Person UID is appended to Text.linked_persons
Yann Weber 8 years ago
parent
commit
e602e009ad
2 changed files with 67 additions and 71 deletions
  1. 3
    0
      lodel/leapi/query.py
  2. 64
    71
      plugins/mongodb_datasource/datasource.py

+ 3
- 0
lodel/leapi/query.py View File

477
     _data_check_args = { 'complete': True, 'allow_internal': False }
477
     _data_check_args = { 'complete': True, 'allow_internal': False }
478
 
478
 
479
     def __init__(self, target_class):
479
     def __init__(self, target_class):
480
+        if target_class.is_abstract():
481
+            raise LeApiQueryError("Trying to create an insert query on an \
482
+abstract LeObject : %s" % target_class )
480
         super().__init__(target_class)
483
         super().__init__(target_class)
481
     
484
     
482
     ## @brief Implements an insert query operation, with only one insertion
485
     ## @brief Implements an insert query operation, with only one insertion

+ 64
- 71
plugins/mongodb_datasource/datasource.py View File

199
     #@return int : number of deleted records
199
     #@return int : number of deleted records
200
     def delete(self, target, filters, relational_filters):
200
     def delete(self, target, filters, relational_filters):
201
         if target.is_abstract():
201
         if target.is_abstract():
202
+            logger.debug("Delete called on %s filtered by (%s,%s). Target is \
203
+abstract, preparing reccursiv calls" % (target, filters, relational_filters))
202
             #Deletion with abstract LeObject as target (reccursiv calls)
204
             #Deletion with abstract LeObject as target (reccursiv calls)
203
             return self.__act_on_abstract(target, filters,
205
             return self.__act_on_abstract(target, filters,
204
                 relational_filters, self.delete)
206
                 relational_filters, self.delete)
207
+        logger.debug("Delete called on %s filtered by (%s,%s)." % (
208
+            target, filters, relational_filters))
205
         #Non abstract beahavior
209
         #Non abstract beahavior
206
         mongo_filters = self.__process_filters(
210
         mongo_filters = self.__process_filters(
207
             target, filters, relational_filters)
211
             target, filters, relational_filters)
218
     #@param upd_datas dict : datas to update (new values)
222
     #@param upd_datas dict : datas to update (new values)
219
     #@return int : Number of updated records
223
     #@return int : Number of updated records
220
     def update(self, target, filters, relational_filters, upd_datas):
224
     def update(self, target, filters, relational_filters, upd_datas):
221
-        res = self.__upodate_no_backref(target, filters, relational_filters,
225
+        res = self.__update_no_backref(target, filters, relational_filters,
222
             upd_datas)
226
             upd_datas)
223
         self.__update_backref_filtered(target, filters, relational_filters,
227
         self.__update_backref_filtered(target, filters, relational_filters,
224
             upd_datas)
228
             upd_datas)
229
     #@see update()
233
     #@see update()
230
     def __update_no_backref(self, target, filters, relational_filters,
234
     def __update_no_backref(self, target, filters, relational_filters,
231
             upd_datas):
235
             upd_datas):
236
+        logger.debug("Update called on %s filtered by (%s,%s) with datas \
237
+%s" % (target, filters, relational_filters, upd_datas))
232
         if target.is_abstract():
238
         if target.is_abstract():
233
             #Update using abstract LeObject as target (reccursiv calls)
239
             #Update using abstract LeObject as target (reccursiv calls)
234
             return self.__act_on_abstract(target, filters,
240
             return self.__act_on_abstract(target, filters,
236
         #Non abstract beahavior
242
         #Non abstract beahavior
237
         mongo_filters = self.__process_filters(
243
         mongo_filters = self.__process_filters(
238
             target, filters, relational_filters)
244
             target, filters, relational_filters)
239
-        res = self.__collection(target).update(mongo_filters, upd_datas)
245
+        mongo_arg = {'$set': upd_datas }
246
+        res = self.__collection(target).update(mongo_filters, mongo_arg)
240
         return res['n']
247
         return res['n']
241
 
248
 
242
         
249
         
246
     # @param new_datas dict : datas to insert
253
     # @param new_datas dict : datas to insert
247
     # @return the inserted uid
254
     # @return the inserted uid
248
     def insert(self, target, new_datas):
255
     def insert(self, target, new_datas):
256
+        logger.debug("Insert called on %s with datas : %s"% (
257
+            target, new_datas))
249
         res = self.__collection(target).insert(new_datas)
258
         res = self.__collection(target).insert(new_datas)
250
-        self.__update_backref(target, None, new_datas) 
259
+        uidname = target.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
260
+        leores = list(self.__collection(target).find({'_id':res}))[0]
261
+        self.__update_backref(target, leores[uidname], None, new_datas) 
251
         return str(res)
262
         return str(res)
252
 
263
 
253
     ## @brief Inserts a list of records in a given collection
264
     ## @brief Inserts a list of records in a given collection
298
     #  self.__update_backref(self.__class__, old_datas, new_datas)
309
     #  self.__update_backref(self.__class__, old_datas, new_datas)
299
     #</pre>
310
     #</pre>
300
     #
311
     #
301
-    #@param target LeObject child class
312
+    #@param target LeObject child classa
313
+    #@param tuid mixed : The target UID (the value that will be inserted in
314
+    #back references)
302
     #@param old_datas dict : datas state before update
315
     #@param old_datas dict : datas state before update
303
     #@param new_datas dict : datas state after the update process
316
     #@param new_datas dict : datas state after the update process
304
     #retun None
317
     #retun None
305
-    def __update_backref(self, target, old_datas, new_datas):
318
+    def __update_backref(self, target, tuid, old_datas, new_datas):
306
         #upd_dict is the dict that will allow to run updates in an optimized
319
         #upd_dict is the dict that will allow to run updates in an optimized
307
         #way (or try to help doing it)
320
         #way (or try to help doing it)
308
         #
321
         #
365
                         vdict = {vtype: value}
378
                         vdict = {vtype: value}
366
                         #fetch and store updated value
379
                         #fetch and store updated value
367
                         new_bref_val = self.__back_ref_upd_one_value(
380
                         new_bref_val = self.__back_ref_upd_one_value(
368
-                            fname, fdh, bref_infos, **vdict)
381
+                            fname, fdh, tuid, bref_infos, **vdict)
369
                         upd_dict[bref_cls][value][1][bref_fname] = new_bref_val
382
                         upd_dict[bref_cls][value][1][bref_fname] = new_bref_val
370
             else:
383
             else:
371
                 #fdh is a single ref so the process is simpler, we do not have
384
                 #fdh is a single ref so the process is simpler, we do not have
392
                         upd_dict[bref_cls][uid_val][1][bref_fname])
405
                         upd_dict[bref_cls][uid_val][1][bref_fname])
393
                 #fetche and store updated value
406
                 #fetche and store updated value
394
                 new_bref_val = self.__back_ref_upd_one_value(
407
                 new_bref_val = self.__back_ref_upd_one_value(
395
-                    fname, fdh , **vdict)
408
+                    fname, fdh, tuid, **vdict)
396
                 upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
409
                 upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
397
         #Now we've got our upd_dict ready.
410
         #Now we've got our upd_dict ready.
398
         #running the updates
411
         #running the updates
429
     ##@brief Prepare a one value back reference update
442
     ##@brief Prepare a one value back reference update
430
     #@param fname str : the source Reference field name
443
     #@param fname str : the source Reference field name
431
     #@param fdh DataHandler : the source Reference DataHandler
444
     #@param fdh DataHandler : the source Reference DataHandler
445
+    #@param tuid mixed : the uid of the Leo that make reference to the backref
432
     #@param bref_infos tuple : as returned by __bref_get_check() method
446
     #@param bref_infos tuple : as returned by __bref_get_check() method
433
     #@param old mixed : (optional **values) the old value
447
     #@param old mixed : (optional **values) the old value
434
     #@param new mixed : (optional **values) the new value
448
     #@param new mixed : (optional **values) the new value
435
     #@return the new back reference field value
449
     #@return the new back reference field value
436
-    def __back_ref_upd_one_value(self, fname, fdh, bref_infos, **values):
450
+    def __back_ref_upd_one_value(self, fname, fdh, tuid, bref_infos, **values):
437
         bref_cls, bref_leo, bref_dh, bref_val = bref_infos
451
         bref_cls, bref_leo, bref_dh, bref_val = bref_infos
438
         oldd = 'old' in values
452
         oldd = 'old' in values
439
-        newd = 'new' in values
440
-        if oldd:
441
-            #
442
-            # We got an old value. It can be an update or a delete
443
-            #
444
-            old_value = values['old']
445
-            bref_cls, bref_leo, bref_dh, bref_val = self.__bref_get_check(
446
-                bref_cls, old_value, bref_fname)
447
-            if issubclass(bref_dh.__class__, MultipleRef):
448
-                #
449
-                # Multiple ref update (iterable)
450
-                if old_value not in bref_val:
453
+        newdd = 'new' in values
454
+        if bref_val is None:
455
+            bref_val = bref_dh.empty()
456
+        if issubclass(bref_dh.__class__, MultipleRef):
457
+            if oldd and newdd:
458
+                if tuid not in bref_val:
451
                     raise MongodbConsistencyError("The value we want to \
459
                     raise MongodbConsistencyError("The value we want to \
452
-replace in this back reference update was not found in the back referenced \
453
-object : %s field %s" % (bref_leo, ref_fname))
454
-                if isinstance(old_value, set):
455
-                    #Specific handling for set (values are not indexed)
456
-                    bref_val -= set([old_value])
457
-                    if newd:
458
-                        # update value
459
-                        bref_val |= set([new_datas[fname]])
460
+delete in this back reference update was not found in the back referenced \
461
+object : %s field %s. Value was : '%s'" % (bref_leo, ref_fname, tuid))
462
+                return bref_val
463
+            elif oldd and not newdd:
464
+                #deletion
465
+                old_value = values['old']
466
+                if tuid not in bref_val:
467
+                    raise MongodbConsistencyError("The value we want to \
468
+delete in this back reference update was not found in the back referenced \
469
+object : %s field %s. Value was : '%s'" % (bref_leo, ref_fname, tuid))
470
+                if isinstance(bref_val, set):
471
+                    bref_val -= set([tuid])
460
                 else:
472
                 else:
461
-                    # Assert that we can handles all other iterable this 
462
-                    #way
463
-                    for ki, val in bref_val:
464
-                        if val == old_value:
465
-                            if newd:
466
-                                #Update
467
-                                bref_val[ki] = values['new']
468
-                            else:
469
-                                #Deletion
470
-                                del(bref_val[ki])
471
-                            break
472
-                    else:
473
-                        raise LodelFatalError("This error should never be \
474
-raised ! We just checked that oldv is in bref_val...")
475
-            else:
476
-                #Single ref handling
477
-                if bref_val != values['old']:
478
-                    raise MongoDbConsistencyError("The value we wanted to \
479
-update do not match excpected value during aback reference  singleReference \
480
-update : expected value was '%s' but found '%s' in field '%s' of leo %s" % (
481
-                    old_value, bref_val, ref_fname, bref_leo))
482
-                
483
-                if newd:
484
-                    #update
485
-                    bref_val = values['new']
473
+                    del(bref_val[bref_val.index(tuid)])
474
+            elif not oldd and newdd:
475
+                if tuid in bref_val:
476
+                    raise MongodbConsistencyError("The value we want to \
477
+add in this back reference update was found in the back referenced \
478
+object : %s field %s. Value was : '%s'" % (bref_leo, ref_fname, tuid))
479
+                if isinstance(bref_val, set):
480
+                    bref_val |= set([tuid])
486
                 else:
481
                 else:
487
-                    #delete
488
-                    if not hasattr(bref_dh, "default"): 
489
-                        raise MongoDbConsistencyError("Unable to delete a \
482
+                    bref_val.append(tuid)
483
+        else:
484
+            #Single value backref
485
+            if oldd and newdd:
486
+                if bref_val != tuid:
487
+                    raise MongodbConsistencyError("The backreference doesn't \
488
+have expected value. Expected was %s but found %s in '%s' field of %s" % (
489
+                        tuid, bref_val, bref_fname, bref_leo))
490
+                return bref_val
491
+            elif oldd and not newdd:
492
+                #deletion
493
+                if not hasattr(bref_dh, "default"): 
494
+                    raise MongoDbConsistencyError("Unable to delete a \
490
 value for a back reference update. The concerned field don't have a default \
495
 value for a back reference update. The concerned field don't have a default \
491
 value : in %s field %s" % (bref_leo, ref_fname))
496
 value : in %s field %s" % (bref_leo, ref_fname))
492
-                    bref_val = getattr(bref_dh, "default")
493
-        elif newd:
494
-            #It's an "insert"
495
-            new_value = values['new']
496
-            if issubclass(bref_dh.__class__, MultipleRef):
497
-                if bref_val is None:
498
-                    bref_val = bref_dh.empty()
499
-                if isinstance(bref_val, set):
500
-                    bref_val |= set([new_value])
501
-                else:
502
-                    bref_val.append(new_value)
503
-            else:
504
-                bref_val = new_value
497
+                bref_val = getattr(bref_dh, "default")
498
+            elif not oldd and newdd:
499
+                bref_val = tuid
505
         return bref_val
500
         return bref_val
506
-
507
-        
508
     
501
     
509
     ##@brief Fetch back reference informations
502
     ##@brief Fetch back reference informations
510
     #@warning thank's to __update_backref_act() this method is useless
503
     #@warning thank's to __update_backref_act() this method is useless

Loading…
Cancel
Save