Skip to content

Commit 81aeb63

Browse files
committed
docs: align documentation with current implementation
Update docs across all major sections to match implemented behavior: - Graph: require IN '<collection>' clause on GRAPH INSERT/DELETE EDGE; document that omitting IN is a parse error - SQL: document INSERT ... ON CONFLICT (DO NOTHING / DO UPDATE SET) with EXCLUDED semantics; clarify that UPSERT is equivalent to ON CONFLICT DO UPDATE over all columns; note trigger op-tag derivation from storage prior-bytes, not surface SQL verb - DDL: document two-phase DROP COLLECTION lifecycle — tombstone, UNDROP within retention window, PURGE for immediate hard-delete; add retention knobs and _system.dropped_collections / l2_cleanup_queue inspection queries; note cascade to materialized views and change-stream consumer groups - CSR index: reflect tenant partitioning via ShardedCsrIndex, structural tenant isolation in B-Tree keys, LocalNodeId partition-tag boundary enforcement, and label width change (u16 → u32) - Columnar: add PK point-get and ORDER BY examples; document that plain INSERT raises unique_violation on PK conflict - KV: add UPSERT, ON CONFLICT DO NOTHING, and ON CONFLICT DO UPDATE examples alongside existing INSERT - WAL: document tombstone GC during checkpoint and crash-safe replay - Backup/recovery: note catalog reconstruction and tombstone-set embedding in backup envelopes - Change streams: clarify DROP stream teardown and name-reuse semantics - Error codes: expand CONSTRAINT_VIOLATION description with SQLSTATE and ON CONFLICT alternatives - fusion-rrf, graph-queries: add required VECTOR_FIELD clause to GraphRAG VECTOR_SEARCH examples
1 parent 2164cee commit 81aeb63

15 files changed

Lines changed: 98 additions & 19 deletions

File tree

docs/administration/backup-recovery.rdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ BACKUP TENANT acme TO '/backups/acme-2026-04.bak';
1313

1414
Backups cover all 7 engines: documents, indexes, vectors, graph edges, KV tables, timeseries, and CRDT state. Encrypted with AES-256-GCM using the tenant WAL key.
1515

16+
The backup envelope embeds catalog rows and the source tombstone set alongside segment data, so a restored snapshot reconstructs the catalog deterministically and refuses to resurrect collections tombstoned before the backup was taken. Each `StoredCollection` row carries a `size_bytes_estimate` field surfaced through `_system.dropped_collections` for sizing the L2 cleanup queue before `PURGE`.
17+
1618
## Validate
1719

1820
```sql

docs/architecture/wal.rdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ The WAL ensures durability. Every write is persisted to the WAL before being ack
2828

2929
**Segmented** — The WAL rolls over to a new segment file automatically. Old segments are eligible for cleanup once all records have been flushed to L1 segments.
3030

31+
**Tombstone GC** — Each checkpoint garbage-collects WAL rows for collections that have been hard-deleted (tombstoned), so tombstone records do not accumulate across restarts. On replay, the startup path merges persisted WAL tombstones with tombstones extracted from the WAL itself — a crash mid-purge cannot resurrect a dropped collection.
32+
3133
**Encryption** — Optional AES-256-GCM encryption at the page level. Key management is external.
3234

3335
## Crash Recovery

docs/data-modeling/btree-index.rdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ CREATE UNIQUE INDEX ON users FIELDS email;
2929

3030
## Graph Edge Storage
3131

32-
Graph edges are persisted in redb B-Trees with forward and reverse indexes. The key format (`src_id\x00label\x00dst_id`) enables efficient prefix scans for outbound traversal.
32+
Graph edges are persisted in redb B-Trees with forward and reverse indexes, keyed by `(tenant_id: u32, "src\x00label\x00dst")` tuples. Tenant isolation is a first-class key component, not a lexical prefix; the composite portion enables prefix scans for outbound traversal within a tenant.

docs/data-modeling/collections.rdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ CREATE SEARCH INDEX ON products FIELDS title, description ANALYZER 'english';
6767
CREATE SPATIAL INDEX ON products FIELDS location;
6868

6969
-- Add graph edges for relationships
70-
GRAPH INSERT EDGE FROM 'products:p1' TO 'products:p2' TYPE 'similar';
70+
GRAPH INSERT EDGE IN 'products' FROM 'products:p1' TO 'products:p2' TYPE 'similar';
7171
```
7272

7373
## Converting Between Engines

docs/data-modeling/columnar.rdx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,27 @@ CREATE COLLECTION locations TYPE COLUMNAR (
6060
## Queries
6161

6262
```sql
63+
-- Point-get by primary key hits the segment PK index (not a full scan).
64+
SELECT * FROM logs WHERE ts = '2026-04-24T10:00:00Z';
65+
6366
SELECT level, COUNT(*) FROM logs
6467
WHERE ts > now() - INTERVAL '1 hour'
6568
GROUP BY level ORDER BY COUNT(*) DESC;
6669

70+
-- ORDER BY is supported on columnar scans
71+
SELECT ts, host, message FROM logs
72+
WHERE level = 'error'
73+
ORDER BY ts DESC
74+
LIMIT 100;
75+
6776
-- Window functions
6877
SELECT host, message,
6978
ROW_NUMBER() OVER (PARTITION BY host ORDER BY ts DESC) AS rank
7079
FROM logs;
7180
```
7281

82+
Plain `INSERT` on a columnar collection raises `unique_violation` on primary-key conflict; use `UPSERT` or `INSERT ... ON CONFLICT (pk) DO UPDATE SET col = EXCLUDED.col` for overwrite semantics.
83+
7384
## HTAP Bridge
7485

7586
Combine strict (OLTP) with columnar (OLAP):

docs/data-modeling/csr-index.rdx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,26 @@ CSR (Compressed Sparse Row) is the graph engine's core index format. It stores a
1010
## Layout
1111

1212
```
13-
out_offsets: Vec<u32> [num_nodes + 1] — offset into target array per node
14-
out_targets: DenseArray<u32> [num_edges] — destination node IDs (contiguous, mmap-capable)
15-
out_labels: DenseArray<u16> [num_edges] — edge labels (parallel array)
16-
out_weights: Option<DenseArray<f64>> — optional, allocated only when weighted
13+
CsrIndex (per tenant):
14+
out_offsets: Vec<u32> [num_nodes + 1] — offset into target array per node
15+
out_targets: DenseArray<u32> [num_edges] — destination node IDs (contiguous, mmap-capable)
16+
out_labels: DenseArray<u32> [num_edges] — edge labels (parallel array)
17+
out_weights: Option<DenseArray<f64>> — optional, allocated only when weighted
1718

18-
in_offsets / in_targets / in_labels / in_weights — symmetric for inbound
19+
in_offsets / in_targets / in_labels / in_weights — symmetric for inbound
1920
```
2021

22+
## Tenant Partitioning
23+
24+
The in-memory index is `ShardedCsrIndex` — one `CsrIndex` per tenant. Algorithms and traversals receive a single tenant's partition; there is no lexical tenant prefix on node names. Each `CsrIndex` is assigned a unique partition tag at construction, and public APIs that return dense node indices hand out `LocalNodeId { id, partition_tag }`. Using a node id from one partition with another partition's API panics at the boundary.
25+
2126
## Memory Efficiency
2227

23-
At 1 billion edges, CSR uses ~10 GB vs ~60 GB for naive adjacency lists (6x improvement). Node IDs are interned as `u32`, labels as `u16`.
28+
At 1 billion edges, CSR uses ~10 GB vs ~60 GB for naive adjacency lists (6x improvement). Node IDs are interned as `u32`, labels as `u32`.
2429

2530
## Storage
2631

27-
Edges are persisted in a redb B-Tree with forward and reverse indexes. The CSR index is built at query time for bulk operations. Writes go to a mutable buffer and become visible immediately. Compaction merges the buffer into dense CSR arrays when the buffer exceeds 10% of the dense size.
32+
Edges are persisted in a redb B-Tree with forward and reverse indexes, both keyed by `(tenant_id: u32, "src\x00label\x00dst")` tuples. Tenant isolation is structural (first-class key component), not lexical. The CSR index is built at query time for bulk operations. Writes go to a mutable buffer and become visible immediately. Compaction merges the buffer into dense CSR arrays when the buffer exceeds 10% of the dense size.
2833

2934
## Graph Operations
3035

docs/data-modeling/graph.rdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ CREATE COLLECTION people;
2424
INSERT INTO people (id, name) VALUES ('alice', 'Alice');
2525
INSERT INTO people (id, name) VALUES ('bob', 'Bob');
2626

27-
GRAPH INSERT EDGE FROM 'alice' TO 'bob' TYPE 'knows' PROPERTIES { since: 2020, weight: 0.9 };
27+
GRAPH INSERT EDGE IN 'people' FROM 'alice' TO 'bob' TYPE 'knows' PROPERTIES { since: 2020, weight: 0.9 };
28+
-- The IN '<collection>' clause is required — edges live on a named collection.
2829
```
2930

3031
## Traversal
@@ -103,6 +104,7 @@ Combines vector similarity with graph traversal in one query:
103104
```sql
104105
GRAPH RAG FUSION ON entities
105106
QUERY $embedding
107+
VECTOR_FIELD 'embedding'
106108
VECTOR_TOP_K 50
107109
EXPANSION_DEPTH 2
108110
EDGE_LABEL 'related_to'

docs/data-modeling/kv.rdx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,22 @@ Purpose-built hash-indexed store with O(1) point lookups, native TTL, and second
2020
```sql
2121
CREATE COLLECTION sessions TYPE KEY_VALUE (key TEXT PRIMARY KEY);
2222

23-
-- Insert with TTL
23+
-- Insert with TTL; plain INSERT raises unique_violation (23505) on duplicate key.
2424
INSERT INTO sessions { key: 'sess_abc', user_id: 'alice', role: 'admin', ttl: 3600 };
2525

26+
-- Set-or-overwrite (Redis SET semantics)
27+
UPSERT INTO sessions { key: 'sess_abc', user_id: 'alice', role: 'admin', ttl: 3600 };
28+
29+
-- Set-if-absent (Redis SETNX semantics)
30+
INSERT INTO sessions { key: 'sess_abc', user_id: 'alice', role: 'admin', ttl: 3600 }
31+
ON CONFLICT DO NOTHING;
32+
33+
-- Conditional merge: bump counter on conflict, EXCLUDED references the incoming row.
34+
INSERT INTO sessions (key, user_id, role, hits) VALUES ('sess_abc', 'alice', 'admin', 1)
35+
ON CONFLICT (key) DO UPDATE SET
36+
role = EXCLUDED.role,
37+
hits = sessions.hits + 1;
38+
2639
-- Get by key
2740
SELECT * FROM sessions WHERE key = 'sess_abc';
2841

docs/introduction/quickstart.rdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ CREATE COLLECTION social;
8484
INSERT INTO social (id, name) VALUES ('alice', 'Alice');
8585
INSERT INTO social (id, name) VALUES ('bob', 'Bob');
8686

87-
GRAPH INSERT EDGE FROM 'alice' TO 'bob' TYPE 'knows' PROPERTIES { since: 2020 };
87+
GRAPH INSERT EDGE IN 'social' FROM 'alice' TO 'bob' TYPE 'knows' PROPERTIES { since: 2020 };
8888

8989
GRAPH TRAVERSE FROM 'alice' DEPTH 2;
9090

docs/real-time/change-streams.rdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ WITH (URL = 'https://hooks.example.com/orders');
1818
CREATE CHANGE STREAM user_state ON users WITH (COMPACTION = 'key', KEY = 'id');
1919

2020
DROP CHANGE STREAM order_events;
21+
-- Drop atomically tears down the stream's consumer groups and persisted offset
22+
-- rows. Recreating a stream with the same name starts from the head; it does
23+
-- not resume at stale offsets.
2124
SHOW CHANGE STREAMS;
2225
```
2326

0 commit comments

Comments
 (0)