mirror of
https://github.com/yweber/lodel2.git
synced 2025-10-31 19:49:02 +01:00
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
This commit is contained in:
parent
37621c8ba5
commit
e602e009ad
2 changed files with 67 additions and 71 deletions
|
|
@ -477,6 +477,9 @@ class LeInsertQuery(LeQuery):
|
||||||
_data_check_args = { 'complete': True, 'allow_internal': False }
|
_data_check_args = { 'complete': True, 'allow_internal': False }
|
||||||
|
|
||||||
def __init__(self, target_class):
|
def __init__(self, target_class):
|
||||||
|
if target_class.is_abstract():
|
||||||
|
raise LeApiQueryError("Trying to create an insert query on an \
|
||||||
|
abstract LeObject : %s" % target_class )
|
||||||
super().__init__(target_class)
|
super().__init__(target_class)
|
||||||
|
|
||||||
## @brief Implements an insert query operation, with only one insertion
|
## @brief Implements an insert query operation, with only one insertion
|
||||||
|
|
|
||||||
|
|
@ -199,9 +199,13 @@ class MongoDbDatasource(object):
|
||||||
#@return int : number of deleted records
|
#@return int : number of deleted records
|
||||||
def delete(self, target, filters, relational_filters):
|
def delete(self, target, filters, relational_filters):
|
||||||
if target.is_abstract():
|
if target.is_abstract():
|
||||||
|
logger.debug("Delete called on %s filtered by (%s,%s). Target is \
|
||||||
|
abstract, preparing reccursiv calls" % (target, filters, relational_filters))
|
||||||
#Deletion with abstract LeObject as target (reccursiv calls)
|
#Deletion with abstract LeObject as target (reccursiv calls)
|
||||||
return self.__act_on_abstract(target, filters,
|
return self.__act_on_abstract(target, filters,
|
||||||
relational_filters, self.delete)
|
relational_filters, self.delete)
|
||||||
|
logger.debug("Delete called on %s filtered by (%s,%s)." % (
|
||||||
|
target, filters, relational_filters))
|
||||||
#Non abstract beahavior
|
#Non abstract beahavior
|
||||||
mongo_filters = self.__process_filters(
|
mongo_filters = self.__process_filters(
|
||||||
target, filters, relational_filters)
|
target, filters, relational_filters)
|
||||||
|
|
@ -218,7 +222,7 @@ class MongoDbDatasource(object):
|
||||||
#@param upd_datas dict : datas to update (new values)
|
#@param upd_datas dict : datas to update (new values)
|
||||||
#@return int : Number of updated records
|
#@return int : Number of updated records
|
||||||
def update(self, target, filters, relational_filters, upd_datas):
|
def update(self, target, filters, relational_filters, upd_datas):
|
||||||
res = self.__upodate_no_backref(target, filters, relational_filters,
|
res = self.__update_no_backref(target, filters, relational_filters,
|
||||||
upd_datas)
|
upd_datas)
|
||||||
self.__update_backref_filtered(target, filters, relational_filters,
|
self.__update_backref_filtered(target, filters, relational_filters,
|
||||||
upd_datas)
|
upd_datas)
|
||||||
|
|
@ -229,6 +233,8 @@ class MongoDbDatasource(object):
|
||||||
#@see update()
|
#@see update()
|
||||||
def __update_no_backref(self, target, filters, relational_filters,
|
def __update_no_backref(self, target, filters, relational_filters,
|
||||||
upd_datas):
|
upd_datas):
|
||||||
|
logger.debug("Update called on %s filtered by (%s,%s) with datas \
|
||||||
|
%s" % (target, filters, relational_filters, upd_datas))
|
||||||
if target.is_abstract():
|
if target.is_abstract():
|
||||||
#Update using abstract LeObject as target (reccursiv calls)
|
#Update using abstract LeObject as target (reccursiv calls)
|
||||||
return self.__act_on_abstract(target, filters,
|
return self.__act_on_abstract(target, filters,
|
||||||
|
|
@ -236,7 +242,8 @@ class MongoDbDatasource(object):
|
||||||
#Non abstract beahavior
|
#Non abstract beahavior
|
||||||
mongo_filters = self.__process_filters(
|
mongo_filters = self.__process_filters(
|
||||||
target, filters, relational_filters)
|
target, filters, relational_filters)
|
||||||
res = self.__collection(target).update(mongo_filters, upd_datas)
|
mongo_arg = {'$set': upd_datas }
|
||||||
|
res = self.__collection(target).update(mongo_filters, mongo_arg)
|
||||||
return res['n']
|
return res['n']
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -246,8 +253,12 @@ class MongoDbDatasource(object):
|
||||||
# @param new_datas dict : datas to insert
|
# @param new_datas dict : datas to insert
|
||||||
# @return the inserted uid
|
# @return the inserted uid
|
||||||
def insert(self, target, new_datas):
|
def insert(self, target, new_datas):
|
||||||
|
logger.debug("Insert called on %s with datas : %s"% (
|
||||||
|
target, new_datas))
|
||||||
res = self.__collection(target).insert(new_datas)
|
res = self.__collection(target).insert(new_datas)
|
||||||
self.__update_backref(target, None, new_datas)
|
uidname = target.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
|
||||||
|
leores = list(self.__collection(target).find({'_id':res}))[0]
|
||||||
|
self.__update_backref(target, leores[uidname], None, new_datas)
|
||||||
return str(res)
|
return str(res)
|
||||||
|
|
||||||
## @brief Inserts a list of records in a given collection
|
## @brief Inserts a list of records in a given collection
|
||||||
|
|
@ -298,11 +309,13 @@ class MongoDbDatasource(object):
|
||||||
# self.__update_backref(self.__class__, old_datas, new_datas)
|
# self.__update_backref(self.__class__, old_datas, new_datas)
|
||||||
#</pre>
|
#</pre>
|
||||||
#
|
#
|
||||||
#@param target LeObject child class
|
#@param target LeObject child classa
|
||||||
|
#@param tuid mixed : The target UID (the value that will be inserted in
|
||||||
|
#back references)
|
||||||
#@param old_datas dict : datas state before update
|
#@param old_datas dict : datas state before update
|
||||||
#@param new_datas dict : datas state after the update process
|
#@param new_datas dict : datas state after the update process
|
||||||
#retun None
|
#retun None
|
||||||
def __update_backref(self, target, old_datas, new_datas):
|
def __update_backref(self, target, tuid, old_datas, new_datas):
|
||||||
#upd_dict is the dict that will allow to run updates in an optimized
|
#upd_dict is the dict that will allow to run updates in an optimized
|
||||||
#way (or try to help doing it)
|
#way (or try to help doing it)
|
||||||
#
|
#
|
||||||
|
|
@ -365,7 +378,7 @@ class MongoDbDatasource(object):
|
||||||
vdict = {vtype: value}
|
vdict = {vtype: value}
|
||||||
#fetch and store updated value
|
#fetch and store updated value
|
||||||
new_bref_val = self.__back_ref_upd_one_value(
|
new_bref_val = self.__back_ref_upd_one_value(
|
||||||
fname, fdh, bref_infos, **vdict)
|
fname, fdh, tuid, bref_infos, **vdict)
|
||||||
upd_dict[bref_cls][value][1][bref_fname] = new_bref_val
|
upd_dict[bref_cls][value][1][bref_fname] = new_bref_val
|
||||||
else:
|
else:
|
||||||
#fdh is a single ref so the process is simpler, we do not have
|
#fdh is a single ref so the process is simpler, we do not have
|
||||||
|
|
@ -392,7 +405,7 @@ class MongoDbDatasource(object):
|
||||||
upd_dict[bref_cls][uid_val][1][bref_fname])
|
upd_dict[bref_cls][uid_val][1][bref_fname])
|
||||||
#fetche and store updated value
|
#fetche and store updated value
|
||||||
new_bref_val = self.__back_ref_upd_one_value(
|
new_bref_val = self.__back_ref_upd_one_value(
|
||||||
fname, fdh , **vdict)
|
fname, fdh, tuid, **vdict)
|
||||||
upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
|
upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
|
||||||
#Now we've got our upd_dict ready.
|
#Now we've got our upd_dict ready.
|
||||||
#running the updates
|
#running the updates
|
||||||
|
|
@ -429,82 +442,62 @@ class MongoDbDatasource(object):
|
||||||
##@brief Prepare a one value back reference update
|
##@brief Prepare a one value back reference update
|
||||||
#@param fname str : the source Reference field name
|
#@param fname str : the source Reference field name
|
||||||
#@param fdh DataHandler : the source Reference DataHandler
|
#@param fdh DataHandler : the source Reference DataHandler
|
||||||
|
#@param tuid mixed : the uid of the Leo that make reference to the backref
|
||||||
#@param bref_infos tuple : as returned by __bref_get_check() method
|
#@param bref_infos tuple : as returned by __bref_get_check() method
|
||||||
#@param old mixed : (optional **values) the old value
|
#@param old mixed : (optional **values) the old value
|
||||||
#@param new mixed : (optional **values) the new value
|
#@param new mixed : (optional **values) the new value
|
||||||
#@return the new back reference field value
|
#@return the new back reference field value
|
||||||
def __back_ref_upd_one_value(self, fname, fdh, bref_infos, **values):
|
def __back_ref_upd_one_value(self, fname, fdh, tuid, bref_infos, **values):
|
||||||
bref_cls, bref_leo, bref_dh, bref_val = bref_infos
|
bref_cls, bref_leo, bref_dh, bref_val = bref_infos
|
||||||
oldd = 'old' in values
|
oldd = 'old' in values
|
||||||
newd = 'new' in values
|
newdd = 'new' in values
|
||||||
if oldd:
|
if bref_val is None:
|
||||||
#
|
bref_val = bref_dh.empty()
|
||||||
# We got an old value. It can be an update or a delete
|
if issubclass(bref_dh.__class__, MultipleRef):
|
||||||
#
|
if oldd and newdd:
|
||||||
old_value = values['old']
|
if tuid not in bref_val:
|
||||||
bref_cls, bref_leo, bref_dh, bref_val = self.__bref_get_check(
|
|
||||||
bref_cls, old_value, bref_fname)
|
|
||||||
if issubclass(bref_dh.__class__, MultipleRef):
|
|
||||||
#
|
|
||||||
# Multiple ref update (iterable)
|
|
||||||
if old_value not in bref_val:
|
|
||||||
raise MongodbConsistencyError("The value we want to \
|
raise MongodbConsistencyError("The value we want to \
|
||||||
replace in this back reference update was not found in the back referenced \
|
delete in this back reference update was not found in the back referenced \
|
||||||
object : %s field %s" % (bref_leo, ref_fname))
|
object : %s field %s. Value was : '%s'" % (bref_leo, ref_fname, tuid))
|
||||||
if isinstance(old_value, set):
|
return bref_val
|
||||||
#Specific handling for set (values are not indexed)
|
elif oldd and not newdd:
|
||||||
bref_val -= set([old_value])
|
#deletion
|
||||||
if newd:
|
old_value = values['old']
|
||||||
# update value
|
if tuid not in bref_val:
|
||||||
bref_val |= set([new_datas[fname]])
|
raise MongodbConsistencyError("The value we want to \
|
||||||
|
delete in this back reference update was not found in the back referenced \
|
||||||
|
object : %s field %s. Value was : '%s'" % (bref_leo, ref_fname, tuid))
|
||||||
|
if isinstance(bref_val, set):
|
||||||
|
bref_val -= set([tuid])
|
||||||
else:
|
else:
|
||||||
# Assert that we can handles all other iterable this
|
del(bref_val[bref_val.index(tuid)])
|
||||||
#way
|
elif not oldd and newdd:
|
||||||
for ki, val in bref_val:
|
if tuid in bref_val:
|
||||||
if val == old_value:
|
raise MongodbConsistencyError("The value we want to \
|
||||||
if newd:
|
add in this back reference update was found in the back referenced \
|
||||||
#Update
|
object : %s field %s. Value was : '%s'" % (bref_leo, ref_fname, tuid))
|
||||||
bref_val[ki] = values['new']
|
if isinstance(bref_val, set):
|
||||||
else:
|
bref_val |= set([tuid])
|
||||||
#Deletion
|
|
||||||
del(bref_val[ki])
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise LodelFatalError("This error should never be \
|
|
||||||
raised ! We just checked that oldv is in bref_val...")
|
|
||||||
else:
|
|
||||||
#Single ref handling
|
|
||||||
if bref_val != values['old']:
|
|
||||||
raise MongoDbConsistencyError("The value we wanted to \
|
|
||||||
update do not match excpected value during aback reference singleReference \
|
|
||||||
update : expected value was '%s' but found '%s' in field '%s' of leo %s" % (
|
|
||||||
old_value, bref_val, ref_fname, bref_leo))
|
|
||||||
|
|
||||||
if newd:
|
|
||||||
#update
|
|
||||||
bref_val = values['new']
|
|
||||||
else:
|
else:
|
||||||
#delete
|
bref_val.append(tuid)
|
||||||
if not hasattr(bref_dh, "default"):
|
else:
|
||||||
raise MongoDbConsistencyError("Unable to delete a \
|
#Single value backref
|
||||||
|
if oldd and newdd:
|
||||||
|
if bref_val != tuid:
|
||||||
|
raise MongodbConsistencyError("The backreference doesn't \
|
||||||
|
have expected value. Expected was %s but found %s in '%s' field of %s" % (
|
||||||
|
tuid, bref_val, bref_fname, bref_leo))
|
||||||
|
return bref_val
|
||||||
|
elif oldd and not newdd:
|
||||||
|
#deletion
|
||||||
|
if not hasattr(bref_dh, "default"):
|
||||||
|
raise MongoDbConsistencyError("Unable to delete a \
|
||||||
value for a back reference update. The concerned field don't have a default \
|
value for a back reference update. The concerned field don't have a default \
|
||||||
value : in %s field %s" % (bref_leo, ref_fname))
|
value : in %s field %s" % (bref_leo, ref_fname))
|
||||||
bref_val = getattr(bref_dh, "default")
|
bref_val = getattr(bref_dh, "default")
|
||||||
elif newd:
|
elif not oldd and newdd:
|
||||||
#It's an "insert"
|
bref_val = tuid
|
||||||
new_value = values['new']
|
|
||||||
if issubclass(bref_dh.__class__, MultipleRef):
|
|
||||||
if bref_val is None:
|
|
||||||
bref_val = bref_dh.empty()
|
|
||||||
if isinstance(bref_val, set):
|
|
||||||
bref_val |= set([new_value])
|
|
||||||
else:
|
|
||||||
bref_val.append(new_value)
|
|
||||||
else:
|
|
||||||
bref_val = new_value
|
|
||||||
return bref_val
|
return bref_val
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##@brief Fetch back reference informations
|
##@brief Fetch back reference informations
|
||||||
#@warning thank's to __update_backref_act() this method is useless
|
#@warning thank's to __update_backref_act() this method is useless
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue