package granary
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=8b18780ea373be48301d9f333925860a2f9110fc0ac28684295118d72b65a67e
sha512=25ca3c9c5e2b528704a542502e0f37dc33ba003f65622d969b8c2b800778585f8ef0cf89b36e6679832e3993e8303aecddfc662742baf7044d6afe4a796b8f11
doc/granary.sql/Granary_sql/Exec/index.html
Module Granary_sql.ExecSource
Execute write operations against the store and catalog.
type txn_mode = | Auto| In_txn of Granary_store.Store.rw Granary_store.Store.txn| In_ro_txn of Granary_store.Store.ro Granary_store.Store.txn
Transaction mode for DML operations. Auto wraps each DML operation in its own RW transaction (autocommit). In_txn tx reuses an externally managed transaction; the caller is responsible for committing or rolling back. In_ro_txn tx (#274) reads every scan through one externally managed RO snapshot so a multi-statement read sees a single point-in-time committed state; read-only — using it on a write path raises.
val execute :
?mode:txn_mode ->
?clock:(unit -> float) option ->
?params:Granary_encoding.Row.value array ->
?before_hook:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
new_row:Granary_encoding.Row.t option ->
old_row:Granary_encoding.Row.t option ->
unit Lwt.t)
option ->
?after_hook:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
new_row:Granary_encoding.Row.t option ->
old_row:Granary_encoding.Row.t option ->
unit Lwt.t)
option ->
?on_replace_delete_before:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
?on_replace_delete:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
?on_upsert_update_before:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
new_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
?on_upsert_update:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
new_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
Granary_store.Store.t ->
Granary_catalog.Catalog.t ->
Plan.op ->
unit Lwt.tExecute a write operation (Plan.op) against the store and catalog. Runs in its own autocommit RW transaction unless ?mode supplies an enclosing one; the optional hooks observe row changes for triggers and REPLACE/UPSERT bookkeeping.
val execute_with_count :
?mode:txn_mode ->
?clock:(unit -> float) option ->
?params:Granary_encoding.Row.value array ->
?before_hook:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
new_row:Granary_encoding.Row.t option ->
old_row:Granary_encoding.Row.t option ->
unit Lwt.t)
option ->
?after_hook:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
new_row:Granary_encoding.Row.t option ->
old_row:Granary_encoding.Row.t option ->
unit Lwt.t)
option ->
?on_replace_delete_before:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
?on_replace_delete:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
?on_upsert_update_before:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
new_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
?on_upsert_update:
(tx:Granary_store.Store.rw Granary_store.Store.txn ->
old_row:Granary_encoding.Row.t ->
new_row:Granary_encoding.Row.t ->
unit Lwt.t)
option ->
Granary_store.Store.t ->
Granary_catalog.Catalog.t ->
Plan.op ->
int Lwt.tLike execute, but returns the rows-affected count. For DDL ops (CREATE TABLE, CREATE INDEX) this is 0; for INSERT it is 1; for UPDATE it is the number of rows whose contents were modified. Op_begin, Op_commit, and Op_rollback are not handled here — they raise Failure if passed; the Db layer intercepts them.
#239: per-query cost/stats signal for an external cost-based cache. rows_examined is the number of rows pulled from a base table/index scan — the true work signal (a query that scans a million rows to return one reads rows_examined = 1_000_000, rows_returned = 1); rows_returned is the result size once the stream is drained; used_index is the plan-time fact that the base access is an index/rowid/FTS seek rather than a full scan.
Mutable counters updated as the stream is consumed: pass a fresh record to query via ?stats, drain the stream, then read the fields. Mirage-pure (no clock/Unix dependency). rows_examined covers seq scans, index/rowid lookups (incl. nested-loop-join right-side probes), the count fast path, both inputs of a hash join, FTS scans (content rows in a plain scan, matched index rows in a MATCH query), and rows read inside scalar/correlated subqueries (#257).
A zeroed query_stats (used_index = false).
type row_change = | Inserted of {rowid : int64;row : Granary_encoding.Row.t;
}| Deleted of {rowid : int64;row : Granary_encoding.Row.t;
}| Updated of {rowid : int64;old_row : Granary_encoding.Row.t;new_row : Granary_encoding.Row.t;
}
#417 Phase 0: one row-level mutation captured by a change-capturing dirty_tables_acc. rowid is the row's int64 rowid; rows are the full Granary_encoding.Row.t as written/removed. Updated carries both the pre-image (old_row) and post-image (new_row).
#240: opaque accumulator for the set of user tables a write statement mutated. Install it around a statement with with_dirty and read the result with dirty_elements. A capturing accumulator (make_change_acc) additionally records the per-row row_change deltas, read with dirty_changes (#417).
A fresh, empty dirty_tables_acc that records mutated table names only.
#417: a fresh accumulator that additionally captures the per-row row_change deltas (read with dirty_changes). Row capture is opt-in: make_dirty_acc callers pay nothing for it.
with_dirty acc f runs f with acc installed as the active write-path mutation sink, so every table whose rows f mutates — directly, or indirectly via FK cascades and triggers — is recorded in acc. Nestable and independent of the query stats context. Schema-changing DDL (ALTER/DROP) is intentionally not recorded, even when it rewrites rows (e.g. ALTER TABLE … DROP COLUMN): DDL invalidation is handled out of band (see Granary_db.Db.dirty_tables).
The accumulator installed by the nearest enclosing with_dirty, if any. Lets a caller (the #427 reactive-view driver) reuse an ambient change-capturing accumulator instead of shadowing it with a fresh one.
The user tables recorded in acc: sorted, deduplicated, with SQLite-reserved sqlite_… objects (sqlite_master / sqlite_sequence) excluded.
#417: the per-row row_change deltas recorded in acc, as (table, changes) pairs sorted by table name, each table's changes in application order. SQLite-reserved sqlite_… objects are excluded, matching dirty_elements. Always [] for a non-capturing accumulator (make_dirty_acc).
#264: quote a SQL identifier with double-quotes when it is not a plain [A-Za-z_][A-Za-z0-9_]* word (embedded quotes doubled); returned verbatim otherwise.
#264: reconstruct a CREATE TABLE statement from catalog metadata (used by both sqlite_master and the logical dump). Emits column types, constraints (NOT NULL, column-level PRIMARY KEY, DEFAULT, CHECK, GENERATED), foreign keys, and the WITHOUT ROWID clause. UNIQUE and composite/table-level PRIMARY KEY constraints are carried by their backing indexes (ddl_of_index), not inline.
#264: reconstruct a CREATE [UNIQUE] INDEX statement from index metadata.
#264: reconstruct a CREATE VIRTUAL TABLE .. USING fts5(..) statement.
val read_fts_content_rows :
Granary_store.Store.t ->
txn_mode ->
Granary_catalog.Catalog.fts_table_meta ->
(int64 * string list) list Lwt.t#330: read an FTS5 table's stored content as (rowid, column_texts) pairs through mode (the dump's shared snapshot / explicit txn), so Db.dump can emit INSERT INTO fts(rowid, ..) statements that round-trip rowids exactly. Rowids are surfaced only here (out-of-band), not via any SQL projection.
#264: render a Granary_encoding.Row.value as a standalone SQL literal that re-reads to the identical value (text quoted, blob as X'..', float as the shortest round-tripping REAL literal, non-finite floats as 1e999/-1e999/NULL). Used to serialize rows as INSERT statements.
val query :
?mode:txn_mode ->
?clock:(unit -> float) option ->
?params:Granary_encoding.Row.value array ->
?stats:query_stats ->
Granary_store.Store.t ->
Granary_catalog.Catalog.t ->
Plan.op ->
Granary_encoding.Row.t Lwt_stream.t Lwt.tExecute read operations; returns a lazy stream of result rows. params are the positional parameter values for ? placeholders. clock supplies the current Unix timestamp for SQL date/time functions invoked with the literal 'now'. mode selects the read's transaction context: Auto reads a fresh RO snapshot of the committed state, whereas In_txn tx reads through tx so the result reflects the transaction's own uncommitted writes (read-your-own-writes, #262) — across scans, index/rowid lookups, the aggregate fast path, indexed joins, FTS scans, and subqueries. stats, when supplied, is populated as the returned stream is consumed (#239); omit it and the read path is entirely unaffected.
val eval_expr :
(unit -> float) option ->
Granary_encoding.Row.value array ->
Granary_encoding.Row.t ->
Plan.expr ->
Granary_encoding.Row.valueEvaluate a Plan.expr against a row. Exposed primarily for testing the rich expression language directly without round-tripping through SQL. Failures (e.g. division by zero, type-mismatched arithmetic) raise Failure.