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,6 +477,9 @@ class LeInsertQuery(LeQuery):
477 477
     _data_check_args = { 'complete': True, 'allow_internal': False }
478 478
 
479 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 483
         super().__init__(target_class)
481 484
     
482 485
     ## @brief Implements an insert query operation, with only one insertion

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

@@ -199,9 +199,13 @@ class MongoDbDatasource(object):
199 199
     #@return int : number of deleted records
200 200
     def delete(self, target, filters, relational_filters):
201 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 204
             #Deletion with abstract LeObject as target (reccursiv calls)
203 205
             return self.__act_on_abstract(target, filters,
204 206
                 relational_filters, self.delete)
207
+        logger.debug("Delete called on %s filtered by (%s,%s)." % (
208
+            target, filters, relational_filters))
205 209
         #Non abstract beahavior
206 210
         mongo_filters = self.__process_filters(
207 211
             target, filters, relational_filters)
@@ -218,7 +222,7 @@ class MongoDbDatasource(object):
218 222
     #@param upd_datas dict : datas to update (new values)
219 223
     #@return int : Number of updated records
220 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 226
             upd_datas)
223 227
         self.__update_backref_filtered(target, filters, relational_filters,
224 228
             upd_datas)
@@ -229,6 +233,8 @@ class MongoDbDatasource(object):
229 233
     #@see update()
230 234
     def __update_no_backref(self, target, filters, relational_filters,
231 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 238
         if target.is_abstract():
233 239
             #Update using abstract LeObject as target (reccursiv calls)
234 240
             return self.__act_on_abstract(target, filters,
@@ -236,7 +242,8 @@ class MongoDbDatasource(object):
236 242
         #Non abstract beahavior
237 243
         mongo_filters = self.__process_filters(
238 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 247
         return res['n']
241 248
 
242 249
         
@@ -246,8 +253,12 @@ class MongoDbDatasource(object):
246 253
     # @param new_datas dict : datas to insert
247 254
     # @return the inserted uid
248 255
     def insert(self, target, new_datas):
256
+        logger.debug("Insert called on %s with datas : %s"% (
257
+            target, new_datas))
249 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 262
         return str(res)
252 263
 
253 264
     ## @brief Inserts a list of records in a given collection
@@ -298,11 +309,13 @@ class MongoDbDatasource(object):
298 309
     #  self.__update_backref(self.__class__, old_datas, new_datas)
299 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 315
     #@param old_datas dict : datas state before update
303 316
     #@param new_datas dict : datas state after the update process
304 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 319
         #upd_dict is the dict that will allow to run updates in an optimized
307 320
         #way (or try to help doing it)
308 321
         #
@@ -365,7 +378,7 @@ class MongoDbDatasource(object):
365 378
                         vdict = {vtype: value}
366 379
                         #fetch and store updated value
367 380
                         new_bref_val = self.__back_ref_upd_one_value(
368
-                            fname, fdh, bref_infos, **vdict)
381
+                            fname, fdh, tuid, bref_infos, **vdict)
369 382
                         upd_dict[bref_cls][value][1][bref_fname] = new_bref_val
370 383
             else:
371 384
                 #fdh is a single ref so the process is simpler, we do not have
@@ -392,7 +405,7 @@ class MongoDbDatasource(object):
392 405
                         upd_dict[bref_cls][uid_val][1][bref_fname])
393 406
                 #fetche and store updated value
394 407
                 new_bref_val = self.__back_ref_upd_one_value(
395
-                    fname, fdh , **vdict)
408
+                    fname, fdh, tuid, **vdict)
396 409
                 upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
397 410
         #Now we've got our upd_dict ready.
398 411
         #running the updates
@@ -429,82 +442,62 @@ class MongoDbDatasource(object):
429 442
     ##@brief Prepare a one value back reference update
430 443
     #@param fname str : the source Reference field name
431 444
     #@param fdh DataHandler : the source Reference DataHandler
445
+    #@param tuid mixed : the uid of the Leo that make reference to the backref
432 446
     #@param bref_infos tuple : as returned by __bref_get_check() method
433 447
     #@param old mixed : (optional **values) the old value
434 448
     #@param new mixed : (optional **values) the new value
435 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 451
         bref_cls, bref_leo, bref_dh, bref_val = bref_infos
438 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 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 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 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 495
 value for a back reference update. The concerned field don't have a default \
491 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 500
         return bref_val
506
-
507
-        
508 501
     
509 502
     ##@brief Fetch back reference informations
510 503
     #@warning thank's to __update_backref_act() this method is useless

Loading…
Cancel
Save