writeonce/tests/corpus/run/table-volatile-inprocess/fixture.wo
shoney.arickathil b74e13d21e feat(db): durable:false skips the WAL append and replay
Task 4 of docs/superpowers/plans/2026-08-26-table-residency.md — the first
behavioural change in the iteration.

- db.c: one predicate, `table_is_durable`, gating the three EXISTING mutation
  sites. Kept as a function rather than an inlined condition so
  database/src/CODE-LOGIC.md's "nothing else may mutate storage" claim keeps
  holding — the choke points stayed three
- the ack contract is untouched for durable tables: RAM applied, record
  staged, one commit before the ack, and a failed commit still removes the row
- replay: a log holding records for a class the image now declares volatile is
  a real migration case, not corruption. apply_record returns -2 (distinct
  from -1), wo_wal_replay_ex reports the class id, and main.c names it and
  exits 2. `wo_wal_replay` stays as the NULL wrapper, so all 156 WAL unit
  checks are untouched
- measured, not asserted: 50 inserts wrote 1500 WAL bytes into a durable
  table and ZERO into a volatile one. The file's SIZE proves nothing (it is
  fallocate'd to 1 MiB up front), so the gate measures the non-zero prefix

BUG I INTRODUCED AND CAUGHT: the mismatch message first printed the class name
with %s, but wo_str.data is `char data[]` with NO NUL terminator (obj.h) — a
buffer over-read. Now %.*s with the explicit length, and re-verified under
ASan.

New gate `just residency` (8 checks), because everything above was otherwise
a one-off manual measurement: restart behaviour, the zero-byte write path, the
mismatch refusal (exit 2, names the class, NOT reported as corruption), and
both compile-time refusals. Its own first run failed two checks for a bug in
the script rather than the feature — `woc | grep` under `set -o pipefail`
returns woc's exit 1 even when grep matches, since woc exits 1 whenever it
reports diagnostics. Captures first now, with the reason noted inline.

Also new: corpus run/table-volatile-inprocess pins that a volatile table is a
FULL table in-process — same @unique enforcement, same index probe, same query
surface. Only survival differs, and that is unobservable from inside one
process.

Gates: woc-test 557/0, 18 runtime suites 0 fail, cli_smoke OK, oop-e2e 119/0
(was 118), residency 8/0, employee 8/0, db-actor 8/0, site 21/0, ASan clean on
the new replay path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 08:23:49 +02:00

30 lines
1,011 B
Text

-- databasev2 2: a `durable: false` table is a FULL table for the life of the
-- process — same indexes, same @unique enforcement, same FK restrict, same
-- query surface. Only its survival differs, and that cannot be observed from
-- inside one process, so this fixture pins the in-process half. The restart
-- half is scripts/residency-accept.sh.
@table(name: "sessions", durable: false, index: [who])
class Session {
token: Text @unique
who: Text
}
fn main() -> Int {
insert Session { token: "t1", who: "asha" };
insert Session { token: "t2", who: "asha" };
let n = 0;
for s in from x in Session select x { n = n + 1; }
print("rows ${n}");
-- @unique still bites on a volatile table
let dup = try insert Session { token: "t1", who: "eve" } catch (e) nil;
if dup == nil { print("unique refused"); }
-- the index-backed probe still works
for s in from x in Session where x.who == "asha" order by x.token select x {
print("who ${s.who} token ${s.token}");
}
return 0;
}