Next: , Previous: Using BTrees, Up: Tutorial


2.10 Using Cursors

You can traverse BTrees with cursors. Open one with

     * (defvar curs (make-cursor *friends-birthdays*))
     => CURS

and close it with

     * (cursor-close curs)
     => NIL

Typically one opens a cursor within an transaction. Cursors should be closed after they are done with, before the enclosing transaction is closed. This is encapsulated in the idiom

     * (with-transaction ()
        (with-btree-cursor (curs *friends-birthdays*)
         ...))

The cursor movement functions in general return three values: a boolean indicating whether a pair was found / available, the key, and the value. For example:

     * (cursor-current curs) ; Not initialized!
     => NIL
     
     * (cursor-first curs)
     => T
        "Andrew"
        2429071200
     
     * (cursor-next curs)
     => T
        "Ben"
        2407298400
     
     * (cursor-next curs) ; No more entries!
     => NIL

Other cursor-* functions include: prev, last, current, set (set to a key), set-range (get the first key greater or equal to the key), get-both (set to a key / value pair), get-both-range (set to a key / value pair with value greater or equal to a particular value), et cetera. Details can be found at Cursors. In general if a movement command fails, the cursor is invalidated, and has to be repositioned.

Internally, BTree keys and values are sorted by an ad-hoc C function. It is capable of sorting most numbers (floats are fine, integers up to 64 bits) and strings (case-insensitively, though Unicode users will find their strings sorted code-point-order which is case sensitive.) Other values it sorts byte-lexically, which is usually meaningless in Lisp.

Finally, one can also insert and delete by cursor, and there is a map-btree function, which functions analogously to the maphash CL function.