2

I was writing a utility class which can give the names of the fields that changed during an update trigger (I have a specific set of fields that i want to track, not all fields). My code snippet is below.

My concern is, if the field is a text field, and it changes from empty string to null (or vice-versa), will this code detect it as a change? After writing my code, i tried using workbench to test it out, but its not helping. I took a record where a text field is null (got it through SOQL query). Then used Apex execute to update it to blank field (sampleRecord.fieldName__c = '';). But querying it again still shows the field as null. So i am unable to test my implementation.

public Map<Id,Set<String>> findFieldChanges(Map<Id,sObject> oldRecordsMap, Map<Id,sObject> newRecordsMap, Set<String> fieldsToBeTracked){
        Map<Id,Set<String>> recIdToFieldNamesMap = new Map<Id,Set<String>>();
        for(sObject currOldRecord : oldRecordsMap.values()){
            sObject currNewRecord = newRecordsMap.get(currOldRecord.Id);
            for(String currField : fieldsToBeTracked){
                if(currOldRecord.get(currField) != currNewRecord.get(currField)){
                    if(!recIdToFieldNamesMap.containsKey(currOldRecord.Id)){
                        recIdToFieldNamesMap.put(currOldRecord.Id, new Set<String>());
                    }
                    (recIdToFieldNamesMap.get(currOldRecord.Id)).add(currField);
                }
            }
        }
        return recIdToFieldNamesMap;
    }

The line

if(currOldRecord.get(currField) != currNewRecord.get(currField))

is what i am curious about. If it a text field, does it differentiate between null and blank?

  • 1
    null is not the same as '' (empty string), but the system automatically converts empty strings to null values when you perform a DML operation, so inside the trigger context, the field will never have an empty string. Adrian's answer demonstrates this principle. You never have to worry about checking for '' as a possible field value when you get a record directly from the database. – sfdcfox May 26 '17 at 4:08
  • @sfdcfox - I figured that. And as Adrian pointed out, trigger.old will always have null. BUT trigger.new could have empty string (let's assume it goes through additional code which tries to set a text field to empty string, and then it encounters my generic method). its a problem for me if a text field going from null to empty is detected as a change. In the code snipped written here, is there a way to take into consideration? In the above code (where it is for generic sObject) can we somehow determine the type of the field specified by parameter currField? – user2957592 May 26 '17 at 7:01
  • @user2957592 Is your generic code running in after update? If so, then my point still stands. There will never be an empty string in your fields. Further, if you're using before update for whatever reason, you will want to use after update instead, because triggers run in an indeterminate order, so you cannot guarantee you have the final state of the fields until after update starts, because the records will be locked then. – sfdcfox May 26 '17 at 12:42
  • @user2957592 If you really, really need to check for empty strings, which I doubt you really do, you can use if(currOldRecord.get(currField) != currNewRecord.get(currField) && currNewRecord.get(currField) != '') Just be aware that you're probably wasting CPU time for a situation that will never occur. – sfdcfox May 26 '17 at 12:47
2

The "old" value would only ever be null, never the empty string (''). These two values are not equal, so yes your code will detect the change if you set the field to the empty string instead of nulling it out.

for (MyObject__c record : trigger.new)
{
    record.TextField__c = '';
    // considered a change

    record.TextField__c = null;
    // not considered a change
}

You can also demonstrate to yourself the database stores values as null by running a unit test like the following:

static testMethod void testNullField()
{
    MyObject__c record = new MyObject__c(TextField__c='');

    Test.startTest();
        insert record;
    Test.stopTest();

    record = [SELECT TextField__c FROM MyObject__c WHERE Id = :record.Id];
    system.assertEquals(null, record.TextField__c, 'The field should be null, not blank');
}
  • - In the code snippet written in original question, is there a way to determine if currField is a text field? Because then i can add the condition if(current field is a text field){ consider null and blank as same} – user2957592 May 26 '17 at 7:03
  • @user I would advise you to just use null rather than the empty string in your code which performs field updates. – Adrian Larson May 26 '17 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.