Commit 5891b79
sync: /save answered 502 because Turso will not parse a bare HAVING (#385)
`/save` failed with 502 every time unless you passed --force. The cause is one
missing clause, and it survived because it is invisible to the test suite.
insertRevision() builds two statements. The --force path sends ifRevision: null
and inserts unconditionally. The ordinary path carries a precondition and
expressed it as a HAVING on an implicit single-group aggregate:
INSERT INTO settings_snapshots (…) SELECT …
FROM settings_snapshots WHERE user_id = ?
HAVING COALESCE(MAX(revision),0) = ?
SQLite treats the whole result as one group and runs that happily. Turso's
parser rejects it outright:
SQL string could not be parsed: near HAVING, "None": syntax error
The route threw, the platform returned 502, and the CLI reported exactly what
it saw. #380 added retries for "the app does not answer", which could never
help: the statement is deterministically unparseable, so every attempt failed
the same way.
The tests could not catch it. They run against `file:` — a different engine
from the deployment — and test/settings-sync.mjs does cover the precondition,
with a stale ifRevision refused as 409 and a current one accepted. It passed
throughout, because on SQLite the statement is valid.
Adding GROUP BY user_id makes it parse on both. It cannot change the answer:
the caller sets ifRevision to null when the account has no current revision, so
there is always at least one row for this user to group.
Verified against the real database rather than only locally — the bare form
fails to parse on Turso, the grouped form parses and inserts nothing when the
precondition does not hold, which is the conflict the caller reports as 409.
test/sql-portability.test.mjs now fails on any HAVING in src/ with no GROUP BY.
Static rather than behavioural on purpose: the behaviour is correct on the
engine the tests use, so only reading the SQL can catch this. It matches the
uppercase keyword with comments stripped, because "having" is also an English
word and four files that contain no SQL said it in prose.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 3ee4755 commit 5891b79
2 files changed
Lines changed: 89 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
128 | 140 | | |
129 | 141 | | |
130 | 142 | | |
| 143 | + | |
131 | 144 | | |
132 | 145 | | |
133 | 146 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
0 commit comments