Direct Access API¶
The Relational Layer’s Direct Access API is a simplified API for accessing data within specific ranges. It avoids using SQL directly, but it uses the same interface as the SQL connection to allow intermingling of SQL queries with these simpler operations. The intent is to provide highly simplified access for common current use-cases (e.g., scanning records within a specific range), but it is highly limited. For more powerful query execution, use the SQL query language instead.
The Direct Access API consists of the following operations:
Scan
Get
Insert
Delete
Scan¶
Scans can access all records which fit within a specified primary key or index key range. These scans can be arbitrarily large, based on the data and the range of interest, and thus continuations are provided to enable paginated queries. For example
try (RelationalStatement statement = createStatement()) {
TableScan scan = TableScan.newBuilder()
.setStartKey(<startKeyName>, <startKeyValue>)
// fill in the rest of the starting keys...
.setEndKey(<endKeyName>, <endKeyValue>)
// fill in the rest of the ending keys...
.build();
Continuation continuation = Continuation.BEGIN;
int continuationBatchSize = 10;
while (!continuation.isEnd()) {
int rowCount = 0;
try (RelationalResultSet scanResultSet = statement.executeScan(<tableName>, scan, <options>) {
while(scanResultSet.next()) {
//process a returned record
rowCount++;
if (rowCount == continuationBatchSize) {
continuation = scanResultSet.getContinuation();
break;
}
}
}
}
}
Scan keys can be partial, as long as they are contiguous. You can specify pk1, pk2
, but not pk1, pk3
;
otherwise, the API will throw an error.
The returned ResultSet
can access a continuation, which is a pointer to the first row which has not yet been read.
Put another way, if the current location in the ResultSet
is position X
, then the continuation will point to position X+1
.
This can be used as a marker for restarting a given query. By passing the continuation to the API when executing the
same statement again, the continuation will be used to resume the execution at the specified location.
Get¶
The Get operation provides the ability to specify the primary key of a certain record, and quickly return the record associated with that Primary Key from a specific table. If the record does not exist, then the result set will be empty.
try (RelationalStatement statement = createStatement()) {
KeySet primaryKey = new KeySet()
.setKeyColumn("<pkColumn1Name>", <pkColumn1Value>)
// set the other values for the primary key of the table...
try (RelationalResultSet recordResultSet = statement.executeGet(<tableName>, primaryKey, <options>)) {
if (recordResultSet.next()){
//process the returned record -- there will always be no more than 1 record in the returned result set.
}
}
}
If you specify an incomplete KeySet
(i.e., an incomplete primary key), then the API will throw an error.
Insert¶
The Insert API provides a way to insert a data element into a specific table using programmatic API. The API requires
building a DynamicMessage
, as follows:
try (RelationalStatement statement = createStatement()) {
DynamicMessageBuilder messageBuilder = statement.getMessageBuilder(<tableName>)
.setField(<fieldName>, <fieldValue>)
// set the other fields in the record, including nested or repeated structures...
statement.executeInsert(<tableName>, messageBuilder.build(), <options>);
}
You can also insert multiple records together in batch, using an iterable interface of build records.
Delete¶
Deletes are very similar to inserts, except that you specify the primary keys of the rows that you want to delete:
try (RelationalStatement statement = createStatement()) {
KeySet primaryKey = new KeySet()
.setKeyColumn("<pkColumn1Name>", <pkColumn1Value>)
// set the other values for the primary key of the table...
statement.executeDelete(<tableName>, primaryKey, <options>);
}