glindex/cursor

Cursor-based iteration over store or index records.

Cursors let you walk through a range of records one at a time, optionally mutating or deleting each one as you go. They are opened via glindex/store.open_cursor and glindex/index.open_cursor.

The iteration model is accumulator-based: your handler receives the current accumulator and the cursor, and returns a Promise of the new accumulator paired with a navigation instruction. Use cursor.continue() to advance, cursor.stop() to finish early, or cursor.advance(n) to skip ahead. The final accumulator is returned as the Result of the cursor call.

Transaction lifetime warning: the same rule as for regular operations applies inside a cursor handler - do not await anything unrelated to the database (HTTP requests, timers, etc.) between cursor steps, or the transaction will auto-close and the next step will fail with TransactionInactiveError.

Example

use result <- promise.await(
  store.open_cursor(tx, s, glindex.All, cursor.Next, [], fn(acc, cur) {
    case cursor.cursor_value(cur) {
      Ok(track) -> promise.resolve(#([track, ..acc], cursor.continue()))
      Error(_) -> promise.resolve(#(acc, cursor.stop()))
    }
  }),
)

Types

The cursor handle passed to your iteration handler.

pub type Cursor(has_value, mode, source, t, p, k)

The direction in which the cursor walks through the records.

  • Next - ascending key order, visiting all records.
  • Prev - descending key order, visiting all records.
  • NextUnique - ascending key order, skipping duplicate index keys.
  • PrevUnique - descending key order, skipping duplicate index keys.
pub type CursorDirection {
  Next
  Prev
  NextUnique
  PrevUnique
}

Constructors

  • Next
  • Prev
  • NextUnique
  • PrevUnique

Errors that can occur inside a cursor handler.

pub type CursorError {
  UnableToDecode(List(decode.DecodeError))
  CursorUnknownError(String)
}

Constructors

Opaque instruction returned from a cursor handler to control iteration.

Construct one with continue, advance, stop, continue_key, or continue_primary_key.

pub opaque type CursorNext(source, p, k)

Values

pub fn advance(n: Int) -> CursorNext(source, p, k)

Skip forward n records from the current position.

pub fn continue() -> CursorNext(source, p, k)

Advance to the next record in the current direction.

pub fn continue_key(key: k) -> CursorNext(source, p, k)

Jump to the first record whose key is greater than or equal to key.

pub fn continue_primary_key(
  key: k,
  primary_key: p,
) -> CursorNext(@internal IndexCursor, p, k)

Jump to the record with the given index key and primary key.

Only valid for index cursors (IndexCursor). Useful for efficiently seeking within a sorted index without visiting every intermediate record.

pub fn cursor_delete(
  cursor: Cursor(
    @internal WithValue,
    @internal ReadWrite,
    source,
    t,
    p,
    k,
  ),
) -> promise.Promise(Result(Nil, CursorError))

Delete the record at the current cursor position.

Only available on read-write cursors (ReadWrite) that carry a value (WithValue).

pub fn cursor_direction(
  cursor: Cursor(value, mode, source, t, p, k),
) -> CursorDirection

Return the direction the cursor is walking.

pub fn cursor_key(
  cursor: Cursor(value, mode, source, t, p, k),
) -> Result(k, CursorError)

Return the key of the record at the current cursor position.

pub fn cursor_primary_key(
  cursor: Cursor(value, mode, source, t, p, k),
) -> Result(p, CursorError)

Return the primary key of the record at the current cursor position.

For store cursors this is the same as cursor_key. For index cursors it is the underlying record key in the object store, which may differ from the indexed key.

pub fn cursor_update(
  cursor: Cursor(
    @internal WithValue,
    @internal ReadWrite,
    source,
    t,
    p,
    k,
  ),
  value: t,
) -> promise.Promise(Result(Nil, CursorError))

Replace the record at the current cursor position with value.

Only available on read-write cursors (ReadWrite) that carry a value (WithValue). The key of the record does not change. value is serialized using the to_value function from the store definition.

pub fn cursor_value(
  cursor: Cursor(@internal WithValue, mode, source, t, p, k),
) -> Result(t, CursorError)

Decode and return the record at the current cursor position.

Only available on cursors opened with store.open_cursor or index.open_cursor (WithValue). Key-only cursors do not carry the record value and cannot call this function.

pub fn stop() -> CursorNext(source, p, k)

Stop iteration and return the current accumulator.

Search Document