Skip to content
Snippets Groups Projects
Commit 46e82426 authored by Johannes Goderbauer's avatar Johannes Goderbauer
Browse files

Merge branch '1054657_FixPersonIndexAffectedReturnNull' into '2020.1'

1054657 fix person index affected return null

See merge request xrm/basic!228
parents 8d988456 95e09e85
No related branches found
No related tags found
No related merge requests found
...@@ -4,11 +4,13 @@ import("system.vars"); ...@@ -4,11 +4,13 @@ import("system.vars");
import("IndexSearch_lib"); import("IndexSearch_lib");
import("Sql_lib"); import("Sql_lib");
var infoContainer, onUpdFn, tableName, res; var infoContainer, onUpdFn, tableName, res, action;
tableName = vars.get("$local.table"); tableName = vars.get("$local.table");
idValue = vars.get("$local.idvalue"); idValue = vars.get("$local.idvalue");
infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, vars.get("$local.action") action = vars.get("$local.action");
infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, action
,function (){return vars.get("$local.columns")} ,function (){return vars.get("$local.columns")}
,function (){return vars.get("$local.oldvalues")} ,function (){return vars.get("$local.oldvalues")}
,function (){return vars.get("$local.values")}); ,function (){return vars.get("$local.values")});
...@@ -19,13 +21,21 @@ switch (tableName) ...@@ -19,13 +21,21 @@ switch (tableName)
res = [idValue]; res = [idValue];
break; break;
case "ORGANISATION": case "ORGANISATION":
res = newSelect("CONTACT.CONTACTID") //if an organisation is created or deleted there is no need to do this for the ORGANISATION and CONTACT-table twice, since everytime a
//entry in ORGANISATION is done´, it is also done in CONTACT which is handled in the switch case above => skip then the ORGANISATION-part
//(also on delete the record does not exist anymore)
if (action == "U")
{
res = newSelect("CONTACT.CONTACTID")
.from("CONTACT") .from("CONTACT")
.where("CONTACT.PERSON_ID is null") .where("CONTACT.PERSON_ID is null")
.and("CONTACT.ORGANISATION_ID", idValue) .and("CONTACT.ORGANISATION_ID", idValue)
.arrayColumn(); .arrayColumn();
}
break; break;
case "ADDRESS": case "ADDRESS":
//do not skip here if it's a delete action since it could be that only an address is removed and not a whole record-set of
//organisation, address, communication, etc.
res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){
return newSelect("ADDRESS.CONTACT_ID") return newSelect("ADDRESS.CONTACT_ID")
.from("ADDRESS") .from("ADDRESS")
...@@ -34,6 +44,8 @@ switch (tableName) ...@@ -34,6 +44,8 @@ switch (tableName)
}); });
break; break;
case "COMMUNICATION": case "COMMUNICATION":
//do not skip here if it's a delete action since it could be that only a communication-entry is removed and not a whole record-set of
//organisation, address, communication, etc.
res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){
return newSelect("COMMUNICATION.CONTACT_ID") return newSelect("COMMUNICATION.CONTACT_ID")
.from("COMMUNICATION") .from("COMMUNICATION")
...@@ -41,10 +53,10 @@ switch (tableName) ...@@ -41,10 +53,10 @@ switch (tableName)
.arrayColumn(); .arrayColumn();
}); });
break; break;
default:
res = []; //needed, because the Index is being rebuilt if nothing gets returned
} }
//needed, because the complete index (fullIndexer) is being rebuilt if nothing gets returned here
if (res)
result.object(res); result.object(res);
else
result.object([]);
...@@ -4,11 +4,13 @@ import("system.vars"); ...@@ -4,11 +4,13 @@ import("system.vars");
import("IndexSearch_lib"); import("IndexSearch_lib");
import("Sql_lib"); import("Sql_lib");
var infoContainer, onUpdFn, tableName, res; var infoContainer, onUpdFn, tableName, res, action;
tableName = vars.get("$local.table"); tableName = vars.get("$local.table");
idValue = vars.get("$local.idvalue"); idValue = vars.get("$local.idvalue");
infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, vars.get("$local.action") action = vars.get("$local.action");
infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, action
,function (){return vars.get("$local.columns")} ,function (){return vars.get("$local.columns")}
,function (){return vars.get("$local.oldvalues")} ,function (){return vars.get("$local.oldvalues")}
,function (){return vars.get("$local.values")}); ,function (){return vars.get("$local.values")});
...@@ -19,19 +21,32 @@ switch (tableName) ...@@ -19,19 +21,32 @@ switch (tableName)
res = [idValue]; res = [idValue];
break; break;
case "PERSON": case "PERSON":
res = newSelect("CONTACT.CONTACTID") //if a contact person is created or deleted there is no need to determine the index-uid for the PERSON and CONTACT-table, since everytime a
.from("CONTACT") //entry in PERSON is done, there is also one mande in the CONTACT table which is handled in the switch case above
.where("CONTACT.PERSON_ID", idValue) //=> skip then the PERSON-part (also on delete the record does not exist anymore)
.arrayColumn(); if (action == "U")
{
res = newSelect("CONTACT.CONTACTID")
.from("CONTACT")
.where("CONTACT.PERSON_ID", idValue)
.arrayColumn();
}
break; break;
case "ORGANISATION": case "ORGANISATION":
res = newSelect("CONTACT.CONTACTID") //an organisation can only be deleted if there are no persons left and if an organisation is created there is no entry for person that has
.from("CONTACT") //to be indexed => only in the update-case necessary
.where("CONTACT.ORGANISATION_ID", idValue) if (action == "U")
.and("CONTACT.PERSON_ID is not null") {
.arrayColumn(); res = newSelect("CONTACT.CONTACTID")
.from("CONTACT")
.where("CONTACT.ORGANISATION_ID", idValue)
.and("CONTACT.PERSON_ID is not null")
.arrayColumn();
}
break; break;
case "ADDRESS": case "ADDRESS":
//do not skip here if it's a delete action since it could be that only an address is removed and not a whole record-set of organisation,
//person, address, communication, etc.
res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){
return newSelect("ADDRESS.CONTACT_ID") return newSelect("ADDRESS.CONTACT_ID")
.from("ADDRESS") .from("ADDRESS")
...@@ -40,6 +55,8 @@ switch (tableName) ...@@ -40,6 +55,8 @@ switch (tableName)
}); });
break; break;
case "COMMUNICATION": case "COMMUNICATION":
//do not skip here if it's a delete action since it could be that only a communication-entry is removed and not a whole record-set of
//organisation, person, address, communication, etc.
res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){
return newSelect("COMMUNICATION.CONTACT_ID") return newSelect("COMMUNICATION.CONTACT_ID")
.from("COMMUNICATION") .from("COMMUNICATION")
...@@ -47,9 +64,10 @@ switch (tableName) ...@@ -47,9 +64,10 @@ switch (tableName)
.arrayColumn(); .arrayColumn();
}); });
break; break;
default:
res = []; //needed, because the Index is being rebuilt if nothing gets returned
break;
} }
result.object(res); //needed, because the complete index (fullIndexer) is being rebuilt if nothing gets returned here
\ No newline at end of file if (res)
result.object(res);
else
result.object([]);
...@@ -5,20 +5,66 @@ import("system.text"); ...@@ -5,20 +5,66 @@ import("system.text");
* provides static methods for special handling of entities in JDito-Processes * provides static methods for special handling of entities in JDito-Processes
* do not create an instance of this * do not create an instance of this
* *
* TODO: lib has to be updated with new Indexsearch when it is available
*
* @class * @class
*/ */
function IndexsearchUtils() {} function IndexsearchUtils() {}
/** /**
* TODO: Comment everything! * Searches within an affectedInfoContainer for an id value <br/>
* This id value can be used in the affectedIds-process of an index-recordContainer for example <br/>
*
* Depending on the provided action the given ID-field is searched in: <br/>
* <ul>
* <li>the newValues (action: I), no other values are yet present</li>
* <li>the oldValues (action: D), other values are not anymore present</li>
* <li>another source by calling a function (action: U), in the update case only values are provided that acutally changed so
* another source (usually the dattabase) is needed to perform the lookup</li>
* <li>Otherwise an empty array is given (action X for example)</li>
* </ul>
*
* @param {String} fieldname <p> Name of the field that shall be searched within the infocontainer
* @param {Object} affectedInfoContainer <p> affectedInfoContainer like it is provided by the IndexsearchUtils.createAffectedInfoContainer-function
*
* @param {Function} updateFn <p> a callback function that is called when an update-action is provided in the affectedInfoContianer
* (which means there are no [useful] newvalues/oldvalues)
*
* @return {Array} <p> 1D-array of Strings with all affectedIds that where found depeding on the information in the
* affectedInfoContainer
* @example
* //example for an affectedIds-procces for a indexer that is built on top of the database table OFFER
* //explanations of the example are written as code-comments
* ...imports, variables and more code here...
* //this is always the uid of the record that has been changed, so if an OFFER-entry has been changed the OFFERID is returned, if an OFFERITEM-entry
* //has been changed the OFFERITEMID is returned and so on
* var idValue = vars.get("$local.idvalue");
* var infoContainer = ...code for creating a infoContainer...
* *
* @param {} fieldname * switch (tableName)//the tableName is always the name of the DB table that has been changed (changed = inserted, updated or deleted)
* @param {} affectedInfoContainer * {
* @param {} updateFn * //if the OFFER itself has been changed it's very easy because it's possible to return the OFFERID directly
* case "OFFER":
* res = [idValue];
* break;
* //for other items (like the OFFERITEM in this exmaple) however it is not that easy, because the index-UID is needed as result in the
* //affectedIdsProcess, so we have find the correct OFFERID for the OFFERITEM that has been changed
* // therefore we have to define the columnname of the index-UID we are searching within our table (here: OFFER_ID) and we have to define a
* //callback function that returns the index-UID with for the given ID of the record that has been changed [to see why we need a function see the
* //descriptiontext of this function]
* case "OFFERITEM":
* res = IndexsearchUtils.getAffectedIdValues("OFFER_ID", infoContainer, function (offerItemId){
* return newSelect("OFFERITEM.OFFER_ID")
* .from("OFFERITEM")
* .where("OFFERITEM.OFFERITEMID", offerItemId)
* .arrayColumn();
* });
* break;
* }
* *
* @return {} * //this needed as a savegate, because the Index is being rebuilt by the indexer if nothing gets returned => do a final check here!
* if (res)
* result.object(res);
* else
* result.object([]);
*/ */
IndexsearchUtils.getAffectedIdValues = function(fieldname, affectedInfoContainer, updateFn) { IndexsearchUtils.getAffectedIdValues = function(fieldname, affectedInfoContainer, updateFn) {
var affectedIds; var affectedIds;
...@@ -26,30 +72,51 @@ IndexsearchUtils.getAffectedIdValues = function(fieldname, affectedInfoContainer ...@@ -26,30 +72,51 @@ IndexsearchUtils.getAffectedIdValues = function(fieldname, affectedInfoContainer
{ {
case "I": case "I":
affectedIds = affectedInfoContainer.newValues[affectedInfoContainer.columns.indexOf(fieldname)]; affectedIds = affectedInfoContainer.newValues[affectedInfoContainer.columns.indexOf(fieldname)];
affectedIds = affectedIds ? [affectedIds] : [] affectedIds = affectedIds ? [affectedIds] : [];//check if affectedIds are present because otherwise we may would return [null]
break; break;
case "U": case "U":
affectedIds = updateFn.call(null, affectedInfoContainer.id); affectedIds = updateFn.call(null, affectedInfoContainer.id);
break; break;
case "D": case "D":
affectedIds = affectedInfoContainer.oldValues[affectedInfoContainer.columns.indexOf(fieldname)]; affectedIds = affectedInfoContainer.oldValues[affectedInfoContainer.columns.indexOf(fieldname)];
affectedIds = affectedIds ? [affectedIds] : [] affectedIds = affectedIds ? [affectedIds] : [];//check if affectedIds are present because otherwise we may would return [null]
break; break;
} }
return affectedIds || []; if(affectedIds)
return affectedIds;
else
return [];
} }
/** /**
* TODO: Comment everything! * Builds an object with various properties and returns the newly created object.
* The object that is retruned is so called affectedInfoContainer, but the type and prototype is still object.<br/>
* <br/>
* Each object represents one audited change in a db table with a sepcific type (insert, update, delete, etc.) for one row.
* The object is basically a unified blueprint for such a change.<br/>
* <br/>
* Main purpose of the object is to make the handling of given values within a affectedIdProcess in an entity-indexRecordContainer easier.
* However it could be used in other cases too, for example in the auditProcess.
* *
* @param {} changedIdValue * @param {String} changedIdValue <p> UID of the row where the change has been audited
* @param {} changedTable * @param {String} changedTable <p> name of the db table where the change has been audited
* @param {} action * @param {String} action <p> action type of the audited change in short form, for exmaple: I, U, D, ...
* @param {} columnsFn * @param {Function} columnsFn <p> callbackFunction that has to return an array with the column names of the audited table
* @param {} oldValueFn * @param {Function} oldValueFn <p> callbackFunction that has to return an array with the new values that exist after the audited change
* @param {} newValueFn * @param {Function} newValueFn <p> callbackFunction that has to return an array with the old values that have existed before the audited change
* *
* @return {} * @return {Object} object with the following properties (values depend on the parameters):
* <ul>
* <li>id: uid of the changed record</li>
* <li>table: name of the database table of the changed record</li>
* <li>action: type of the change, this is usually "I" for insert, "U" for update, "D" for delete and "X" for unknown</li>
* <li>columns: array of column names of the table that have been audited (if present)</li>
* <li>oldValues: detemined values before the change (if present)</li>
* <li>newValues: detemined values after the change (if present)</li>
* </ul>
* <br/>
* Note that this only what the object SHOULD contain, the actual values depend on the input parameters.
*
*/ */
IndexsearchUtils.createAffectedInfoContainer = function(changedIdValue, changedTable, action, columnsFn, oldValueFn, newValueFn) { IndexsearchUtils.createAffectedInfoContainer = function(changedIdValue, changedTable, action, columnsFn, oldValueFn, newValueFn) {
var res, internalStorage; var res, internalStorage;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment