Next: , Previous: Persistent BTrees, Up: User Guide

4.7 BTree Cursors

Aside from getting, setting and dropping key-value pairs from the database, you can also traverse the BTree structure one key-value pair at a time.

Cursors must be created in the context of an active transaction (i.e. a with/ensure-transaction body). A cursor is made through a call to the make-cursor method of the BTree you wish to traverse. You must ensure that the cursor gets closed when the stack is unwound; it's best to use the convenience macro with-btree-cursor instead of make-cursor.

An existing cursors can also be duplicated within the same transaction by calling cursor-duplicate which avoids the overhead of setting a second cursor to the same location.

Cursors can be in two states: initialized and uninitialized. BTree Cursor API for details.

To initialize a cursor, you have to use one of the initializing functions to select a key-value pair in the btree.

A valid cursor will return multiple values: (exists? key value). The first argument tells whether or not the cursor is initialized and pointing at a proper value. The second two arguments are self-explanatory.

cursor-current returns the current state of the cursor, nil if it is uninitialized.

Once a cursor is properly initialized, it can be incremented or decremented, a simple constant-time operation on BTrees.

cursor-next and cursor-prev move the cursor a single step forward or back across the sorted key-value pairs. cursor-next moves in ascending order, cursor-prev in descending order.

Finally cursors can be used for side effects on the current key-value pair. The function cursor-put replaces the value (but does not increment the current value) and cursor-delete deletes the key-value pair and become uninitialized. It is a valid operation to use the (setf get-value) method while the cursor is active to change the value at the current cursor.

If cursors take place within a transaction, what happens when traversing a very large BTree? This depends on the data store policy regarding whether a cursor read locks its entire btree (or the subset that is being iterated over) or allows changes to any pairs its transaction has not changed. See your data store documentation for details.