Module read

Module read 

Source
Expand description

The read model: a program’s maintained state as relations, and a small SQL over them.

docs/05-tier-lowering.md §5.3 names this as one of the four things the data tier owes:

Read models … one-shot queries and pgwire access for the outside world: psql, BI tools, DBeaver see materialized views as ordinary tables — the single cheapest trust-builder for adopting teams

§What a read model is here, and what it is not

§5.3’s row also says “generated tables in the same Postgres”, and that is not what this builds. A read model is not a second copy of the state written on the append path; it is the collection the fold already holds and the arrangement crate::engine already maintains, projected. Three consequences, and they are the argument for it:

  • A read model costs nothing per event. Nothing is written, nothing is projected, and the sequencer is untouched — which is 26 §26.2’s rule (“who advances it: not the sequencer”) applied to a second kind of reader rather than argued with.
  • It cannot disagree with the page. A durable projection is a second code path, and a second code path over the same events is a thing that can drift. These rows are read from the same arrangement the view renders from, so the recompute oracle already covers them.
  • It is exactly as fresh as the query. A query advances the dataflow to the log’s head and then reads, so a SELECT issued after an ack sees that ack’s event. There is no projection lag because there is no projection.

What that costs is the one-transaction property 67 §67.1 held open: an append and its projection are still not one transaction, because there is still no projection. §88.6 is the row-by-row list.

§Where the tables come from

TableRowsRead from
a collection-valued field of the accumulatorits elementsthe state value
the accumulator’s remaining scalar fieldsonethe state value
a declared signal that does not read the sessionits elements, or onethe maintained node

The third row is the interesting one: a read model is a view that does not depend on who is asking, which is the same cut §5.3 draws for arrangement sharing. A per_session signal is not a table because a SQL client is not a session — it has no Session to be rendered for, and inventing one would answer a question nobody asked.

§What this is not

It is not a query planner. 04 §4.2 keeps the Query sub-language symbolic, and §20.5 holds beck explain query until an engine compiles one; what parse accepts is a hand-written subset over one table at a time, with no joins, no subqueries and no aggregation beyond count(*). It exists so that an outside tool can read what the program holds, which is what §5.3’s row is for.

Structs§

Answer
What a query answered.
Column
Cond
Schema
Every table a program’s read model has.
Select
What a query asks for.
SqlError
Why a query could not be answered. The message reaches the client verbatim.
Table

Enums§

Cardinality
How many rows a table can have, which is a fact about its shape rather than about its data.
CmpOp
Datum
Item
Source
Where a table’s rows are read from.
SqlTy
The four SQL types a Beck scalar maps onto.
Stmt
A statement, which is a select or one of the two things a client says before it asks for anything.

Traits§

Rows
Where a table’s rows come from. Implemented by whoever holds the running program.

Functions§

at_path
Follow a path of field names into a value.
elements
The elements of a collection value, in the order it holds them.
parse
Parse one statement.
quote_ident
A name as it has to be written in this SQL: bare when it can be, quoted when it cannot.
version
What select version() answers.

Type Aliases§

Cell
A value in one column, or SQL NULL.