If I Use a Loan Pattern is Salesforce smart enough to do a SOQL for loop?
Agreed with sfdcfox that returning a List<SObject>
will materialize the whole query first rather than let you do a proper SOQL FOR loop.
One alternative is, you could have your factory return Database.getQueryLocator(query)
which is of type Database.queryLocator
. Then you can call .iterator()
on that locator to return an Iterator<SObject>
. Now you iterate it like this:
while(iter.hasNext()){
SObject so = iter.next(); // or cast it to a specific SObject type
// do whatever work here
}
This has functionally the same effect as a SOQL FOR loop. In my experience the way it works is, it fetches the first 200 records under the hood and returns them to you one by one. If there are more after that 200, it fetches the next set, etc. So the query work is spread more evenly across the transaction and the heap is used more efficiently compared to querying the whole thing first.
Yes, Salesforce requires either an inline query or a direct call to Database.query.
When returning a value from a function call, all the results will be retrieved before the values can be used, similar to:
Account[] records = Database.query('select id from account');
for(Account record: records);
There's no way around this restriction aside from actually returning the SOQL and calling it directly:
public List<SObject> selectForQuery(XAP_DAO_SOQL_QueryInterpolation queryInterpolation) {
return this.toSoql(queryInterpolation);
}
Which your loop can then call:
for (SObject[] sobj : Database.query(queryFactory.getSOQL())) {
Calling a method forces all the results to be retrieved, which eliminates the possibility of using this construct.