Queries and mutations

The example stores the people in a database and queries their names. It collects query pages, updates Ada's age, and reads the changed age.

The optional adaptive query planner learns from runs and compares alternative plans for stored queries. Enable it through the database's plugins open option.

Example

The example compares these results:

  • a committed mutation
  • a repeated mutation
  • a query that matches no entity

Give Ada her birthday and read her age

birthday_text holds this document:

json186 B
{
  "query": {
    "find": [
      "?e"
    ],
    "where": [
      [
        "?e",
        "name",
        "Ada"
      ]
    ]
  },
  "patch": {
    "?e": {
      "age": 37
    }
  }
}

query_text holds this document:

json150 B
{
  "find": [
    "?age"
  ],
  "where": [
    [
      "?e",
      "name",
      "Ada"
    ],
    [
      "?e",
      "age",
      "?age"
    ]
  ]
}
odin588 B
birthday_source := stardust.parse(birthday_text, .JSON) or_return
defer stardust.close(&birthday_source)

birthday := stardust.mutation(db, birthday_source) or_return
defer stardust.close(&birthday)

commit := stardust.run(birthday) or_return
defer stardust.close(&commit)

definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query) or_return
defer stardust.close(&rows)

result := stardust.all_pages(rows) or_return
defer stardust.close(&result)
Result / 25 B
[
  {
    "age": 37
  }
]

Query pages

Each query page is an owned document.

  • You can keep a page after you release the rows handle, query, or database that produced it.
  • Release each page when you finish with its values. The document ownership rule applies.

Cached joins

The database can keep completed native fact joins as owned binding rows before aggregation. When you run the same query and plan again, the cache can supply those rows at the same database snapshot. Aggregates and output expressions still run for each call.

The cache uses the database working-memory budget and gives memory back when queries need it. The cache discards rows from joins that do not complete. After a write, new queries use a new snapshot. An active reader keeps the rows from its original snapshot.

Parameterized, temporal and overlay queries use their normal execution paths. Queries with predicates, derivations, member clauses or transaction terms also use those paths. Background planner trials and sampled foreground measurements execute joins directly.

Exact indexes

A query or mutation definition that compares a field with a value makes the database build that field's exact index. The comparison is a fact clause with a constant or a parameter value, or a =, <, <=, >, >= or hasPrefix predicate on a fact clause's value. With the index, a hasPrefix predicate reads only the texts that start with the prefix, and no value of another type.

  • Storing the definition starts the build. An inline query or mutation that compares a field the same way also starts one.
  • The database builds the index in the background, including the values committed before the definition. The call that started it does not wait.
  • Queries scan the field until its index is ready. The results are the same; only the time differs.
  • Use indexes_sync to wait until every index that earlier definitions and inline runs ask for is ready, for example before you measure a query.
  • An index that no definition uses any more stays until the database next opens.

Operations

OperationReturnsSummary
read_entitydocumentdatabase.read_entity(entity, max_depth, max_entities) atomically returns an owned {document links revisions truncated} document, expanding links up to max_depth hops.
queryqueryOpen an owned query from a path or an inline definition.
mutationmutationOpen an owned mutation from a path or an inline definition.
runrowsRun the query and return an owned row cursor.
closenoneRelease the query handle.
nextdocumentRead the next page as an owned document.
page_iteratorpagesrows.pages() iterates the non-empty pages of the cursor.
all_pagesdocumentrows.all_pages() reads every remaining page into one owned array document.
closenoneRelease the rows handle.
subscribesubscriptionquery.subscribe(parameters, options) opens an owned live subscription.
nexteventWait for the next live event.
eventsUnavailablesubscription.events() delivers events in order until the subscription is cancelled, closes or fails.
cancelnonesubscription.cancel() ends the subscription.
closenoneRelease the subscription handle.
runcommitRun the mutation and return commit information.
closenoneRelease the mutation handle.
merge_patchcommitdatabase.merge_patch(patch) applies an entity-keyed patch document in one transaction and returns commit information.
indexes_syncnonedatabase.indexes_sync(max_wait) waits until the database built every exact index that earlier definition commits and inline runs ask for.
bulk_beginnonedatabase.bulk_begin() starts a bulk build of data merge patches held by the database.
bulk_addnonedatabase.bulk_add(patch) copies and queues one merge-patch document in the bulk build.
bulk_finishdocumentdatabase.bulk_finish() publishes the bulk build with one commit, ends it and returns an owned summary document.
bulk_abortnonedatabase.bulk_abort() drops the bulk build in progress without writing it.
subscription_set_notifyErrorWake a host scheduler when a subscription may be ready.

read_entity

odin174 B
read_entity :: proc(
	db: Database,
	entity: builtin.i64,
	max_depth: builtin.i64 = 0,
	max_entities: builtin.i64 = 0,
	allocator := context.allocator,
) -> (Document, Error)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
entitybuiltin.i64ValueRequiredThe decimal user entity ID.
max_depthbuiltin.i64Value0Link hops to expand along each path, 0 through 32. 0, the default, leaves every link a {#link id} reference.
max_entitiesbuiltin.i64Value0The most entity documents the result holds, counting the root and every expanded or absent target each time it is placed. 0 selects the default of 1000.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentthe entity ID is outside the user entity range, max_depth is negative or above 32, or max_entities is negative
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

revisions maps each placed entity's decimal ID to its last-touch transaction for #_tx.stardust/checkAndSet. Empty object and array fields are omitted recursively. See entity reads for result fields, JSON Pointer links and expansion rules.

Examples

Read Bob with his mentor expanded

odin80 B
result := stardust.read_entity(db, 2, 1) or_return
defer stardust.close(&result)
Result / 291 B
{
  "document": {
    "age": 41,
    "mentor": {
      "age": 36,
      "name": "Ada",
      "role": "engineer"
    },
    "name": "Bob",
    "role": "engineer"
  },
  "links": {
    "/mentor": {
      "#link": 1
    }
  },
  "revisions": {
    "1": 4,
    "2": 4
  },
  "truncated": false
}

C exports: stardust_db_read_entity, stardust_result_take_document, stardust_result_error, stardust_result_release

query

odin91 B
query :: proc(db: Database, path: string, allocator := context.allocator) -> (Query, Error)
odin110 B
query :: proc(
	db: Database,
	definition: Document,
	allocator := context.allocator,
) -> (
	Query,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
pathstringValueRequiredThe stored definition path selected at run time.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.
definitionDocumentBorrowed for the callRequiredThe inline native definition copied into the opened handle.

Errors

StatusWhen
.Not_Foundno definition is stored at the path
.Invalid_Definitionthe definition is invalid
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

Inline definitions are copied. Stored paths select their definition at run time.

Query documents.

Examples

Open an inline query and read its first page

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin309 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query) or_return
defer stardust.close(&rows)

result := stardust.next(rows) or_return
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

Refuse an invalid query definition

query_text holds this document:

json29 B
{
  "find": [
    "?x"
  ]
}
odin199 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query, result := stardust.query(db, definition)
defer stardust.close(&query)
defer stardust.close(&result)
Result / 168 B
{
  "code": "unbound_variable",
  "message": "Unbound_Variable",
  "path": null,
  "field": null,
  "entity": null,
  "offset": null,
  "status": "invalid_definition"
}

Report a missing stored query

odin112 B
query, result := stardust.query(db, "people/missing")
defer stardust.close(&query)
defer stardust.close(&result)
Result / 174 B
{
  "code": "not_found",
  "message": "no definition at this path",
  "path": "people/missing",
  "field": null,
  "entity": null,
  "offset": null,
  "status": "not_found"
}

C exports: stardust_db_query_open, stardust_db_query_error

mutation

odin97 B
mutation :: proc(db: Database, path: string, allocator := context.allocator) -> (Mutation, Error)
odin116 B
mutation :: proc(
	db: Database,
	definition: Document,
	allocator := context.allocator,
) -> (
	Mutation,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
pathstringValueRequiredThe stored definition path selected at run time.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.
definitionDocumentBorrowed for the callRequiredThe inline native definition copied into the opened handle.

Errors

StatusWhen
.Not_Foundno definition is stored at the path
.Invalid_Definitionthe definition is invalid
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

Inline definitions are copied. Stored paths select their definition at run time.

Mutation documents.

Examples

database/mutation

birthday_text holds this document:

json186 B
{
  "query": {
    "find": [
      "?e"
    ],
    "where": [
      [
        "?e",
        "name",
        "Ada"
      ]
    ]
  },
  "patch": {
    "?e": {
      "age": 37
    }
  }
}
odin263 B
source := stardust.parse(birthday_text, .JSON) or_return
defer stardust.close(&source)

mutation := stardust.mutation(db, source) or_return
defer stardust.close(&mutation)

commit := stardust.run(mutation) or_return
defer stardust.close(&commit)

result := commit
Result / 111 B
{
  "status": "committed",
  "transaction": 5,
  "facts": 1,
  "committed_at": 17923367876843352,
  "ids": {}
}

C exports: stardust_db_mutation_open, stardust_db_mutation_error

run

odin172 B
run :: proc(
	query: Query,
	parameters: Document = {},
	options: Run_Options = {},
	explain: ^Query_Explain = nil,
	allocator := context.allocator,
) -> (
	Rows,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
queryQueryBorrowed for the callRequiredThe query owner for this operation. Keep it alive during the call.
parametersDocumentBorrowed for the call{}An optional object of parameter values that merge-patches the definition's declared parameters. A parameter matched in the entity position of a fact clause takes an entity reference {#link id}, never the bare ID number: a commit returns IDs as numbers, so wrap one as {#link id}, or as the typed Link value where the binding has one, before passing it. A query run fails with entity_reference_expected when a bare number reaches that position. Projected and found entities also read back as {#link id}, so a typed field that receives one uses Link rather than a plain integer.
optionsRun_OptionsValue{}The operation's options record. See its field defaults.
explain^Query_ExplainCaller-owned outputnilOptional explain output. This record contains explain output for query run. The compile, plan, execute, group and order fields divide the wall time of run into stages.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Not_Foundthe stored query definition was deleted
.Invalid_Definitionthe loaded query definition is invalid
.Invalid_Argumentthe parameters or run options are invalid
.Evaluation_Failedthe query fails or exceeds max_cost
.Closedthe query is closed
.Out_Of_Memorynative memory is exhausted

Notes

Query documents.

Examples

Open an inline query and read its first page

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin309 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query) or_return
defer stardust.close(&rows)

result := stardust.next(rows) or_return
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

Capture the host duration boundary

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}

boundary_text holds this document:

json20 B
9223372036854775807
odin537 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

boundary := stardust.parse(boundary_text, .JSON) or_return
defer stardust.close(&boundary)

nanoseconds := stardust.i64(boundary, stardust.root(boundary) or_return) or_return
options := stardust.Run_Options{page_size = 2, max_cost = time.Duration(nanoseconds)}
rows := stardust.run(query, options = options) or_return
defer stardust.close(&rows)

result := options
Result / 67 B
{
  "page_size": 2,
  "max_cost": 92233720368547758,
  "as_of": 0
}

Truncate a positive sub-tick duration

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}

boundary_text holds this document:

json3 B
99
odin537 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

boundary := stardust.parse(boundary_text, .JSON) or_return
defer stardust.close(&boundary)

nanoseconds := stardust.i64(boundary, stardust.root(boundary) or_return) or_return
options := stardust.Run_Options{page_size = 2, max_cost = time.Duration(nanoseconds)}
rows := stardust.run(query, options = options) or_return
defer stardust.close(&rows)

result := options
Result / 51 B
{
  "page_size": 2,
  "max_cost": 0,
  "as_of": 0
}

Explain query execution

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin309 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

explain: stardust.Query_Explain
rows := stardust.run(query, explain = &explain) or_return
defer stardust.close(&rows)

result := explain
Result / 670 B
{
  "load_definition": {
    "cpu": 642,
    "wall": 653,
    "arena_bytes": 1680
  },
  "parameters": {
    "cpu": 9,
    "wall": 11,
    "arena_bytes": 0
  },
  "run": {
    "cpu": 10045,
    "wall": 10077,
    "arena_bytes": 7424
  },
  "total": {
    "cpu": 10726,
    "wall": 10770,
    "arena_bytes": 9104
  },
  "arena_capacity": 4194304,
  "work": 6827,
  "rows": 3,
  "compile": 259,
  "plan": 507,
  "execute": 0,
  "group": 0,
  "order": 0,
  "memory_bytes": 5995,
  "memory_refusals": 0,
  "budget_bytes": 10489856512,
  "budget_used_bytes": 10194,
  "budget_peak_bytes": 14267,
  "budget_refusals": 0,
  "retry": 0,
  "stages_completed": 3,
  "retries": 0
}

A negative Odin duration keeps its sign at the ABI boundary

odin59 B
result := stardust.Run_Options{max_cost = -time.Nanosecond}
Result / 52 B
{
  "page_size": 0,
  "max_cost": -1,
  "as_of": 0
}

Run with typed query options

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin347 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

options := stardust.Run_Options{page_size = 2, max_cost = time.Second}
rows := stardust.run(query, options = options) or_return
defer stardust.close(&rows)

result := options
Result / 58 B
{
  "page_size": 2,
  "max_cost": 10000000,
  "as_of": 0
}

C exports: stardust_db_query_run, stardust_db_rows_error

close

odin28 B
close :: proc(query: ^Query)

Consumes the receiver handle.

Parameters

ParameterTypeOwnershipDefaultMeaning
query^QueryConsumed ownerRequiredThe query owner to release. Do not use it after this call.

Examples

Open an inline query and read its first page

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin333 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query) or_return
defer stardust.close(&rows)

result := stardust.next(rows) or_return
defer stardust.close(&result)

stardust.close(&query)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_query_release

next

odin77 B
next :: proc(rows: Rows, allocator := context.allocator) -> (Document, Error)

Parameters

ParameterTypeOwnershipDefaultMeaning
rowsRowsBorrowed for the callRequiredThe rows owner for this operation. Keep it alive during the call.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Evaluation_Failedthe page does not render
.Closedthe rows is closed
.Out_Of_Memorynative memory is exhausted

Notes

An empty array ends the cursor. Every page reads the snapshot selected by the run. Returned pages survive cursor and database closure.

Examples

Open an inline query and read its first page

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin309 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query) or_return
defer stardust.close(&rows)

result := stardust.next(rows) or_return
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_rows_next, stardust_result_take_document, stardust_result_error, stardust_result_release

page_iterator

odin82 B
page_iterator :: proc(rows: Rows, allocator := context.allocator) -> Page_Iterator

Parameters

ParameterTypeOwnershipDefaultMeaning
rowsRowsBorrowed for the callRequiredThe rows owner for this operation. Keep it alive during the call.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Evaluation_Faileda page does not render
.Closedthe rows is closed
.Out_Of_Memorynative memory is exhausted

Notes

Pages are read lazily from the run's snapshot. Rust callers own each page. In other bindings, a page closes when iteration advances. Use next to retain an owned page. Close the cursor separately.

Examples

Iterate the pages of a query run

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin466 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query, options = stardust.Run_Options{page_size = 1}) or_return
defer stardust.close(&rows)

it := stardust.page_iterator(rows)
defer stardust.page_iterator_destroy(&it)
result: i64 = 0
for _ in stardust.iterate_pages(&it) {
	result += 1
}
if it.err != nil {return it.err}
Result / 1 B
3

C exports: stardust_db_rows_next, stardust_result_take_document, stardust_result_error, stardust_result_release, stardust_document_root, stardust_document_read_many, stardust_document_release

all_pages

odin97 B
all_pages :: proc(rows: Rows, allocator := context.allocator) -> (result: Document, error: Error)

Parameters

ParameterTypeOwnershipDefaultMeaning
rowsRowsBorrowed for the callRequiredThe rows owner for this operation. Keep it alive during the call.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Evaluation_Faileda page does not render
.Closedthe rows is closed
.Out_Of_Memorynative memory is exhausted

Notes

The array contains rows, not page documents. Previously read pages are excluded. Memory grows with the remaining result. Use pages for bounded page-by-page processing. Close the cursor separately.

Examples

Read all remaining rows into one document

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin361 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query, options = stardust.Run_Options{page_size = 1}) or_return
defer stardust.close(&rows)

result := stardust.all_pages(rows) or_return
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_rows_next, stardust_result_take_document, stardust_result_error, stardust_result_release, stardust_document_count, stardust_document_read_many, stardust_document_i64, stardust_document_f64, stardust_document_release, stardust_document_builder_create, stardust_document_builder_add_many, stardust_document_builder_seal, stardust_document_builder_release

close

odin26 B
close :: proc(rows: ^Rows)

Consumes the receiver handle.

Parameters

ParameterTypeOwnershipDefaultMeaning
rows^RowsConsumed ownerRequiredThe rows owner to release. Do not use it after this call.

Examples

Open an inline query and read its first page

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin332 B
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)

query := stardust.query(db, definition) or_return
defer stardust.close(&query)

rows := stardust.run(query) or_return
defer stardust.close(&rows)

result := stardust.next(rows) or_return
defer stardust.close(&result)

stardust.close(&rows)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_rows_release

subscribe

odin154 B
subscribe :: proc(
	query: Query,
	parameters: Document = {},
	options: Run_Options = {},
	allocator := context.allocator,
) -> (
	Subscription,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
queryQueryBorrowed for the callRequiredThe query owner for this operation. Keep it alive during the call.
parametersDocumentBorrowed for the call{}An optional object of parameter values that merge-patches the definition's declared parameters. A parameter matched in the entity position of a fact clause takes an entity reference {#link id}, never the bare ID number: a commit returns IDs as numbers, so wrap one as {#link id}, or as the typed Link value where the binding has one, before passing it. A query run fails with entity_reference_expected when a bare number reaches that position. Projected and found entities also read back as {#link id}, so a typed field that receives one uses Link rather than a plain integer.
optionsRun_OptionsValue{}The operation's options record. See its field defaults.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Definitionthe query or its callable definitions are invalid
.Invalid_Argumentthe parameters or subscription options are invalid
.Closedthe query is closed
.Out_Of_Memorynative memory is exhausted

Notes

The subscription copies its definition and parameters. Later definition edits do not change it. The page_size option is ignored.

Blocking next works without registration. To wake your scheduler, see Readiness callbacks for registration, waiting and context lifetime.

Query documents.

Examples

query/subscribe

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin352 B
source := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&source)

query := stardust.query(db, source) or_return
defer stardust.close(&query)

subscription := stardust.subscribe(query) or_return
defer stardust.close(&subscription)

event := stardust.next(subscription, 0) or_return
result := event.result
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

Read the complete initial subscription event

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin330 B
source := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&source)

query := stardust.query(db, source) or_return
defer stardust.close(&query)

subscription := stardust.subscribe(query) or_return
defer stardust.close(&subscription)

result := stardust.next(subscription, 0) or_return
defer stardust.close(&result)
Result / 174 B
{
  "sequence": 1,
  "superseded": 0,
  "transaction": 4,
  "result": [
    {
      "name": "Ada"
    },
    {
      "name": "Bob"
    },
    {
      "name": "Cy"
    }
  ]
}

C exports: stardust_db_query_subscribe, stardust_db_subscription_set_notify, stardust_db_subscription_error

next

odin126 B
next :: proc(
	subscription: Subscription,
	max_wait: time.Duration,
	allocator := context.allocator,
) -> (
	Event,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
subscriptionSubscriptionBorrowed for the callRequiredThe subscription owner for this operation. Keep it alive during the call.
max_waittime.DurationValueRequiredThe maximum wait. Zero checks once.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentmax_wait is negative
.Cancelledthe subscription is cancelled or closed
.Evaluation_Faileda rerun of the query failed. Every later call reports this failure
.Closedthe subscription is closed
.Out_Of_Memorynative memory is exhausted

Notes

Each event replaces the entire result. superseded counts skipped computed results, not commits. Cancel, close and database close wake blocked waits. Windows rounds deadlines to milliseconds.

Examples

subscription/next

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin352 B
source := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&source)

query := stardust.query(db, source) or_return
defer stardust.close(&query)

subscription := stardust.subscribe(query) or_return
defer stardust.close(&subscription)

event := stardust.next(subscription, 0) or_return
result := event.result
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_subscription_next, stardust_db_subscription_error, stardust_document_release

events

Odin callers loop over next directly

C exports: stardust_db_subscription_next, stardust_db_subscription_error

cancel

odin55 B
subscription_cancel :: proc(subscription: Subscription)

Parameters

ParameterTypeOwnershipDefaultMeaning
subscriptionSubscriptionBorrowed for the callRequiredThe subscription owner for this operation. Keep it alive during the call.

Notes

Repeated cancellation is safe. Close the subscription separately to release its handle.

Examples

subscription/cancel

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin382 B
source := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&source)

query := stardust.query(db, source) or_return
defer stardust.close(&query)

subscription := stardust.subscribe(query) or_return
defer stardust.close(&subscription)

event := stardust.next(subscription, 0) or_return
stardust.cancel(subscription)
result := event.result
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_subscription_cancel

close

odin42 B
close :: proc(subscription: ^Subscription)

Consumes the receiver handle.

Parameters

ParameterTypeOwnershipDefaultMeaning
subscription^SubscriptionConsumed ownerRequiredThe subscription owner to release. Do not use it after this call.

Examples

subscription/close

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin383 B
source := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&source)

query := stardust.query(db, source) or_return
defer stardust.close(&query)

subscription := stardust.subscribe(query) or_return
defer stardust.close(&subscription)

event := stardust.next(subscription, 0) or_return
result := event.result
defer stardust.close(&result)

stardust.close(&subscription)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

C exports: stardust_db_subscription_release

run

odin183 B
run :: proc(
	mutation: Mutation,
	parameters: Document = {},
	options: Run_Options = {},
	explain: ^Mutation_Explain = nil,
	allocator := context.allocator,
) -> (
	Commit,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
mutationMutationBorrowed for the callRequiredThe mutation owner for this operation. Keep it alive during the call.
parametersDocumentBorrowed for the call{}An optional object of parameter values that merge-patches the definition's declared parameters. A parameter matched in the entity position of a fact clause takes an entity reference {#link id}, never the bare ID number: a commit returns IDs as numbers, so wrap one as {#link id}, or as the typed Link value where the binding has one, before passing it. A query run fails with entity_reference_expected when a bare number reaches that position. Projected and found entities also read back as {#link id}, so a typed field that receives one uses Link rather than a plain integer.
optionsRun_OptionsValue{}The operation's options record. See its field defaults.
explain^Mutation_ExplainCaller-owned outputnilOptional explain output. This record contains explain output for mutation run.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Definitionthe mutation selection or definition is invalid
.Invalid_Argumentthe parameters or run options are invalid
.Schema_Violationthe write breaks a schema
.Conflictconcurrent writes prevent the commit
.Rejecteda mutation target or write guard refuses the write
.Unavailablethe patch sets stardust/history and no enabled plugin purges history
.Evaluation_Failedthe mutation fails
.Closedthe mutation is closed
.Out_Of_Memorynative memory is exhausted

Notes

Mutation documents.

Examples

mutation/run

birthday_text holds this document:

json186 B
{
  "query": {
    "find": [
      "?e"
    ],
    "where": [
      [
        "?e",
        "name",
        "Ada"
      ]
    ]
  },
  "patch": {
    "?e": {
      "age": 37
    }
  }
}
odin263 B
source := stardust.parse(birthday_text, .JSON) or_return
defer stardust.close(&source)

mutation := stardust.mutation(db, source) or_return
defer stardust.close(&mutation)

commit := stardust.run(mutation) or_return
defer stardust.close(&commit)

result := commit
Result / 111 B
{
  "status": "committed",
  "transaction": 5,
  "facts": 1,
  "committed_at": 17923367880977709,
  "ids": {}
}

Explain mutation execution

birthday_text holds this document:

json186 B
{
  "query": {
    "find": [
      "?e"
    ],
    "where": [
      [
        "?e",
        "name",
        "Ada"
      ]
    ]
  },
  "patch": {
    "?e": {
      "age": 37
    }
  }
}
odin319 B
source := stardust.parse(birthday_text, .JSON) or_return
defer stardust.close(&source)

mutation := stardust.mutation(db, source) or_return
defer stardust.close(&mutation)

explain: stardust.Mutation_Explain
commit := stardust.run(mutation, explain = &explain) or_return
defer stardust.close(&commit)

result := explain
Result / 387 B
{
  "load_definition": {
    "cpu": 902,
    "wall": 908,
    "arena_bytes": 2320
  },
  "parameters": {
    "cpu": 7,
    "wall": 9,
    "arena_bytes": 0
  },
  "run": {
    "cpu": 7352,
    "wall": 64539,
    "arena_bytes": 43856
  },
  "total": {
    "cpu": 8354,
    "wall": 65555,
    "arena_bytes": 46176
  },
  "arena_capacity": 4194304,
  "stages_completed": 3,
  "attempts": 1
}

C exports: stardust_db_mutation_run, stardust_db_result_commit_info, stardust_result_error, stardust_result_release

close

odin34 B
close :: proc(mutation: ^Mutation)

Consumes the receiver handle.

Parameters

ParameterTypeOwnershipDefaultMeaning
mutation^MutationConsumed ownerRequiredThe mutation owner to release. Do not use it after this call.

Examples

mutation/close

birthday_text holds this document:

json186 B
{
  "query": {
    "find": [
      "?e"
    ],
    "where": [
      [
        "?e",
        "name",
        "Ada"
      ]
    ]
  },
  "patch": {
    "?e": {
      "age": 37
    }
  }
}
odin290 B
source := stardust.parse(birthday_text, .JSON) or_return
defer stardust.close(&source)

mutation := stardust.mutation(db, source) or_return
defer stardust.close(&mutation)

commit := stardust.run(mutation) or_return
defer stardust.close(&commit)

result := commit

stardust.close(&mutation)
Result / 111 B
{
  "status": "committed",
  "transaction": 5,
  "facts": 1,
  "committed_at": 17923367880161468,
  "ids": {}
}

C exports: stardust_db_mutation_release

merge_patch

odin144 B
merge_patch :: proc(
	db: Database,
	patch: Document,
	explain: ^Patch_Explain = nil,
	allocator := context.allocator,
) -> (
	Commit,
	Error,
)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
patchDocumentBorrowed for the callRequiredAn entity-keyed native patch. Temporary names use #_name. #_tx holds metadata and an optional stardust/checkAndSet map from entity IDs to expected transactions. Positive expectations match exact last-touch transactions; zero requires no current facts. Conditions are consumed and checked atomically, including for no-ops.
explain^Patch_ExplainCaller-owned outputnilOptional explain output. This record contains explain output for merge_patch.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Commit_Timethe #_tx commit time is not later than the last commit
.Conflictan entity revision check fails or a concurrent writer prevents the commit; a revision mismatch reports the entity and expected and actual revisions
.Rejectedthe database refuses the patch; the code and diagnostic path name the reason and key
.Unavailablethe patch sets stardust/history and no enabled plugin purges history
.Invalid_Argumentthe patch is not an entity-keyed object, or a link names an ID outside the user entity range
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

Patch documents.

Examples

database/merge_patch

seed_text holds this document:

json333 B
{
  "#_ada": {
    "name": "Ada",
    "role": "engineer",
    "age": 36
  },
  "#_bob": {
    "name": "Bob",
    "role": "engineer",
    "age": 41,
    "mentor": {
      "#link": "#_ada"
    }
  },
  "#_cy": {
    "name": "Cy",
    "role": "designer",
    "age": 29
  },
  "#_tx": {
    "author": "smoke",
    "reason": "seed"
  }
}
odin181 B
patch := stardust.parse(seed_text, .JSON) or_return
defer stardust.close(&patch)

commit := stardust.merge_patch(db, patch) or_return
defer stardust.close(&commit)

result := commit
Result / 161 B
{
  "status": "committed",
  "transaction": 4,
  "facts": 12,
  "committed_at": 17923367874874714,
  "ids": {
    "#_ada": 1,
    "#_bob": 2,
    "#_cy": 3
  }
}

Explain patch validation and commit

seed_text holds this document:

json333 B
{
  "#_ada": {
    "name": "Ada",
    "role": "engineer",
    "age": 36
  },
  "#_bob": {
    "name": "Bob",
    "role": "engineer",
    "age": 41,
    "mentor": {
      "#link": "#_ada"
    }
  },
  "#_cy": {
    "name": "Cy",
    "role": "designer",
    "age": 29
  },
  "#_tx": {
    "author": "smoke",
    "reason": "seed"
  }
}
odin224 B
patch := stardust.parse(seed_text, .JSON) or_return
defer stardust.close(&patch)

explain: stardust.Patch_Explain
commit := stardust.merge_patch(db, patch, &explain) or_return
defer stardust.close(&commit)

result := explain
Result / 298 B
{
  "copy_patch": {
    "cpu": 13812,
    "wall": 14034,
    "arena_bytes": 3096
  },
  "commit": {
    "cpu": 456,
    "wall": 32966,
    "arena_bytes": 8008
  },
  "total": {
    "cpu": 14417,
    "wall": 47158,
    "arena_bytes": 11118
  },
  "arena_capacity": 4194304,
  "stages_completed": 2
}

Refuse a metadata-only transaction

patch_text holds this document:

json38 B
{
  "#_tx": {
    "author": "x"
  }
}
odin192 B
patch := stardust.parse(patch_text, .JSON) or_return
defer stardust.close(&patch)

commit, result := stardust.merge_patch(db, patch)
defer stardust.close(&commit)
defer stardust.close(&result)
Result / 199 B
{
  "code": "transaction_only",
  "message": "a patch of only #_tx is refused: #_tx annotates a write",
  "path": "#_tx",
  "field": null,
  "entity": null,
  "offset": null,
  "status": "rejected"
}

Refuse a repeated commit time

future_text holds this document:

json120 B
{
  "#_d": {
    "x": 1
  },
  "#_tx": {
    "stardust/committedAt": {
      "#utc": "2200-01-01T00:00:00Z"
    }
  }
}

older_text holds this document:

json120 B
{
  "#_e": {
    "x": 2
  },
  "#_tx": {
    "stardust/committedAt": {
      "#utc": "2200-01-01T00:00:00Z"
    }
  }
}
odin368 B
future := stardust.parse(future_text, .JSON) or_return
defer stardust.close(&future)

committed := stardust.merge_patch(db, future) or_return
defer stardust.close(&committed)

patch := stardust.parse(older_text, .JSON) or_return
defer stardust.close(&patch)

commit, result := stardust.merge_patch(db, patch)
defer stardust.close(&commit)
defer stardust.close(&result)
Result / 227 B
{
  "code": "invalid_commit_time",
  "message": "stardust/committedAt must be strictly newer than the latest commit time",
  "path": null,
  "field": null,
  "entity": null,
  "offset": null,
  "status": "invalid_commit_time"
}

C exports: stardust_db_merge_patch, stardust_db_result_commit_info, stardust_result_error, stardust_result_release

indexes_sync

odin100 B
indexes_sync :: proc(db: Database, max_wait: time.Duration, allocator := context.allocator) -> Error

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
max_waittime.DurationValueRequiredThe maximum wait. Zero checks once.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentmax_wait is negative
.Timeoutmax_wait passed first
.Closedthe database is closed

Notes

An index that cannot be built does not hold this wait.

Examples

Wait for the exact indexes of the stored queries

odin151 B
stardust.indexes_sync(db, 5 * time.Second) or_return
result := stardust.definitions(db, "queries", "people/.*") or_return
defer stardust.close(&result)
Result / 22 B
[
  "people/by_role"
]

C exports: stardust_db_indexes_sync

bulk_begin

odin73 B
bulk_begin :: proc(db: Database, allocator := context.allocator) -> Error

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumenta bulk build is already in progress on the database
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

On a database with existing facts, each added patch commits immediately and the summary reports fallback true. Closing the database drops an unfinished build.

Examples

Start a bulk build and drop it

odin57 B
stardust.bulk_begin(db) or_return
stardust.bulk_abort(db)

C exports: stardust_db_bulk_begin

bulk_add

odin88 B
bulk_add :: proc(db: Database, patch: Document, allocator := context.allocator) -> Error

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
patchDocumentBorrowed for the callRequiredOne borrowed entity-keyed merge-patch document, as merge_patch takes it. Temporary names use #_name and are scoped to this patch. Transaction metadata uses #_tx. The document is borrowed only until the call returns.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentno bulk build is in progress
.Rejectedthe database refuses the patch; the build has failed and later adds report the same status
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

Patches retain add order. Entity and field order within a patch does not matter. Temporary names resolve within one patch. The call waits for space within the build's memory budget. After failure, use finish for its diagnostic or abort for cleanup.

Patch documents.

Examples

Queue patches in commit order

odin495 B
stardust.bulk_begin(db) or_return
defer stardust.bulk_abort(db)
// The first entity of an empty database is 1, so the second patch updates it.
patch1 := stardust.parse(`{"#_ada":{"name":"Ada"}}`, .JSON) or_return
defer stardust.close(&patch1)
stardust.bulk_add(db, patch1) or_return
patch2 := stardust.parse(`{"1":{"title":"Countess"}}`, .JSON) or_return
defer stardust.close(&patch2)
stardust.bulk_add(db, patch2) or_return
summary := stardust.bulk_finish(db) or_return
stardust.close(&summary)

C exports: stardust_db_bulk_add

bulk_finish

odin86 B
bulk_finish :: proc(db: Database, allocator := context.allocator) -> (Document, Error)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.
allocatormem.AllocatorValuecontext.allocatorAllocator for copied return values and diagnostics. The caller releases them with the same allocator.

Errors

StatusWhen
.Invalid_Argumentno bulk build is in progress
.Rejectedthe database refuses a patch; an initial build publishes nothing and fallback keeps earlier commits
.Conflictanother write committed to the database during the build
.Closedthe database is closed
.Out_Of_Memorynative memory is exhausted

Notes

Finish ends the build even on failure. An initial build publishes all patches or none. Fallback keeps patches already committed.

The summary contains:

FieldMeaning
statuscommitted, or no_change when nothing was written
patches, transactions, facts, entitiesLoad counts
firstTransaction, lastTransactionAssigned transaction range
fallbackWhether patches committed individually
threadsWorker count
tempBytesTemporary run bytes
memoryBytes, memoryPeakBytesReserved memory share and its peak use
phasesparse, assign, rows, updates, spill, build and commit timings, each with wallNs and cpuNs

The memory budget covers build allocations. It excludes operating-system file cache and the process baseline.

Examples

Load patches with one commit and read the summary

odin424 B
stardust.bulk_begin(db) or_return
defer stardust.bulk_abort(db)
patch := stardust.parse(`{"#_ada":{"name":"Ada","title":"Countess"}}`, .JSON) or_return
defer stardust.close(&patch)
stardust.bulk_add(db, patch) or_return
// Finish ends the build also when it fails.
summary := stardust.bulk_finish(db) or_return
defer stardust.close(&summary)
// summary holds status, patches, transactions, facts, entities and phase timings.

C exports: stardust_db_bulk_finish, stardust_result_take_document, stardust_result_error, stardust_result_release

bulk_abort

odin32 B
bulk_abort :: proc(db: Database)

Parameters

ParameterTypeOwnershipDefaultMeaning
dbDatabaseBorrowed for the callRequiredThe database owner for this operation. Keep it alive during the call.

Notes

Abort preserves patches already committed in fallback mode. It is safe without a build or after database closure.

Examples

Drop a bulk build without writing it

odin258 B
stardust.bulk_begin(db) or_return
// Abort writes nothing; without a build it does nothing.
defer stardust.bulk_abort(db)
patch := stardust.parse(`{"#_ada":{"name":"Ada"}}`, .JSON) or_return
defer stardust.close(&patch)
stardust.bulk_add(db, patch) or_return

C exports: stardust_db_bulk_abort

subscription_set_notify

odin37 B
Notify :: #type proc "c"(ctx: rawptr)
odin136 B
subscription_set_notify :: proc(
	subscription: Subscription,
	notify: Notify,
	ctx: rawptr,
	allocator := context.allocator,
) -> Error

Parameters

ParameterRequirementMeaning
subscriptionRequiredSubscription receiving the callback. Use the handle exclusively during registration.
notifyRequiredReadiness callback.
ctxnil is validCaller-owned state, passed unchanged to the callback. Stardust does not read or free it.
allocatorcontext.allocatorAllocator for copied error diagnostics.

Notes

Use this optional callback to wake a host scheduler without polling or a dedicated waiting thread. Blocking next works without registration.

Register a borrowed signal-only C callback once, before any next call. NULL context is valid. Native registration allocates nothing. Install the application waiter before next with zero wait; TIMEOUT arms a coalesced readiness hint. The callback may run on any thread, must return promptly, and must not call Stardust or run application work. Keep callback code and context valid until close returns; no callback is running or can run afterward. Concurrent next calls race for events. A null subscription or callback, duplicate registration, or registration after next reports invalid_argument. A failed subscription preserves its saved failure. A rejected registration retains nothing.

Examples

Wait through a readiness callback

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
odin1.4 kB
definition := stardust.parse(query_text, .JSON) or_return
defer stardust.close(&definition)
query := stardust.query(db, definition) or_return
defer stardust.close(&query)

Waiter :: struct {
	mutex: sync.Mutex,
	changed: sync.Cond,
	generation: i64,
}
waiter: Waiter
notify :: proc "c" (ctx: rawptr) {
	state := (^Waiter)(ctx)
	sync.mutex_lock(&state.mutex)
	state.generation += 1
	sync.cond_broadcast(&state.changed)
	sync.mutex_unlock(&state.mutex)
}
subscription := stardust.subscribe(query) or_return
// Deferred close joins callbacks before this stack context leaves scope.
defer stardust.close(&subscription)
stardust.subscription_set_notify(subscription, notify, &waiter) or_return

started := time.tick_now()
result: stardust.Document
for {
	sync.mutex_lock(&waiter.mutex)
	observed := waiter.generation
	sync.mutex_unlock(&waiter.mutex)
	event, error := stardust.next(subscription, 0)
	if error == nil {result = event.result; break}
	failure := error.(stardust.Failure)
	if failure.status != .Timeout {return error}
	sync.mutex_lock(&waiter.mutex)
	for waiter.generation == observed {
		remaining := 5*time.Second-time.tick_since(started)
		if remaining <= 0 {break}
		_ = sync.cond_wait_with_timeout(&waiter.changed, &waiter.mutex, remaining)
	}
	timed_out := waiter.generation == observed
	sync.mutex_unlock(&waiter.mutex)
	if timed_out {return error}
	stardust.close(&error)
}
defer stardust.close(&result)
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

run_options

This record supplies options for query and mutation run. Zero selects each default. Mutations use DB_Write_Options, whose fields are a subset.

FieldTypeUnitRangeMeaning
page_sizeu32CountHost type rangeRows per page. 0 selects the default page size. Queries only.
max_costtime.DurationHost duration (100 ns ticks at the ABI)Tick rangeThread CPU duration limit. 0 selects the engine’s dynamic budget.
as_ofbuiltin.i64NoneHost type rangeA positive transaction runs a stored definition as of that transaction.

commit

This record contains the result of mutation run, merge_patch and patch_definition.

FieldTypeUnitRangeAbsentMeaning
statusCommit_StatusNoneHost type range——
transactionbuiltin.i64NoneHost type range—Zero when nothing was written.
factsbuiltin.i64CountHost type range——
committed_attime.TimeUTC instant (100 ns ticks since the Unix epoch at the ABI)Tick rangeThe zero time.TimeRecorded commit time as a UTC instant. The call measures this value. Independent calls can differ.
idsmap[string]builtin.i64NoneHost type range—Maps each #_name of a merge patch to its entity ID number. Wrap an ID as {#link id}, or as the typed Link value where the binding has one, to pass it as an entity reference.

event

This record contains the result of subscription next.

FieldTypeUnitMeaning
sequencebuiltin.i64CountEvent number. Event 1 is the initial result.
supersededbuiltin.i64CountIntermediate computed results skipped by this subscription since its previous event. Zero for its first event. The delivered result replaces them in full. This value counts neither commits nor changed rows.
transactionbuiltin.i64NoneTransaction the result was computed at.
resultDocumentNoneThe full query result. The event owns it and the consumer closes it.