From b5551af278b6339682ecb4fc71d77745ac0c566f Mon Sep 17 00:00:00 2001 From: Sean Silvius Date: Sun, 2 Aug 2026 22:12:07 -0700 Subject: [PATCH 1/2] fix(spec): make S4.1 placeholders and S5 type mapping dialect-neutral S4.1 named `?` as the placeholder syntax; the normative content is the ordering rule, so state that and leave placeholder syntax to the server's dialect with a non-normative note (`?` in SQLite/MySQL, `$1` in PostgreSQL). S5 mapped JSON values onto SQLite type affinities, and the boolean -> INTEGER (1 or 0) row was a conformance defect: a PostgreSQL server following it literally binds an integer into a boolean column and fails. Express the mapping as the server's corresponding types instead, and note SQLite's 1/0 representation as an implementation detail of SQLite-backed servers. Closes #8 Co-Authored-By: Claude Fable 5 --- SPEC.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/SPEC.md b/SPEC.md index e115dab..55cd625 100644 --- a/SPEC.md +++ b/SPEC.md @@ -46,7 +46,9 @@ A request body MUST be a JSON object containing **either** a `sql` field (single ``` - `sql` (REQUIRED, string) — the SQL statement. -- `params` (OPTIONAL, array) — positional parameters, in the order of `?` placeholders in `sql`. Defaults to `[]`. +- `params` (OPTIONAL, array) — positional parameters, in the order of the positional placeholders in `sql`. Defaults to `[]`. + +The placeholder syntax itself is the server's, not this spec's: http-sql does not parse or rewrite `sql`, so the client MUST write placeholders in the syntax its target server accepts. (Non-normative: `?` in SQLite and MySQL, `$1` in PostgreSQL. The examples in this document use `?`.) ### 4.2 Batch @@ -67,15 +69,17 @@ Servers MAY reject batches that exceed a server-defined statement count with HTT ## 5. Parameter types -Positional parameters use JSON values. The mapping to SQL types is: +Positional parameters use JSON values. Each JSON value MUST be bound as the server's corresponding SQL type: + +| JSON value | Bound as | +|--------------------|--------------------------| +| string | the server's text type | +| integer number | the server's integer type | +| floating-point | the server's real type | +| boolean | the server's boolean type | +| null | SQL `NULL` | -| JSON value | SQL type | -|--------------------|-------------------| -| string | TEXT | -| integer number | INTEGER | -| floating-point | REAL | -| boolean | INTEGER (1 or 0) | -| null | NULL | +The type names above are semantic, not literal SQL type names; each server maps them onto its own type system. Where a server's engine lacks one of these types natively, how it represents the value is an implementation detail of that server — for example, SQLite has no boolean type, so SQLite-backed servers store booleans as `1` and `0`. Servers MUST NOT assume any particular engine's type system on the client's behalf. For values that cannot be represented as a JSON primitive (binary blobs, integers outside JS-safe range, dates as strings of a specific format), a **tagged value** is used: From 55fa12406a9484e0225054e10988d7058dfe5861 Mon Sep 17 00:00:00 2001 From: Sean Silvius Date: Sun, 2 Aug 2026 22:26:37 -0700 Subject: [PATCH 2/2] chore: retrigger CI (spec-sanity landed after this branch)