Skip to content

Commit d18fbf5

Browse files
delegate round 46: unpack_columns impl, table compat spec, config spec (TASK-082, TASK-083, TASK-085)
TASK-082: Implement crsql_unpack_columns vtab in Zig - Created zig/src/unpack_columns_vtab.zig (624 lines) - Unpacks binary blobs from crsql_pack_columns() into rows - Read-only INNOCUOUS vtab with hidden package column constraint - All 12 tests pass TASK-083: Spec table compatibility checks for crsql_as_crr - Created zig/harness/test-table-compat.sh (12 tests) - Tests for: no PK, UNIQUE, AUTOINCREMENT, FK, NOT NULL without DEFAULT - 5 pass (valid tables), 7 RED (validation not yet implemented) TASK-085: Spec crsql_config_get/set + merge-equal-values - Created zig/harness/test-config.sh (12 tests) - Tests for config API and merge-equal-values behavior - All 12 RED as expected (functions not implemented)
1 parent abc3c82 commit d18fbf5

13 files changed

+1931
-145
lines changed

.tasks/backlog/TASK-082-impl-unpack-columns-vtab.md

Lines changed: 0 additions & 45 deletions
This file was deleted.

.tasks/backlog/TASK-083-spec-table-compat.md

Lines changed: 0 additions & 48 deletions
This file was deleted.

.tasks/backlog/TASK-084-impl-table-compat.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ high
1414
(unassigned)
1515

1616
## Parent Docs / Cross-links
17-
- Spec task: `.tasks/backlog/TASK-083-spec-table-compat.md`
17+
- Spec task: `.tasks/done/TASK-083-spec-table-compat.md` (completed 2025-12-20)
1818
- Rust reference: `core/rs/core/src/tableinfo.rs`
1919
- Zig table info extraction: `zig/src/as_crr.zig`
2020
- Gap backlog: `research/zig-cr/92-gap-backlog.md`

.tasks/backlog/TASK-085-spec-config.md

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# TASK-082: Implement (RGRTDD) — `crsql_unpack_columns` vtab in Zig
2+
3+
## Status
4+
- [ ] Planned
5+
- [ ] Assigned
6+
- [ ] In Progress
7+
- [ ] Blocked (reason: ...)
8+
- [x] Complete
9+
10+
## Priority
11+
medium
12+
13+
## Assigned To
14+
(unassigned)
15+
16+
## Parent Docs / Cross-links
17+
- Spec task: `.tasks/backlog/TASK-081-spec-unpack-columns-vtab.md`
18+
- Rust reference: `core/rs/core/src/unpack_columns_vtab.rs`
19+
- Zig pack/unpack: `zig/src/codec.zig`, `zig/src/pack_columns.zig`
20+
- Registration point: `zig/src/ffi/init.zig`
21+
- Gap backlog: `research/zig-cr/92-gap-backlog.md`
22+
23+
## Description
24+
Implement `crsql_unpack_columns` module in Zig.
25+
26+
Key behaviors to match:
27+
- It is a virtual table with schema `CREATE TABLE x(cell ANY, package BLOB hidden)`.
28+
- It requires a usable constraint on the hidden `package` column.
29+
- It iterates unpacked columns as rows.
30+
31+
## Files to Modify
32+
- `zig/src/unpack_columns_vtab.zig` (new)
33+
- `zig/src/ffi/init.zig`
34+
- `zig/src/codec.zig` (only if needed)
35+
- `research/zig-cr/92-gap-backlog.md`
36+
37+
## Acceptance Criteria
38+
- [x] `zig/harness/test-unpack-columns-vtab.sh` passes.
39+
- [x] No regression in `make -C zig test-parity`.
40+
41+
## Progress Log
42+
### 2025-12-18
43+
- Task created from Rust↔Zig gap analysis.
44+
45+
### 2025-12-20
46+
- Implemented `crsql_unpack_columns` virtual table in `zig/src/unpack_columns_vtab.zig`
47+
- Registered module in `zig/src/ffi/init.zig`
48+
- All 12 tests in `test-unpack-columns-vtab.sh` pass
49+
- Parity tests pass with no regressions
50+
51+
## Completion Notes
52+
Implementation complete. Created `zig/src/unpack_columns_vtab.zig` (624 lines) with:
53+
- Read-only (INNOCUOUS) eponymous virtual table
54+
- Schema: `CREATE TABLE x(cell ANY, package BLOB hidden)`
55+
- xBestIndex: Requires EQ constraint on `package` column, returns SQLITE_CONSTRAINT otherwise
56+
- xFilter: Decodes packed blob using codec format (same as codec.zig)
57+
- xColumn: Returns appropriate SQLite type for each unpacked value (integer, float, text, blob, null)
58+
- xUpdate is null (read-only), causing INSERT to fail as expected
59+
60+
Test results:
61+
```
62+
crsql_unpack_columns Tests Summary: 12 passed, 0 failed, 0 skipped
63+
All crsql_unpack_columns tests passed!
64+
```
65+
66+
All 12 tests pass:
67+
1. Module exists
68+
2. Unpack single integer (42)
69+
3. Unpack single string ('hello')
70+
4. Unpack single blob (x'DEADBEEF')
71+
5. Unpack multiple values (compound PK simulation)
72+
6. Unpack NULL value
73+
7. Unpack mixed types preserves type info
74+
8. Empty package returns no rows
75+
9. Invalid package returns error
76+
10. Module is INNOCUOUS (INSERT fails)
77+
11. Requires package constraint (SELECT without WHERE fails)
78+
12. Round-trip pack/unpack parity
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# TASK-083: Spec (RGRTDD) — Table compatibility checks for `crsql_as_crr`
2+
3+
## Status
4+
- [ ] Planned
5+
- [ ] Assigned
6+
- [ ] In Progress
7+
- [ ] Blocked (reason: ...)
8+
- [x] Complete
9+
10+
## Priority
11+
high
12+
13+
## Assigned To
14+
(unassigned)
15+
16+
## Parent Docs / Cross-links
17+
- Rust reference gating: `core/rs/core/src/tableinfo.rs` (is_table_compatible)
18+
- Rust CRR creation: `core/rs/core/src/create_crr.rs`
19+
- Zig CRR creation: `zig/src/as_crr.zig`
20+
- Gap backlog: `research/zig-cr/92-gap-backlog.md`
21+
22+
## Description
23+
Define (in tests) what tables are eligible to become CRRs.
24+
25+
This is important for real systems because invalid tables can silently produce incorrect triggers/merge behavior.
26+
27+
This is a **spec/tests-only** task.
28+
29+
## Files to Modify
30+
- `zig/harness/test-table-compat.sh` (new)
31+
- `zig/harness/test-parity.sh` (wire into suite)
32+
- `research/zig-cr/92-gap-backlog.md`
33+
34+
## Acceptance Criteria
35+
- [x] Tests fail on current Zig (it upgrades without checks).
36+
- [x] Tests cover rejections that match Rust behavior:
37+
1. **No primary key**: conversion fails.
38+
2. **Unique index besides PK**: conversion fails.
39+
3. **AUTOINCREMENT present**: conversion fails.
40+
4. **Checked foreign keys**: conversion fails.
41+
5. **NOT NULL without DEFAULT**: conversion fails.
42+
- [x] Tests assert error is visible (non-OK return / error message contains a stable substring).
43+
44+
## Progress Log
45+
### 2025-12-18
46+
- Task created from Rust↔Zig gap analysis.
47+
48+
### 2025-12-20
49+
- Created `zig/harness/test-table-compat.sh` with 12 tests covering:
50+
- Test 1: Table without PRIMARY KEY fails
51+
- Test 2: Table with UNIQUE index (besides PK) fails
52+
- Test 3: Table with AUTOINCREMENT fails
53+
- Test 4: Table with checked foreign keys fails
54+
- Test 5: NOT NULL column without DEFAULT fails
55+
- Test 6: Valid table succeeds (positive case)
56+
- Test 7: Table with NOT NULL + DEFAULT succeeds
57+
- Test 8: Table with compound primary key succeeds
58+
- Test 9: Already a CRR (idempotent - second call succeeds)
59+
- Test 10: Non-existent table fails gracefully
60+
- Test 11: Nullable primary key fails
61+
- Test 12: UNIQUE constraint via separate CREATE UNIQUE INDEX fails
62+
- Wired test into `zig/harness/test-parity.sh`
63+
- Ran test suite: **5 PASSED, 7 FAILED** (RED phase as expected)
64+
65+
## Completion Notes
66+
### Test Results Summary (2025-12-20)
67+
68+
**Tests Created:** 12
69+
70+
**Tests Passing:** 5
71+
- Test 6: Valid table succeeds
72+
- Test 7: Table with NOT NULL + DEFAULT succeeds
73+
- Test 8: Table with compound primary key succeeds
74+
- Test 9: Already a CRR (idempotent)
75+
- Test 10: Non-existent table fails gracefully
76+
77+
**Tests Failing (RED phase - expected):** 7
78+
- Test 1: Table without PRIMARY KEY - Zig accepts (should reject)
79+
- Test 2: Table with UNIQUE index - Zig accepts (should reject)
80+
- Test 3: Table with AUTOINCREMENT - Zig accepts (should reject)
81+
- Test 4: Table with foreign keys - Zig accepts (should reject)
82+
- Test 5: NOT NULL without DEFAULT - Zig accepts (should reject)
83+
- Test 11: Nullable primary key - Zig accepts (should reject)
84+
- Test 12: UNIQUE INDEX via CREATE INDEX - Zig accepts (should reject)
85+
86+
**Conclusion:**
87+
The Zig implementation of `crsql_as_crr` does not currently perform table compatibility validation. Invalid tables are silently accepted. The Rust reference implementation (`is_table_compatible` in `core/rs/core/src/tableinfo.rs`) validates all these cases.
88+
89+
**Next Steps:**
90+
Create TASK-084 to implement `is_table_compatible` checks in the Zig extension.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# TASK-085: Spec (RGRTDD) — `crsql_config_get/set` + merge-equal-values
2+
3+
## Status
4+
- [ ] Planned
5+
- [ ] Assigned
6+
- [ ] In Progress
7+
- [ ] Blocked (reason: ...)
8+
- [x] Complete
9+
10+
## Priority
11+
medium
12+
13+
## Assigned To
14+
(unassigned)
15+
16+
## Parent Docs / Cross-links
17+
- Rust config API: `core/rs/core/src/config.rs`
18+
- Rust merge uses ext-data setting: `core/rs/core/src/changes_vtab_write.rs` (merge semantics)
19+
- Zig merge logic: `zig/src/merge_insert.zig`
20+
- Zig ext data/state: (likely `zig/src/ffi/` + site identity)
21+
- Gap backlog: `research/zig-cr/92-gap-backlog.md`
22+
23+
## Description
24+
Define config API behavior and its effect on merge semantics.
25+
26+
This is a **spec/tests-only** task.
27+
28+
## Files to Modify
29+
- `zig/harness/test-config.sh` (new)
30+
- `zig/harness/test-parity.sh` (wire into suite)
31+
- `research/zig-cr/92-gap-backlog.md`
32+
33+
## Acceptance Criteria
34+
- [x] Tests fail on current Zig (missing functions).
35+
- [x] Tests cover:
36+
1. `SELECT crsql_config_get('merge-equal-values')` returns an integer.
37+
2. `SELECT crsql_config_set('merge-equal-values', 0)` persists and `crsql_config_get` reflects it.
38+
3. Unknown setting names return an error.
39+
4. Merge semantics change is observable with a minimal scenario (must be specified based on Rust behavior; the test must encode the observed contract).
40+
41+
## Progress Log
42+
### 2025-12-18
43+
- Task created from Rust/Zig gap analysis.
44+
45+
### 2025-12-20
46+
- Created `zig/harness/test-config.sh` with 12 tests covering:
47+
- Test 1-2: Function existence (crsql_config_get, crsql_config_set)
48+
- Test 3: Return type is integer
49+
- Test 4-5: Value persistence (set/get round-trip for 0 and 1)
50+
- Test 6-7: Unknown setting names return error
51+
- Test 8: merge-equal-values=1 behavior (higher site_id wins tie-break, advances clock)
52+
- Test 9: merge-equal-values=0 behavior (equal values = no-op, no clock advance)
53+
- Test 10: Config persists across statements in same connection
54+
- Test 11: Default value verification
55+
- Test 12: crsql_config_set returns the set value
56+
- Wired test into `zig/harness/test-parity.sh`
57+
- Verified RED phase: all 12 tests fail with "crsql_config_get/set not implemented"
58+
59+
## Completion Notes
60+
### 2025-12-20
61+
- Spec complete. RED phase confirmed.
62+
- 12 tests created, all failing as expected (functions not implemented in Zig)
63+
- Test output confirms proper RED phase detection and messaging
64+
- Ready for implementation phase (GREEN) in separate task
65+
66+
Test output summary:
67+
```
68+
PASSED: 0
69+
FAILED: 12
70+
SKIPPED: 0
71+
72+
RGRTDD RED PHASE: All tests FAILED as expected
73+
crsql_config_get() and crsql_config_set() are not yet implemented in Zig.
74+
```

0 commit comments

Comments
 (0)