mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-21 14:36:31 +00:00
fix(server): plan 4 — RULE12 paren-count scanner ignores string literals
The entity generator's RULE12_fixGarbledCheckExpressions CHECK-expression
paren-balance scanner counted every `(`/`)` character regardless of
whether it fell inside a single-quoted SQL string literal. A CHECK
expression like `status IN ('confirmed)', 'tentative')` has a literal `)`
inside its first string value; the scanner would hit depth 0 at that
in-string character and truncate the expression, losing its own real
closing paren. The scanner now tracks single-quote string state (handling
the doubled `''` SQLite escape) and skips parens while inside one.
Latent-bug fix — no shipped entity's CHECK expression has hit this shape
yet (3d's ledger: "nothing affected today").
This commit is contained in:
@@ -939,6 +939,18 @@ export interface CheckExpressionFixup {
|
||||
* `end_date >= start_date` — or balanced-but-never-closing nested ones) is
|
||||
* left byte-identical: this only fires on the specific over-capture shape,
|
||||
* never on a clean expression.
|
||||
*
|
||||
* The walk skips a `(`/`)` that falls inside a single-quoted SQL string
|
||||
* literal (a doubled `''` is SQLite's escape for a literal quote *inside*
|
||||
* the literal, so it does not end the string) — an expression like
|
||||
* `status IN ('confirmed)', 'tentative')` has a literal `)` inside its first
|
||||
* string value that is not a real closing paren; without this tracking the
|
||||
* scanner would hit depth 0 at that spurious character and truncate a
|
||||
* perfectly clean expression (losing its own genuine trailing `)` in the
|
||||
* process, corrupting otherwise-valid SQL), not just leave RULE12-003's kind
|
||||
* of case ambiguous the way a false paren-count fires here (Task 8a's own
|
||||
* carry — "nothing affected today" per 3d's ledger, a latent-bug fix, not an
|
||||
* active one — no shipped entity's CHECK expression has hit this shape yet).
|
||||
*/
|
||||
export function RULE12_fixGarbledCheckExpressions(metadata: EntityMetadata[]): CheckExpressionFixup[] {
|
||||
const fixups: CheckExpressionFixup[] = [];
|
||||
@@ -948,9 +960,25 @@ export function RULE12_fixGarbledCheckExpressions(metadata: EntityMetadata[]): C
|
||||
const expr = check.expression;
|
||||
let depth = 1;
|
||||
let cut = -1;
|
||||
let inString = false;
|
||||
for (let i = 0; i < expr.length; i++) {
|
||||
if (expr[i] === '(') depth++;
|
||||
else if (expr[i] === ')') {
|
||||
const ch = expr[i];
|
||||
if (inString) {
|
||||
if (ch === "'") {
|
||||
if (expr[i + 1] === "'") {
|
||||
i++; // a doubled '' is an escaped quote inside the literal, not its end
|
||||
continue;
|
||||
}
|
||||
inString = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch === "'") {
|
||||
inString = true;
|
||||
continue;
|
||||
}
|
||||
if (ch === '(') depth++;
|
||||
else if (ch === ')') {
|
||||
depth--;
|
||||
if (depth === 0) {
|
||||
cut = i;
|
||||
|
||||
Reference in New Issue
Block a user