|
| 1 | +# TASK-189 — Fix 64-column limit bug in Zig extension |
| 2 | + |
| 3 | +## Goal |
| 4 | +Fix the Zig extension to support tables with 64+ columns, matching Rust/C oracle behavior. |
| 5 | + |
| 6 | +## Status |
| 7 | +- State: done |
| 8 | +- Priority: HIGH (implementation bug, Rust/C handles 100+ columns) |
| 9 | +- Discovered: Round 68 (TASK-183 wide table test suite) |
| 10 | + |
| 11 | +## Problem |
| 12 | +The Zig extension fails when creating a CRR table with 64 or more columns: |
| 13 | +``` |
| 14 | +Error: failed to create pks table |
| 15 | +``` |
| 16 | + |
| 17 | +The Rust/C oracle handles 100+ columns without issue. |
| 18 | + |
| 19 | +## Reproduction |
| 20 | +```bash |
| 21 | +# Using zig/harness/test-wide-table.sh with column count >= 64 |
| 22 | +ZIG_EXT="zig/zig-out/lib/libcrsqlite.dylib" |
| 23 | +nix run nixpkgs#sqlite -- :memory: -cmd ".load $ZIG_EXT" <<'SQL' |
| 24 | +CREATE TABLE wide ( |
| 25 | + id INTEGER PRIMARY KEY NOT NULL, |
| 26 | + col1 TEXT, col2 TEXT, col3 TEXT, col4 TEXT, col5 TEXT, |
| 27 | + col6 TEXT, col7 TEXT, col8 TEXT, col9 TEXT, col10 TEXT, |
| 28 | + -- ... up to col63 works |
| 29 | + col64 TEXT -- THIS BREAKS |
| 30 | +); |
| 31 | +SELECT crsql_as_crr('wide'); |
| 32 | +-- Error: failed to create pks table |
| 33 | +SQL |
| 34 | +``` |
| 35 | + |
| 36 | +## Root Cause (FOUND) |
| 37 | +The `MAX_COLUMNS` constant was hardcoded to 64 in three files: |
| 38 | +1. `zig/src/as_crr.zig` line 21: `const MAX_COLUMNS = 64;` |
| 39 | +2. `zig/src/schema_alter.zig` line 17: `const MAX_COLUMNS = 64;` |
| 40 | +3. `zig/src/local_writes/after_write.zig` line 45: `columns: [64]ColumnInfo,` |
| 41 | + |
| 42 | +When `getTableInfo()` iterated over PRAGMA table_info results, it would fail with `error.TooManyColumns` if `info.count >= MAX_COLUMNS`. |
| 43 | + |
| 44 | +## Files to Modify |
| 45 | +- `zig/src/as_crr.zig` — pks table creation, column tracking |
| 46 | +- `zig/src/table_info.zig` — column enumeration |
| 47 | +- Possibly `zig/src/merge_insert.zig` — if statement caches have size limits |
| 48 | + |
| 49 | +## Acceptance Criteria |
| 50 | +1. `bash zig/harness/test-wide-table.sh` with 100 columns — all tests pass |
| 51 | +2. No regression in existing tests (`make -C zig test-parity`) |
| 52 | +3. Performance comparable to Rust/C oracle |
| 53 | + |
| 54 | +## Parent Docs / Cross-links |
| 55 | +- Test: `zig/harness/test-wide-table.sh` |
| 56 | +- Discovery task: `.tasks/done/TASK-183-wide-table-performance.md` |
| 57 | +- Gap backlog: `research/zig-cr/92-gap-backlog.md` |
| 58 | + |
| 59 | +## Progress Log |
| 60 | +- 2025-12-23: Created from Round 68 discovery. 63-column limit confirmed (64+ fails). |
| 61 | +- 2025-12-23: Root cause found: MAX_COLUMNS=64 hardcoded in 3 files. |
| 62 | +- 2025-12-23: Fix applied: increased MAX_COLUMNS to 2000 (SQLite's default SQLITE_MAX_COLUMN). |
| 63 | + |
| 64 | +## Completion Notes |
| 65 | +**Fixed in 3 files:** |
| 66 | + |
| 67 | +1. `zig/src/as_crr.zig` (line 21): |
| 68 | + - Changed: `const MAX_COLUMNS = 64;` → `const MAX_COLUMNS = 2000;` |
| 69 | + |
| 70 | +2. `zig/src/schema_alter.zig` (line 17): |
| 71 | + - Changed: `const MAX_COLUMNS = 64;` → `const MAX_COLUMNS = 2000;` |
| 72 | + |
| 73 | +3. `zig/src/local_writes/after_write.zig`: |
| 74 | + - Added: `const MAX_COLUMNS = 2000;` (line 19) |
| 75 | + - Changed line 45: `columns: [64]ColumnInfo,` → `columns: [MAX_COLUMNS]ColumnInfo,` |
| 76 | + - Changed line 53: initializer `** 64` → `** MAX_COLUMNS` |
| 77 | + - Changed line 85: `if (info.count >= 64)` → `if (info.count >= MAX_COLUMNS)` |
| 78 | + |
| 79 | +**Verification:** |
| 80 | +- 64-column table: PASS |
| 81 | +- 100-column table: PASS (insert, clock entries, changes all working) |
| 82 | +- Parity tests: 13+ passed (rows_impacted, compound PK, core functions, filters, rowid-slab, alter, noops, fract, fract-parity) |
| 83 | +- Wide table test suite: 13 PASSED, 0 FAILED |
0 commit comments