function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Dipak@pvsDipak@pvs 

First error: unexpected token: '{' while running a batch from developer console

Hi,

Whenever I am going to run the folowing batch I get the error 'First error: unexpected token: '{''. The batch is :

global class ZmDmAttachmentCleanupBatch implements Database.Batchable<SObject>, Database.Stateful{

private List<Id> ZmDmAttachmentIds;

private String MarketCleanupId;

public ZmDmAttachmentCleanupBatch() {
        //do nothing   
    }

   
public ZmDmAttachmentCleanupBatch(List<Id> ZmDmAttachmentIds) {
        this.ZmDmAttachmentIds = ZmDmAttachmentIds;
    }
   
public ZmDmAttachmentCleanupBatch(String MarketId) {
        this.MarketCleanupId = MarketId;
    }  

    global Database.QueryLocator start(Database.BatchableContext bc){
        return Database.getQueryLocator(prepareSOQL());
    }

    global void execute(Database.BatchableContext bc, List<Attachment> rows){
            delete rows;
           DataBase.emptyRecycleBin(rows);    
    }
   
    global void finish(Database.BatchableContext bc){
     String CleanupLastRun;
     datetime myDateTime = datetime.now();
     String myDateStr = String.ValueOf(myDateTime);
     Market__c mkt = [select Id,Cleanup_Last_Run__c from market__c
                                                        where Market_Id__c=:MarketCleanupId];

         String CleanupLastRun1 = mkt.Cleanup_Last_Run__c;
         String CleanupLastRun2 = CleanupLastRun1+'Attachment:'+myDateStr;             
        // mkt.Cleanup_Last_Run__c = 'Attachment:'+myDateStr;
              
           update mkt;
          
           Database.executeBatch(new SlAttachmentCleanupBatch('73'),2000);
        System.debug('job finished.');
     
    }
   
    public static void startJob() {
        scheduleJob(2);
    }
   
   
    private String prepareSOQL() {
     
       Market__c mrkt = [select PREV_1_CMPGN_NR__c,X90_Day_Camp_CNT__c from market__c
                                                     where Market_Id__c=:MarketCleanupId];
       List<CDW_Market_Report__c> Parent_id = [select id from CDW_Market_Report__c
                                                      where Market__r.Market_Id__c=:MarketCleanupId];
             system.debug('parent id'+Parent_id);
      
      // List<SObject> results = Database.query(someSOQL);
       Set<Id> resultIds = (new Map<Id,CDW_Market_Report__c>(Parent_id)).keySet();
      // Set<Id> resultIds = new Set<Id> (new Map<Id,CDW_Market_Report__c>(Parent_id).keySet());
      // Set<String> resultIds = (new Map<String,CDW_Market_Report__c>(Parent_id)).keySet();      
       List<Calendar__c> camp = [select CMPGN_NR__c,CMPGN_STRT_DT__c from Calendar__c
                                                    where MRKT_ID__c = :MarketCleanupId order by CMPGN_NR__c desc];

          Integer index = -1;
         
          Integer CampaignIndex=6;

       List<String> Camps=new List<String>();
      
          for(Calendar__c ca: camp){
            Camps.add(String.valueOf(ca.CMPGN_NR__c));
          }

          for(Integer m = 0; m<Camps.size();m++){
             IF(Camps[m].equalsignorecase(mrkt.PREV_1_CMPGN_NR__c)){
             index = m;
             System.debug('index='+ index);
             break;       
             }
          }
       Calendar__c PrevCmpgnStr1=camp[index+CampaignIndex];
              system.debug('final campaign'+ PrevCmpgnStr1);
  
               date startdate= PrevCmpgnStr1.CMPGN_STRT_DT__c;
               Datetime dt = datetime.newInstance(startdate.year(), startdate.month(),startdate.day(),00,00,00);

     // List<Attachment> atc = [select Id from Attachment where ParentId In :resultIds and LastModifiedDate<:dt];
     
     // system.debug('attachmentis'+ atc);

      // String PrevCmpgnStr=Camps[index+CampaignIndex];
      
      String sql = 'SELECT Id FROM Attachment ';
                
           // sql += ' where ParentId In :\''+resultIds+'\' and LastModifiedDate<:\''+dt+'\'';
            sql += ' where ParentId In :'+resultIds+' and LastModifiedDate<:'+dt+'';
           
       system.debug('queryis'+ sql);           
      return sql;
     
    }
   
   
    private Set<String> fetchEligibleMarketCodes() {
        Set<String> marketCodes = new Set<String>();
        for (Market__c market : [Select Market_Id__c from Market__c where Is_ALMPLUS_Enabled__c=true]) {
            marketCodes.add(market.Market_Id__c);
        }
        System.debug('eligible market codes: ' + marketCodes);
        return marketCodes;
    }
   
    private static void scheduleJob(Integer minutesOffset) {
        DateTime currentTime = System.now();
        String scheduleTime = ALMPlusUtils.prepareJobsSchTime(currentTime, minutesOffset); 
        String uniqueJobName = ALMPlusUtils.getUniqueJobName('ZmDmAttachmentCleanupBatch');
        String cronID = System.schedule(uniqueJobName, scheduleTime, new BatchJobScheduler(new ZmDmAttachmentCleanupBatch(), 1000));  //use 10 as the batch size         
    }
   
    //ZmDmAttachmentCleanupBatch zda=new ZmDmAttachmentCleanupBatch('73');
    //zda.startJob();
   
   
}

Can anybody tell me where I am missing in the code.

Regards,
Dip
Best Answer chosen by Dipak@pvs
Swati GSwati G

Hi,

You are creating dynamic query some where else and executing it in some other method.

When we create dynamic query and want to use binding then include variable directly in query.

Like this,
sql += ' where ParentId In :resultIds  and LastModifiedDate<:dt';

When you execute this query in that method which creates this  query string it will work properly as variables are defined in that method's local scope. but when you execute this in start method it wont get those variables.

So, instead of using variable create string from them as shown below.

String formatedDate = dt.format('yyyy-MM-dd\'T\'hh:mm:ss\'Z\'');
List<Id> listId =  New List<Id>();
listId.addAll(resultIds);
String idString= '\''+String.join(listId,'\',\'')+'\'';
sql += ' where ParentId In '+idString+' and LastModifiedDate<'+dt+'';

replace your sql statement which create where clause with the above line of code and check if it works.

All Answers

Vinita_SFDCVinita_SFDC
Hi Dip,

This error occurs if there is a mismatch in number of open and closed parenthesis.  Please check if you are missing any {} ; or ()
Dipak@pvsDipak@pvs
Hi Vinita,

This error is not comming because of parenthesis mismatch. This is comming because of dynamic query. Ever since I have used Set<Id> resultIds = (new Map<Id,CDW_Market_Report__c>(Parent_id)).keySet(); in code and used the 'resultIds' in query, I am getting this error.
Swati GSwati G

Hi,

You are creating dynamic query some where else and executing it in some other method.

When we create dynamic query and want to use binding then include variable directly in query.

Like this,
sql += ' where ParentId In :resultIds  and LastModifiedDate<:dt';

When you execute this query in that method which creates this  query string it will work properly as variables are defined in that method's local scope. but when you execute this in start method it wont get those variables.

So, instead of using variable create string from them as shown below.

String formatedDate = dt.format('yyyy-MM-dd\'T\'hh:mm:ss\'Z\'');
List<Id> listId =  New List<Id>();
listId.addAll(resultIds);
String idString= '\''+String.join(listId,'\',\'')+'\'';
sql += ' where ParentId In '+idString+' and LastModifiedDate<'+dt+'';

replace your sql statement which create where clause with the above line of code and check if it works.
This was selected as the best answer
Dipak@pvsDipak@pvs
Hi Swati,

After using this piece of code I am getting the following error:

expecting a colon, found 'a05F0000007jRoEIAU'

I used the where clause of query in different way but every time I got different error.

Set<Id> resultIds = (new Map<Id,CDW_Market_Report__c>(Parent_id)).keySet();
      //Set<Id> resultIds = new Set<Id> (new Map<Id,CDW_Market_Report__c>(Parent_id).keySet());
      String formatedDate = dt.format('yyyy-MM-dd\'T\'hh:mm:ss\'Z\'');
       List<Id> listId =  New List<Id>();
        listId.addAll(resultIds);
         String idString= '\''+String.join(listId,'\',\'')+'\'';
        
         system.debug('idString'+ idString);

      String sql = 'SELECT Id FROM Attachment';
      sql += ' where ParentId In '+idString+' and LastModifiedDate<'+dt+'';-----expecting a colon, found 'a05F0000007jRoEIAU'
    
      // sql += ' where ParentId In '+idString+' and LastModifiedDate<'+dt+'';
      //  sql += ' where ParentId = '+idString+' and LastModifiedDate<:'+dt+'';---------First error: unexpected token: ','
      // sql += ' where ParentId In: \''+idString+'\' and LastModifiedDate<:\''+formatedDate+'\'';----First error: Only variable references are allowed in dynamic                                                                                                                                                              SOQL/SOSL.
                 
           // sql += ' where ParentId In :\''+resultIds+'\' and LastModifiedDate<:\''+dt+'\'';----First error: Only variable references are allowed in dynamic                                                                                                                                                              SOQL/SOSL.
        //    sql += ' where ParentId In :'+resultIds+' and LastModifiedDate<:'+dt+'';-----First error: unexpected token: '{'

Regards,
Dip
Swati GSwati G
try this,

sql += ' where ParentId In ('+idString+') and LastModifiedDate<'+dt+'';-----expecting a colon, found 'a05F0000007jRoEIAU'

I forgot to tell that you will have to use open and close brackets
Dipak@pvsDipak@pvs
Hi Swati,

Thanks for your help. It worked perfectly. Just I replaced the 'dt' in LastModifiedDate from formatedDate in query.

Regards,
Dip
Nazrul AminNazrul Amin
Swati, this was driving me nuts.  Thanks so much for the explanation above. 

What I found was that variables declared outside of the method where the query is being built show error: "Only variable references are allowed in dynamic SOQL/SOSL.", in which case your suggestion of declaring another variable in the same method as where the query is being built, and then copying the existing values over to this new variable (which is then being referenced in the query) does the trick. 

We also then need to build the WHERE clause without any speech marks etc (as per code snippet below), else can see error: "unexpected token".

Thanks again.
Nazrul

CODE SNIPPET THAT WORKS FOR ME:
List<String> prodTxts = new List<String>();
prodTxts.addAll(ProdsList);
String Query = 'SELECT Id, Contracted_Product__c FROM Product2 WHERE Product_Group__c IN:prodTxts AND IsActive = TRUE AND RecordType.DeveloperName = \'Service_Product\' ';