@@ -48,15 +48,64 @@ LQP clients send `Transaction`s that the engine executes.
4848
4949 Write := Define(fragment::Fragment)
5050 | Undefine(fragment_id::FragmentId)
51+ | Context(relations::RelationId[])
52+ | Snapshot(mappings::SnapshotMapping[], prefix::String[])
5153
5254 Read := Demand(relation_id::RelationId)
5355 | Output(name::String, relation_id::RelationId)
54- | Export(config::ExportCSVConfig )
55- | WhatIf(branch::String, epochs ::Epoch[] )
56+ | Export(config::ExportConfig )
57+ | WhatIf(branch::String, epoch ::Epoch)
5658 | Abort(name::String, relation_id::RelationId)
5759
5860Transactions are structured into one or more epochs, which correspond to observable states
5961of the installed program. This allows users to execute a sequence of steps in a single
6062transaction. Within an epoch writes execute before reads. Multiple writes or multiple reads
61- can be performed concurrently and in any order. Of special note are the WhatIf operations,
63+ can be performed concurrently and in any order. Of special note are the ` WhatIf ` operations,
6264which allow executing an epoch in a throwaway clone of the runtime state.
65+
66+ ## Execution Model
67+
68+ Transaction execution proceeds in two passes. First, the _ simulator_ runs the transaction
69+ against a transient copy of the runtime state to validate it and minimize it (e.g. dropping
70+ writes whose effects are clobbered by later writes). Then the _ driver_ executes the
71+ validated, minimized transaction against the actual runtime. If the simulator detects invalid
72+ state at any point, the transaction is aborted and errors are returned.
73+
74+ ## Write Operations
75+
76+ ` Define ` installs a fragment and its declarations into the execution graph. ` Undefine `
77+ removes a fragment. ` Context ` declares which relations should be jointly optimized — more
78+ context gives the optimizer more reuse opportunities but increases planning time. ` Snapshot `
79+ materializes derived relations into durable EDB (base) relations, associating new relation
80+ values with stable identities over time.
81+
82+ ## Read Operations
83+
84+ ` Demand ` triggers computation of a relation without returning its contents — useful for
85+ warming caches. ` Output ` computes and returns a relation's contents under a human-readable
86+ name. ` Export ` writes data to external storage (CSV or Iceberg). ` WhatIf ` runs a speculative
87+ epoch on a transient fork; writes don't persist, reads observe the modified state. ` Abort `
88+ enforces integrity constraints: the transaction fails if the referenced relation is non-empty.
89+
90+ ## Types
91+
92+ All types are primitive and aligned with the Apache Iceberg type system. The engine uses
93+ type information for equality, ordering, promotion, and algebraic properties of operations.
94+ Overloading must be handled by higher-level compilers. See the ` Type ` message in
95+ ` logic.proto ` for the full list.
96+
97+ ## External Data
98+
99+ ` Data ` declarations describe external sources (CSV, Iceberg, BeTree) without eagerly
100+ ingesting them — data is loaded lazily when first demanded. ` EDB ` declares durable
101+ engine-managed base relations (the result of ` Snapshot ` operations). ` CSVData ` and
102+ ` IcebergData ` describe how to read from those respective formats, with column-to-relation
103+ mappings via ` GNFColumn ` .
104+
105+ ## Protobuf Specification
106+
107+ The proto files in ` ../proto/relationalai/lqp/v1/ ` are the authoritative specification:
108+
109+ - ` logic.proto ` — Declarations, formulas, types, values, and external data sources
110+ - ` fragments.proto ` — Content-addressable compilation units and debug info
111+ - ` transactions.proto ` — Transaction structure, write/read operations, and export config
0 commit comments