0

I am working on a method that is apart of a batch class to query for Contacts. I'm trying to see if the field "CASL_Compliant_Source__c" is in a keyet that I passed to a makestring method.

I keep getting an error when I run the batch in debug:

Variable does not exist: s

global class NPD_Batch_CASLCompliance implements Database.Batchable<sObject>
{
Map<String, Date> sources = new Map<String, Date>();  

public NPD_Batch_CASLCompliance() 
{         
    this.sources = sources;
    Date inquiryDate = System.today().addMonths(-6);
    Date relationshipDate = System.today().addYears(-2);
    sources.put('Contact Initiated the Inquiry', inquiryDate);
    sources.put('Business Relationship', relationshipDate);     
}

global Database.QueryLocator start(Database.BatchableContext BC) 
{ 
    String query = makeString(sources); 
    return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<sObject> scope) 
{
    NPD_CASLCompliance.actions(sources, scope);
}

global void finish(Database.BatchableContext BC) 
{
}

/*
    * MethodName        : makeString
    * param             : Map<String, Date> sources
    * Description       : This method will make a string to use as a query
*/

public String makeString(Map<String, Date> sources)
{
    Set<String> s = sources.keySet();

    String query = 
        'SELECT Id, ' +
        '       CASL_Compliant_Date__c, ' +
        '       CASL_Compliant_Source__c, ' +
        '       CASL_Compliant__c ' +
        'FROM   Contact ' +
        'WHERE  CASL_Compliant_Source__c IN :s ' + 
        'AND    CASL_Compliant__c = TRUE';
    return query; 
}

If I make the variable within the method why would it not exist?

2 Answers 2

3

Lets expand your code:

global Database.QueryLocator start(Database.BatchableContext BC) 
{ 
    String query = makeString(sources); 
    return Database.getQueryLocator(query);
} 

Becomes:

global Database.QueryLocator start(Database.BatchableContext BC) 
    { 
        String query = makeString(sources); 
        return Database.getQueryLocator('SELECT Id, ' +
        '       CASL_Compliant_Date__c, ' +
        '       CASL_Compliant_Source__c, ' +
        '       CASL_Compliant__c ' +
        'FROM   Contact ' +
        'WHERE  CASL_Compliant_Source__c IN :s ' + 
        'AND    CASL_Compliant__c = TRUE');
    } 

Now after expansion, does your s variable exists in start method? No the s varible's scope was just in makeString method. After that it does not exists. And hence it gives you an error.

Fix: Make your s as an instance variable, so that its present in start.

global class NPD_Batch_CASLCompliance implements Database.Batchable<sObject>{
    private Set<String> s;
    public String makeString(Map<String, Date> sources){
        s = sources.keySet();

        String query = 
        'SELECT Id, ' +
        '       CASL_Compliant_Date__c, ' +
        '       CASL_Compliant_Source__c, ' +
        '       CASL_Compliant__c ' +
        'FROM   Contact ' +
        'WHERE  CASL_Compliant_Source__c IN :s ' + 
        'AND    CASL_Compliant__c = TRUE';
        return query; 
    }
    global Database.QueryLocator start(Database.BatchableContext BC){ 
        String query = makeString(sources); 
        return Database.getQueryLocator(query);
    }
}
2

When you use Apex binding in Dynamic SOQL, the bound variables must be in scope at the point when Database.query() is called, rather than at the point when the query string is initialized.

Here, you'd probably want to create an instance variable (sourceKeys?), and bind to that. Doing so ensures that the bind's scope covers all of your instance methods.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .