fix(localdb): escape apostrophes in apply/snapshot JSON paths (LocalDb-006)

A column name containing ' was captured fine but ended the JSON-path SQL
literal early on the apply and snapshot paths, dead-lettering every row of the
table on the peer and faulting the snapshot page query for a quoted PK column.
Both paths now share JsonPathSql.For, which doubles ' after the JSON-path
escape. 2-node delta and wiped-peer snapshot tests fail pre-fix.

(scadaproj#46)

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 15:08:04 -05:00
parent c207573595
commit 76e9c355b4
5 changed files with 200 additions and 10 deletions
+14 -3
View File
@@ -10,7 +10,7 @@
| Last reviewed | 2026-11-09 |
| Reviewer | Claude |
| Commit reviewed | `91fb2b4` |
| Open findings | 3 |
| Open findings | 2 |
## Summary
@@ -402,7 +402,7 @@ _Unresolved._
| Severity | Low |
| Priority | P3 |
| Category | Correctness & logic bugs |
| Status | Open |
| Status | Resolved |
| Location | `ZB.MOM.WW.LocalDb/src/ZB.MOM.WW.LocalDb.Replication/Internal/LwwApplier.cs:349` |
**Description**
@@ -432,7 +432,18 @@ test.
**Resolution**
_Unresolved._
Resolved 2026-11-09 (scadaproj#46, LocalDb `0.3.6`, unpublished). Re-verified with a 2-node test: on a table
`q("o'key" TEXT PRIMARY KEY, "it's" TEXT, "say ""hi""" TEXT)` both nodes dead-lettered every peer row with
`SQLite Error 1: 'near "key": syntax error'`, and a wiped peer's snapshot faulted the sender's page query. The
apply and snapshot paths now build their JSON paths through one shared helper, `JsonPathSql.For`: the column's `"`
is backslash-escaped for the JSON path grammar, then every `'` in the path is doubled for the SQL string literal.
`LwwApplier` and `SnapshotStreamer` no longer carry their own copies. Column names are not newly restricted at
registration, so no existing schema is refused; the wire format is unchanged (the `row_json`/`pk_json` keys come from
capture, which already escaped both quote styles).
Tests (`QuotedColumnNameTests`): a 2-node delta round trip (insert both ways, then an update and a delete keyed on
the quoted PK) and a wiped-peer snapshot through a quoted PK column. Both fail pre-fix and pass after. The table also carries a
`"` column, which the old escape already handled.
### LocalDb-007 — README is stale on version, adoption, test count, `Synchronous` values and baseline scope