WiredTiger: Cursors in Java

| Version 3.1.0

Fork me on GitHub Join my user group
Cursors in Java

Common operations in WiredTiger are performed using Cursor handles. A cursor includes:

- a position within a data source
- getter/setters for key and value fields
- encoding of fields to store in the data source
- methods to navigate within and iterate through the data

See Cursor operations in Java for a description of how to use cursors.

# Cursor types

The following are the builtin basic cursor types:

URI | Type | Notes
--- | --- | ---
`table:<table name>[<projection>]` | table cursor | table key, table value(s) with optional projection of columns
`colgroup:<table name>:<column group name>` | column group cursor | table key, column group value(s)
`index:<table name>:<index name>[<projection>]` | index cursor | key=index key, value=table value(s) with optional projection of columns
`join:table:<table name>[<projection>]` | join cursor | key=table key, value=table value(s) with optional projection of columns

Some administrative tasks can be accomplished using the following special cursor types that give access to data managed by WiredTiger:

URI | Type | Notes
--- | --- | ---
`backup:` | backup cursor | key=`string`, see Backups for details
`log:` | log cursor | key=`(long fileID, long offset, int seqno)`, value=`(uint64_t txnid, uint32_t rectype, uint32_t optype, uint32_t fileid, WT_ITEM key, WT_ITEM value)`, see Log cursors for details
`metadata:[create]` | metadata cursor (optionally only returning configuration strings for WT_SESSION::create if `create` is appended | key=`string`, value=`string`, see Reading WiredTiger Metadata for details
`statistics:[<data source URI>]` | database | data source or join statistics cursor | key=`int id`, value=`(string description, string value, uint64_t value)`, see Statistics Data for details

Advanced applications may also open the following low-level cursor types:

URI | Type | Notes
--- | --- | ---
`file:<file name>` | file cursor | file key, file value(s)
`lsm:<name>` | LSM cursor (key=LSM key, value=LSM value) | LSM key, LSM value, see Log-Structured Merge Trees

See the following for more details:

- Data Sources in Java
- Reading WiredTiger Metadata
- Log cursors in Java
- Join cursors in Java

# Projections

Cursors on tables and indices can return a subset of columns. This is done by listing the column names in parenthesis in the `uri` parameter to Session.open_cursor. Only the fields from the listed columns are returned by Cursor.get_value.

The ex_schema.java example creates a table where the value format is `"5sHq"`, where the initial string is the country, the short is a year, and the long is a population. The following example lists just the country and year columns from the table record values:

/*
* Use a projection to return just the table's country and year
* columns.
*/
cursor = session.open_cursor("table:poptable(country,year)", null, null);
while ((ret = cursor.next()) == 0) {
country = cursor.getValueString();
year = cursor.getValueShort();
System.out.println("country " + country + ", year " + year);
}

This is particularly useful with index cursors, because if all columns in the projection are available in the index (including primary key columns, which are the values of the index), the data can be read from the index without accessing any column groups. See Index cursor projections for more information.

# Cursors and Transactions

If there is a transaction active in a session, cursors operate in the context of that transaction. Reads performed while a transaction is active inherit the isolation level of the transaction, and updates performed within a transaction are made durable by calling Session.commit_transaction, or discarded by calling Session.rollback_transaction.

If no transaction is active, cursor reads are performed at the isolation level of the session, set with the `isolation` configuration key to Connection.open_session and successful updates are automatically committed before the update operation completes.

Any operation that consists of multiple related updates should be enclosed in an explicit transaction to ensure that the updates are applied atomically.

At `read-committed` (the default) or `snapshot` isolation levels, committed changes from concurrent transactions become visible when no cursor is positioned. In other words, at these isolation levels, all cursors in a session read from a stable snapshot while any cursor in the session remains positioned.

Cursor positions survive transaction boundaries, unless a transaction is rolled back. When a transaction is rolled-back either implicitly or explicitly, all cursors in the session are reset as if the Cursor.reset method was called, discarding any cursor position as well as any key and value.

See Transactions in Java for more information.

# Cursors and Eviction

Cursor positions hold resources that can inhibit the eviction of memory pages. If a cursor is active on a page being considered for eviction, the eviction will defer until the cursor is moved or reset. To avoid this and to keep resources freed in general, an application should call Cursor.reset during times it does not need to keep the cursor positioned. A cursor that has been reset is not active and will not inhibit eviction.

# Raw mode

Cursors can be configured for raw mode by specifying the `"raw"` config keyword to Session.open_cursor. In this mode, the methods Cursor.get_key, Cursor.get_value, Cursor.set_key and Cursor.set_value all take a single byte array in the variable-length argument list instead of a separate argument for each column.

The following example lists the table record values, using raw mode:

cursor = session.open_cursor("table:poptable", null, "raw");
while ((ret = cursor.next()) == 0) {
byte[] key, value;
key = cursor.getKeyByteArray();
System.out.println(Arrays.toString(key));
value = cursor.getValueByteArray();
System.out.println("raw key: " + Arrays.toString(key) +
", raw value: " + Arrays.toString(value));
}

Raw mode can be used in combination with projections. The following example lists just the country and year columns from the table record values, using raw mode:

/*
* Use a projection to return just the table's country and year
* columns.
*/
cursor = session.open_cursor("table:poptable(country,year)", null, null);
while ((ret = cursor.next()) == 0) {
country = cursor.getValueString();
year = cursor.getValueShort();
System.out.println("country " + country + ", year " + year);
}

# Reading WiredTiger Metadata

WiredTiger cursors provide access to data from a variety of sources. One of these sources is the list of objects in the database.

To retrieve the list of database objects, open a cursor on the uri `metadata:`. Each returned key will be a database object and each returned value will be the information stored in the metadata for object named by the key.

For example:

cursor = session.open_cursor("metadata:", null, null);

To retrieve value strings that are valid arguments for calls to Session.create, open a cursor on `metadata:create`.

The metadata cursor is read-only, and the metadata cannot be modified.