0

I am trying to clone a record and dynamically query all fields. This works fine for system administrator but something is going wrong for non system administrator users trying to trigger the logic. Can anyone provide some insight on what's happening for non system administrator users when querying the fields dynamically? Its happening on line:

for(Pre_Clarification__c p : database.query(soql)){

Error:Apex trigger AccountTrigger caused an unexpected exception, contact your administrator: AccountTrigger: execution of AfterUpdate caused by: System.QueryException: unexpected token: 'from': ()

public static void CreateReviewSOAPreClara(Account[] accs){
Schema.DescribeSObjectResult d = Schema.SObjectType.Pre_Clarification__C; 
rtMapByName = d.getRecordTypeInfosByName();  
rtCST = rtMapByName.get('CST');    
Map<Id,Id> preclaraMap = new Map<Id,Id>();
Pre_Clarification__c[] preclaraDMLList = New Pre_Clarification__C[]{};
Set<String> preclaracloneId = new Set<String>();

for(Account acc : accs){
    if(acc.Regarding_Pre_Clarification__c != null){
        preclaracloneId.add(acc.Regarding_Pre_Clarification__c);      
    }
}

Map<String, Schema.SObjectField> fMap = Schema.getGlobalDescribe().get('Pre_Clarification__c'.toLowerCase()).getDescribe().Fields.getMap();
List<String> fields = new List<String>();
List<String> allfields = new List<String>();
if (fMap != null){
    for (Schema.SObjectField ft : fMap.values()){ // loop through all field tokens (ft)
        Schema.DescribeFieldResult fd = ft.getDescribe(); // describe each field (fd)
        if (fd.isCreateable()){ // field is creatable
            fields.add(fd.getName());
        }
        allfields.add(fd.getName());
    }
}
String soql = 'select ' + 'Related_Account__r.Regarding_Review_Brief__c, Related_Account__r.Regarding_Annual_Review__c,'
                        + 'Related_Account__r.FirstName, Related_Account__r.LastName, '
                + String.join(fields,',') + ' from Pre_Clarification__c where Id in : preclaracloneId';    
System.debug( '********SOQL STRING**************** fields: ' + fields + ' ********** allfields: ' + allfields);   
for(Pre_Clarification__c p : database.query(soql)){
    Pre_Clarification__c pclone = p.clone();
    pclone.Related_Review_Brief__c = null;
    pclone.Related_Opportunity__c = pclone.Related_Account__r.Regarding_Annual_Review__c;
    pclone.Name = 'Name will auto update'; 
    pclone.Related_ASAP_FP__c = null;
    pclone.Related_ASAP_Super__c = null; 
    pclone.RecordTypeId = rtCST.getRecordTypeId();
    pclone.Review_SOA_Pre_Clarification__c = true;
    preclaraDMLList.add(pclone);
}

insert preclaraDMLList;

}

Here is the debug of string soql:

08:26:53.359 (389041028)|USER_DEBUG|[300]|DEBUG|********SOQL STRING**************** stringvalue: select Related_Account__r.Regarding_Review_Brief__c, Related_Account__r.Regarding_Annual_Review__c,Related_Account__r.FirstName, Related_Account__r.LastName, from Pre_Clarification__c where Id in : preclaracloneId

I just debugged fields string and created another string allfields and updated above. It looks like the isCreatable() line is failting to meet criteria and causing fields string to come back null.

08:58:18.349 (374728976)|USER_DEBUG|[302]|DEBUG|********SOQL STRING**************** fields: () ********** allfields: (Id, OwnerId, IsDeleted, Name, RecordTypeId, CreatedDate, CreatedById, LastModifiedDate, LastModifiedById, SystemModstamp, ...)

  • issue is with String.join(fields,',') so can you check value of fields. It seems non admin user missing FLS for those fields – Himanshu Nov 29 '16 at 7:24
  • Does the user need edit FLS to those fields or just read? – Michael Nov 29 '16 at 7:40
  • The user does have at least read FLS to every field on Pre_Clarification__c. – Michael Nov 29 '16 at 7:52
1

When building dynamic queries like this, you should make sure your list of fields is not empty. I would add this following line before your declaration of soql:

if (fields.isEmpty()) fields.add('Id');

In this way, you'll never have an empty list after your comma, which would lead to an invalid query:

SELECT ... Related_Account__r.LastName, FROM Pre_Clarification__c WHERE ...
  • I understand this but I need the dynamic field query to run and work no matter who is triggering it so that the fields are copied across when cloning. My question is how do I fix this so when a user triggers this method it queries the fields and why isn't the trigger being run as system admin in the first place? – Michael Nov 29 '16 at 22:40
  • @Michael And why do you think the trigger would be run as system admin for some other user? – Adrian Larson Nov 30 '16 at 2:58
  • I meant to say system mode sorry. Doesn't the trigger run as system mode by default? In the same way a user can trigger apex to create a record when they don't have the create permission – Michael Nov 30 '16 at 3:11
  • But that does not affect describe information which tells you permission levels. You get permissions of the running user. – Adrian Larson Nov 30 '16 at 3:18
  • Ah ok I didn't know this, which permission is required to describe fields on custom object? Or is there a way of running describe in system mode? – Michael Nov 30 '16 at 3:24
0

I think the issue is in the below code

String soql = 'select ' + 'Related_Account__r.Regarding_Review_Brief__c, Related_Account__r.Regarding_Annual_Review__c,'
                        + 'Related_Account__r.FirstName, Related_Account__r.LastName, '
                + String.join(fields,',') + ' from Pre_Clarification__c where Id in : preclaracloneId';

Have you debug the soql query string what exactly is coming while executing. If no please debug and see.

I think the below soql query will fail if there is no FLS or fields list is null.

  • The user does have at least read FLS to every field on Pre_Clarification__c. – Michael Nov 29 '16 at 7:52
  • 1
    can you add the debug value of soql string? – RCS Nov 29 '16 at 8:38
  • So from the debug log we can see that String.join(fields,',') is coming back null. Why is the trigger not running as default system user with System Administrator privileges? I have added debug to original question. – Michael Nov 29 '16 at 22:29
0

I misunderstood isCreatable() method for describing fields and didn't know it was in context to the current user. I just removed it and the code worked fine. I thought early on while testing this by not having isCreatable was causing an error but it isn't anymore.

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.