Note: This release is in preview. Features described here don’t become generally available until the latest general availability date that Salesforce announces for this release. Before then, and where features are noted as beta, pilot, or developer preview, we can’t guarantee general availability within any particular time frame or at all. Make your purchase decisions only on the basis of generally available products and features.
Compound Filters in the Apex Connector Framework
Filters can have child filters, which are stored in the subfilters property.
If a filter has children, the filter type must be one of the following.
| Filter Type | Description |
|---|---|
| AND_ | We return all rows that match all of the subfilters. |
| OR_ | We return all rows that match any of the subfilters. |
| NOT_ | The filter reverses how its child filter evaluates rows. Filters of this type can have only one subfilter. |
This code example illustrates how to deal with compound filters.
1override global DataSource.TableResult query(DataSource.QueryContext context) {
2 // Call out to an external data source and retrieve a set of records.
3 // We should attempt to get as much information as possible about the
4 // query from the QueryContext, to minimize the number of records
5 // that we return.
6 List<Map<String,Object>> rows = retrieveData(context);
7
8 // This only filters the results. Anything in the query that we don’t
9 // currently support, such as aggregation or sorting, is ignored.
10 return DataSource.TableResult.get(context, postFilterRecords(
11 context.tableSelection.filter, rows));
12}
13
14private List<Map<String,Object>> retrieveData(DataSource.QueryContext context) {
15 // Call out to an external data source. Form the callout so that
16 // it filters as much as possible on the remote site,
17 // based on the parameters in the QueryContext.
18 return ...;
19}
20
21private List<Map<String,Object>> postFilterRecords(
22 DataSource.Filter filter, List<Map<String,Object>> rows) {
23 if (filter == null) {
24 return rows;
25 }
26 DataSource.FilterType type = filter.type;
27 List<Map<String,Object>> retainedRows = new List<Map<String,Object>>();
28 if (type == DataSource.FilterType.NOT_) {
29 // We expect one Filter in the subfilters.
30 DataSource.Filter subfilter = filter.subfilters.get(0);
31 for (Map<String,Object> row : rows) {
32 if (!evaluate(filter, row)) {
33 retainedRows.add(row);
34 }
35 }
36 return retainedRows;
37 } else if (type == DataSource.FilterType.AND_) {
38 // For each filter, find all matches; anything that matches ALL filters
39 // is returned.
40 retainedRows = rows;
41 for (DataSource.Filter subfilter : filter.subfilters) {
42 retainedRows = postFilterRecords(subfilter, retainedRows);
43 }
44 return retainedRows;
45 } else if (type == DataSource.FilterType.OR_) {
46 // For each filter, find all matches. Anything that matches
47 // at least one filter is returned.
48 for (DataSource.Filter subfilter : filter.subfilters) {
49 List<Map<String,Object>> matchedRows = postFilterRecords(
50 subfilter, rows);
51 retainedRows.addAll(matchedRows);
52 }
53 return retainedRows;
54 } else {
55 // Find all matches for this filter in our collection of records.
56 for (Map<String,Object> row : rows) {
57 if (evaluate(filter, row)) {
58 retainedRows.add(row);
59 }
60 }
61 return retainedRows;
62 }
63}
64
65private Boolean evaluate(DataSource.Filter filter, Map<String,Object> row) {
66 if (filter.type == DataSource.FilterType.EQUALS) {
67 String columnName = filter.columnName;
68 Object expectedValue = filter.columnValue;
69 Object foundValue = row.get(columnName);
70 return expectedValue.equals(foundValue);
71 } else {
72 // Throw an exception; implementing other filter types is left
73 // as an exercise for the reader.
74 throwException('Unexpected filter type: ' + filter.type);
75 }
76 return false;
77}