How to stop a Before-Query Business Rule running on child tables

oacp
Kilo Contributor

I have a before-query business rule that runs on the IT Service table. However, since Service Component is a child table of the IT Service table it is running on Service Component as well and subsequently blocks all the data since the query in the BR is only set up to align with IT Services.

Since I don't have access to 'current' in a before-query business rule, I cannot specify in the condition that the BR should only run if the current table is the IT Service table since you can only really mention user or session specific details in the condition field.

How can I stop the before-query business rule running on the child table?

1 ACCEPTED SOLUTION

LaurentChicoine
Tera Guru

Hi Olivia,



You have access to current.getTableName() inside a query business rule.



So you can add a condition on your query business rule to only run on that parent table using current.getTableName() == 'name_of_table'



Also if you want to see all of your records of Service Component when in IT Service table you should simply add a OR condition to include other tables by making a condition including every records where sys_class_name is not IT Service. In encoded query or with an addOrContion('sys_class_name', '!=', 'name_of_table')


View solution in original post

13 REPLIES 13

Yadin
Tera Contributor

I'm trying to do this same thing in a transform but every post I find seems to be about business rules and things seem to work differently between the two...

var check2 = new GlideRecord('cmdb_ci_computer');
check2.addQuery('name',source.u_computername);
check2.addQuery('sys_class_name', 'cmdb_ci_computer');
check2.query();

This does not work.  The sys_class_name query is ignored for some reason so I get results from the extended table when I need to constrain results to the parent.  Anyone have advice?

Hi, could you give more context on where this script is running, what are you trying to do? Is it inside a transform script, a field map or the transform map script?

Have you tried to run your script in a background script to see if the result is the same? For example:

var check2 = new GlideRecord('cmdb_ci_computer');
check2.addQuery('name', 'name_of_a_non_computer_that_is_returned_in_transform');
check2.addQuery('sys_class_name', 'cmdb_ci_computer');
check2.query();
while(check2.next()){
  gs.print(check2.sys_class_name);
}

 

It's in a field map transform script.  I had also tried it in a transform map onBefore transform script (I love the clarity of SN terms...)

 

The script does work as expected when tested as a background script.  I have to execute it in Global not the application context as gs.print is not allowed otherwise, but I would not think that makes a difference.  If I target a computer name that is in the parent table it returns the class name as it should.  If I target a computer in the extended table there is no result.  I target a computer that is in the extended table that does have a duplicate in the extended table and I still get no result.  The latter means there is no way I should have that reference in the first place because it should never have returned a result from the child table and yet it did on import and put in the reference.  I'm at a loss why this is so unreliable in the transform.

Yadin
Tera Contributor

wait... I just tried using an if statement instead of a while statement and instead of returning the class it returns "undefined"... 

if(check2.hasNext()){

vs

while(check2.next()){

So the problem is with hasNext??  I specifically used that because of threads and docs indicating it was the better way to evaluate this in an if statement, but it seems like maybe that is bugged and "while" is the reliable method?  Will that still work if there happens to be multiple results instead of just one?

hasNext() does not retrieve the record, it simply returns true or false based on if there is a next record that has not been retrieved yet.

next() however returns true or false based on if there is a next record and retrieves the next record.

Therefore if you need to access data of the next record, you should use .next() even if it is inside an if statement.

If you really are not able to make the query work properly inside the field map script, you could always check the sys_class_name inside the while loop, something like:

answer = (function transformEntry(source) {

    var check2 = new GlideRecord('cmdb_ci_computer');
    check2.addQuery('name', source.u_computername);
    check2.addQuery('sys_class_name', 'cmdb_ci_computer');
    check2.query();
    while (check2.next()) {
        if(check2.getRecordClassName() == 'cmdb_ci_computer'){
			return check2.getUniqueValue();
		}
    }
	
	return "-1";

})(source);

That way you check the sys_class_name (getRecordClassName) directly on the record before returning it, it normally shouldn't be required but if it does not work with the query it might be your best bet.

Has soon as 1 record match it returns the record sys_id (getUniqueValue) and complete the function). If nothing is matched the script gets to the last return statement to return -1 for a new record to be inserted.