SqlQueueable Class

Abstract base class for executing long-running Data 360 SQL queries asynchronously in chained Queueable jobs. Implements Queueable and Database.AllowsCallouts. Create a concrete subclass that implements processDataChunk() to process each page of results and chainNextJob() to enqueue the next job when more data remains.

Namespace

sfsqlquery

Usage

The framework handles query submission, status polling, pagination, and job chaining automatically. Your subclass only needs to process data chunks and define how to chain the next job. Inside processDataChunk(), call getRows() to iterate results as Row objects, or getPageOutput() to access the raw ConnectApi.QuerySqlPageOutput. If you call cancel() inside processDataChunk(), the framework skips chainNextJob() automatically.

Example

Define a concrete subclass and start a new query:

1public with sharing class MyQueryJob extends sfsqlquery.SqlQueueable {
2    public MyQueryJob(sfsqlquery.SqlStatement stmt) { super(stmt); }
3    public MyQueryJob(sfsqlquery.QueryHandle handle) { super(handle); }
4
5    public override void processDataChunk() {
6        for (sfsqlquery.Row row : getRows()) {
7            System.debug(row.getString('Name__c'));
8        }
9    }
10
11    public override void chainNextJob(sfsqlquery.QueryHandle handle) {
12        System.enqueueJob(new MyQueryJob(handle));
13    }
14}
15
16// Start the job
17sfsqlquery.SqlStatement stmt = sfsqlquery.SqlStatement.create('SELECT Id__c, Name__c FROM accounts__dlm', 'default');
18System.enqueueJob(new MyQueryJob(stmt));

SqlQueueable Constructors

The following are constructors for SqlQueueable.

SqlQueueable(handle)

Creates a SqlQueueable subclass instance that resumes an in-progress query from a saved QueryHandle. Use this constructor in chainNextJob() to continue processing the next page.

Signature

public SqlQueueable(sfsqlquery.QueryHandle handle)

Parameters

handle
Type: sfsqlquery.QueryHandle
QueryHandle tracking the position and state of an in-progress query.

SqlQueueable(statement)

Creates a SqlQueueable subclass instance from a SqlStatement to start a new query. Pass the constructed job to System.enqueueJob() to begin execution.

Signature

public SqlQueueable(sfsqlquery.SqlStatement statement)

Parameters

statement
Type: sfsqlquery.SqlStatement
SqlStatement defining the query to execute.

SqlQueueable Methods

The following are methods for SqlQueueable.

cancel()

Cancels the current query. When called inside processDataChunk(), the framework automatically skips chainNextJob(), stopping further job chaining.

Signature

public void cancel()

Return Value

Type: void

Example

Cancel the query based on a condition:

1public override void processDataChunk() {
2    Integer errorCount = 0;
3    for (sfsqlquery.Row row : getRows()) {
4        try {
5            // Process row
6        } catch (Exception e) {
7            errorCount++;
8            if (errorCount > 10) {
9                cancel();  // Stop processing after too many errors
10                return;
11            }
12        }
13    }
14}

chainNextJob(handle)

Abstract method called by the framework when more pages remain. Override this in your concrete subclass to enqueue the next job, passing the provided QueryHandle to the next job's constructor.

Signature

public abstract void chainNextJob(sfsqlquery.QueryHandle handle)

Parameters

handle
Type: sfsqlquery.QueryHandle
QueryHandle tracking the current query state, including position for the next page. Pass this to your next job's constructor.

Return Value

Type: void

getColumnNames()

Returns the ordered list of column names from the current data chunk. Call this inside processDataChunk().

Signature

public List<String> getColumnNames()

Return Value

Type: List<String>

An ordered list of column names as they appear in the result set.

Example

See getMetadata() for a combined example.

getMetadata()

Returns the column metadata for the current data chunk, including column names and data types. Call this inside processDataChunk().

Signature

public List<ConnectApi.QuerySqlMetadataItem> getMetadata()

Return Value

Type: List<ConnectApi.QuerySqlMetadataItem>

A list of ConnectApi.QuerySqlMetadataItem objects describing each column's name and data type.

Example

Use metadata and column names for dynamic column handling:

1public override void processDataChunk() {
2    List<String> columns = getColumnNames();
3    List<ConnectApi.QuerySqlMetadataItem> metadata = getMetadata();
4
5    System.debug('Query returned ' + columns.size() + ' columns');
6    for (Integer i = 0; i < metadata.size(); i++) {
7        System.debug(columns[i] + ' (' + metadata[i].type + ')');
8    }
9
10    // Process rows using the metadata
11    for (sfsqlquery.Row row : getRows()) {
12        for (String columnName : columns) {
13            Object value = row.getObject(columnName);
14            System.debug(columnName + ': ' + value);
15        }
16    }
17}

getPageOutput()

Returns the raw ConnectApi.QuerySqlPageOutput for the current page. Use this inside processDataChunk() when you need direct access to the underlying API response instead of Row objects.

Signature

public ConnectApi.QuerySqlPageOutput getPageOutput()

Return Value

Type: ConnectApi.QuerySqlPageOutput

The raw ConnectApi.QuerySqlPageOutput for the current page.

Example

Access raw API response for custom processing:

1public override void processDataChunk() {
2    ConnectApi.QuerySqlPageOutput output = getPageOutput();
3    System.debug('Page size: ' + output.rows.size());
4    System.debug('Done: ' + output.done);
5}

getQueryId()

Returns the server-assigned ID for this query. Save this value to resume the query in a later job using QueryHandle.create().

Signature

public String getQueryId()

Return Value

Type: String

The server-assigned query ID string.

Example

Save the query ID to resume later:

1public override void processDataChunk() {
2    String queryId = getQueryId();
3    // Store queryId in a custom object or platform cache
4    MyQueryState__c state = new MyQueryState__c(QueryId__c = queryId);
5    insert state;
6}

getRows()

Returns the rows in the current data chunk as an iterable of Row objects. Call this inside processDataChunk() to iterate over the page with typed accessor methods.

Signature

public Iterable<sfsqlquery.Row> getRows()

Return Value

Type: Iterable

An iterable of Row objects for the current page.

Example

Iterate over rows and insert records:

1public override void processDataChunk() {
2    List<Account> accounts = new List<Account>();
3    for (sfsqlquery.Row row : getRows()) {
4        accounts.add(new Account(
5            Name = row.getString('Name__c'),
6            AnnualRevenue = row.getDecimal('Revenue__c')
7        ));
8    }
9    insert accounts;
10}

processDataChunk()

Abstract method called by the framework with each page of query results. Override this in your concrete subclass to process the data chunk. Use getRows() or getPageOutput() to access the current page's data.

Signature

public abstract void processDataChunk()

Return Value

Type: void

toString()

Returns a string representation of this SqlQueueable.

Signature

public String toString()

Return Value

Type: String

A string representation of this SqlQueueable.