Apex Cursors (Beta)
Apex cursors are stateless and generate results from the offset position that is specified in the Cursor.fetch(integer position, integer count) method. You must track the offsets or positions of the results within your particular processing scenario.
A cursor is created when a SOQL query is executed on a Database.getCursor() or Database.getCursorWithBinds() call. When a Cursor.fetch(integer position, integer count) method is invoked with an offset position and the count of records to fetch, the corresponding rows are returned from the cursor. The maximum number of rows per cursor is 50 million, regardless of the operation being synchronous or asynchronous. To get the number of cursor rows returned from the SOQL query, use Cursor.getNumRecords().
Apex cursors throw these new System exceptions: System.FatalCursorException and System.TransientCursorException. Transactions that fail with System.TransientCursorException can be retried.
Apex cursors have the same expiration limits as API Query cursors. See API Query Cursor Limits.
To get Apex cursor limits, use these new methods in the Limits class.
- Limits.getApexCursorRows() and its upper bound Limits.getLimitApexCursorRows() method
- Limits.getFetchCallsOnApexCursor() and its upper bound Limits.getLimitFetchCallsOnApexCursor() method
Apex Cursor Example
public class QueryChunkingQueuable implements Queueable {
private Database.Cursor locator;
private integer position;
public QueryChunkingQueuable() {
locator = Database.getCursor
('SELECT Id FROM Contact WHERE LastActivityDate = LAST_N_DAYS:400');
position = 0;
}
public void execute(QueueableContext ctx) {
List<Contact> scope = locator.fetch(position, 200);
position += scope.size();
// do something, like archive or delete the scope list records
if(position < locator.getNumRecords() ) {
// process the next chunk
System.enqueueJob(this);
}
}
}