Преглед изворни кода

Merge pull request #1 from database-pizza/docs/composite-pk-and-23505

docs: composite primary key rejection and SQLSTATE 23505
Danilo Fragoso пре 1 дан
родитељ
комит
346a4d2251

+ 3 - 3
src/content/docs/sql-reference/constraints.md

@@ -9,8 +9,8 @@ Constraints in PizzaSQL fall into two camps: the ones that are actually implemen
 
 ### PRIMARY KEY
 
-- A single column can be `PRIMARY KEY`, or a table-level `PRIMARY KEY (col, ...)`.
-- A table-level composite key uses **only the first named column** as the effective primary key; true composite keys are not supported.
+- A single column can be `PRIMARY KEY`. A table-level `PRIMARY KEY (col)` is also accepted.
+- A composite primary key (`PRIMARY KEY (a, b)`) is rejected at `CREATE TABLE` with SQLSTATE `0A000`; it is never silently reduced to the first column.
 - An **`INTEGER PRIMARY KEY`** column becomes an alias for the implicit rowid. Inserting without a value auto-assigns the next rowid; inserting with a value sets the rowid and advances the counter past it.
 - A **non-integer primary key** (e.g. `TEXT PRIMARY KEY`) is a normal column with a separate hidden rowid counter.
 - The primary key drives **duplicate detection** on `INSERT`, and therefore `INSERT OR REPLACE`/`OR IGNORE` and `ON CONFLICT DO NOTHING`/`DO UPDATE` — all of which are keyed on the primary key only.
@@ -36,7 +36,7 @@ Constraints in PizzaSQL fall into two camps: the ones that are actually implemen
 `UNIQUE` is enforced, but through validating scans rather than a durable uniqueness claim:
 
 - `CREATE UNIQUE INDEX` and inline/table-level `UNIQUE` constraints both materialize into a unique index definition.
-- The core write paths (`INSERT`, `UPDATE`, `DELETE`, and their `ON CONFLICT`/`OR` variants) validate non-`NULL` values against the table's unique indexes before persisting, rejecting duplicates with `UNIQUE constraint failed`.
+- The core write paths (`INSERT`, `UPDATE`, `DELETE`, and their `ON CONFLICT`/`OR` variants) validate non-`NULL` values against the table's unique indexes before persisting, rejecting duplicates with `UNIQUE constraint failed`. Over the PostgreSQL wire protocol the rejection is SQLSTATE `23505`, and the message names the violated index.
 - `CREATE UNIQUE INDEX` on a table that already contains duplicate non-`NULL` values is rejected and the index is not registered.
 - `NULL` values are exempt — multiple `NULL`s are allowed, matching SQLite.
 - Composite unique indexes are enforced, and integral numerics are canonicalized so `1` (integer) and `1.0` (real) collide the way SQLite's affinity does.

+ 2 - 2
src/content/docs/sql-reference/statements.md

@@ -79,7 +79,7 @@ DELETE FROM table WHERE condition;
 CREATE TABLE [IF NOT EXISTS] table (
   column TYPE [PRIMARY KEY] [NOT NULL] [DEFAULT expr] [AUTOINCREMENT],
   ...,
-  [PRIMARY KEY (col, ...)],
+  [PRIMARY KEY (col)],
   [UNIQUE (col, ...)],
   [CHECK (expr)],
   [FOREIGN KEY (col) REFERENCES other (col)]
@@ -88,7 +88,7 @@ CREATE TABLE [IF NOT EXISTS] table (
 
 - `IF NOT EXISTS` silently succeeds if the table already exists.
 - `PRIMARY KEY`, `NOT NULL`, and `DEFAULT` have an effect; `AUTOINCREMENT` is accepted but adds no behavior. Inline and table-level `UNIQUE` constraints are materialized into unique indexes and enforced on the core write paths — see [Constraints](/sql-reference/constraints/). `CHECK` and `FOREIGN KEY` are still parsed and discarded.
-- A table-level `PRIMARY KEY (a, b)` uses the first named column as the primary key; composite keys are not truly supported.
+- A table-level composite `PRIMARY KEY (a, b)` is rejected at `CREATE TABLE` (SQLSTATE `0A000`) instead of being reduced to the first column.
 - `DEFAULT expr` is evaluated when the table is created, so it must be a constant expression. Signed numeric literals (`DEFAULT -1`, `DEFAULT +5`, `DEFAULT (-7)`) are accepted.
 - A bare `NULL` column specifier is accepted as a no-op (columns are nullable by default); `NOT NULL` still applies whenever it appears.
 - `AUTOINCREMENT` is accepted but has no extra behaviour over a plain `INTEGER PRIMARY KEY`.