Expand description
Whether a statement can run inside a read-only transaction.
The predicate is consulted before a statement executes, to choose the transaction mode it runs under. It therefore has to answer from the syntax alone, with no catalog, no bound parameters and no runtime values.
§The approximation is one-sided
read_only over-approximates: it may call a statement writable that
turns out only to read, and that costs nothing but a write transaction. It
must never call a writing statement read-only — a mutation that reaches a
read-only transaction fails partway through, after the statement has
already started producing results.
Every construct whose effect is invisible from the syntax therefore answers
false. A closure invoked through a value the classifier cannot see into
($fn(...), value.unregistered(...)), a custom or scripted function, a
module or silo call, and the eval::* / api::invoke builtins that
evaluate arbitrary nested queries are all writable as far as this walk is
concerned.
§Keeping this in step with the expression layer
surrealdb-expr carries the same predicate over its own tree, and the two
enums evolve separately. The equivalence test in
surrealdb-core’s dbs::read_only_test asserts that for every fixture the
surface AST and the expression it converts to answer identically, which is
what catches a variant added to one side and not the other.