ADR-0024 Phase C: create table with column-list value literals

Migrate `create table <Name> [with pk [<col>:<type>[, ...]]]`
to the walker. Exercises Repeated{separator: Some(Punct(','))}
for the first time — the with-pk column-spec list.

Walker behaviour changes:
- Optional now backtracks on partial-match failure (Incomplete
  or Failed-Mismatch from a Seq mid-shape). Path / per-byte
  state rolls back to before the partial attempt; the inner's
  expected-set propagates as `skipped` so callers see "what
  would have completed it". Matches chumsky's `or_not`
  semantics. ValidationFailed (content errors) does NOT
  backtrack — the user means to fix those.
- Bridge: ValidationFailed errors now classify as
  `at_eof = true`, mirroring the chumsky-side custom-error
  convention. This is what lets `create table Customers`
  classify as IncompleteAtEof rather than DefiniteErrorAt
  (the user can still continue typing `with pk …`).

Grammar:
- src/dsl/grammar/ddl.rs gains CREATE: shape is
  Seq(Word("table"), Ident{NewName,table_name}, Optional(WITH_PK))
  where WITH_PK = Seq(Word("with"), Word("pk"),
  Optional(Repeated{COL_SPEC, separator: Punct(','), min:1})).
  AST builder enforces `with pk needs at least one column`
  with the existing parse.custom.create_table_needs_pk catalog
  wording; `with pk` alone defaults to id:serial.

Tests:
- 6 new walker-specific tests for create_table: with-pk
  default, named typed PK, compound PK, whitespace tolerance
  around `:` and `,`, bare-create-table-errors-with-with-pk-
  hint, case-insensitive keywords.
- Total: 825 passed, 0 failed, 1 ignored (was 819 / 1).
- cargo clippy --all-targets -- -D warnings clean.
This commit is contained in:
claude@clouddev1
2026-05-15 07:12:22 +00:00
parent 7e79ca865a
commit 6bb688251b
5 changed files with 277 additions and 29 deletions
+7 -1
View File
@@ -180,10 +180,16 @@ fn walker_outcome_to_parse_result(
.map(|(k, v)| (*k, v as &dyn std::fmt::Display))
.collect();
let message = crate::friendly::translate(error.message_key, &arg_refs);
// Mirror the chumsky-side custom-error convention
// (parser.rs `into_parse_error`): treat validation
// errors as `at_eof = true` so the input renderer
// classifies them as IncompleteAtEof rather than a
// mid-input definite error. Live overlay is
// suppressed; the on-submit error still fires.
Err(ParseError::Invalid {
message,
position,
at_eof: false,
at_eof: true,
expected: Vec::new(),
})
}