Skip to content

feat(expressions): add statement-discriminator contract + Into/Keyword accessors - #63

Merged
sjincho merged 1 commit into
mainfrom
sjcho/expressions/command-keyword-discriminator-contract
Aug 5, 2026
Merged

feat(expressions): add statement-discriminator contract + Into/Keyword accessors#63
sjincho merged 1 commit into
mainfrom
sjcho/expressions/command-keyword-discriminator-contract

Conversation

@sjincho

@sjincho sjincho commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Adds a read-side surface so a consumer can classify a parsed statement without re-normalizing strings or cracking a Command's raw remainder. No change to parse or generate output.

What's added (expressions/statement_discriminators.go)

  • Exported constants for the bounded discriminator vocabularies: IntoOutfile/IntoDumpfile, SetItemTransaction, and the distinguished MySQL Show* labels.
  • Expression.Into() — typed read of the into arg (replaces a hand-written type assertion) — and Expression.Keyword() — the normalized Command leading keyword, stable across both Command builder paths and multi-word tokens (LOCK TABLES).
  • A documented, test-enforced contract that the structured string discriminators (Into.kind, Create/Alter/Drop.kind, SetItem.kind, Show.this) are canonical uppercase, so a consumer compares them directly (no ToUpper). This matches upstream (which upper-cases these itself) — a documented invariant, not a divergence, so no DEVIATIONS.md entry; the accessors are additive Go sugar, peers of the existing TableName()/SchemaName() accessors.

Boundaries worth knowing (the traps)

  • Show.this is canonical only for MySQL SHOW; a Postgres SHOW carries the verbatim config-parameter name (e.g. search_path, timezone) — pinned by a dedicated test so it can't silently start being uppercased.
  • The Create/Alter/Drop object-type vocabulary is deliberately not exported as constants: which objects are structured is verb/dialect-dependent (DROP TRIGGER structures, CREATE TRIGGER is a Command; PG structures CREATE TYPE, MySQL doesn't). A consumer maps the (canonical) keyword itself.
  • The Command node's this/expression stay verbatim by design for round-trip fidelity — Keyword() normalizes on read.

Verification: go test ./... green, gofmt/go vet clean. Reviewed via three-model dual-review; findings (Postgres SHOW over-claim, phantom object constants, a Keyword() docstring over-claim) applied.

Context: first of two slices enabling the proxy-monster statement classifier to drop its defensive ToUpper/remainder-parsing. The follow-up structures the replication + RENAME TABLE/RENAME USER statements.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UpLPXA4aqraDVKB84Gwxi2

…d accessors

Give consumers a typed, normalized read surface for classifying a parsed
statement, without changing parse or generate output.

- Export the bounded discriminator vocabularies as constants: IntoOutfile/
  IntoDumpfile, SetItemTransaction, and the distinguished MySQL Show* labels.
- Add Expression.Into, a typed read of the into arg, replacing a hand-written
  type assertion; and Expression.Keyword, the normalized Command leading
  keyword, stable across both Command builder paths and multi-word command
  tokens, so a consumer never keys on a Command's untokenized remainder.
- Document + test-enforce that the structured string discriminators — Into.kind,
  Create/Alter/Drop.kind, SetItem.kind, Show.this — are canonical uppercase, so
  a consumer compares them directly with no ToUpper. This matches upstream
  (which upper-cases these itself); it is a documented invariant, not a
  divergence, so it carries no DEVIATIONS entry — the Into/Keyword accessors are
  additive Go sugar, peers of the existing TableName/SchemaName accessors.

Two boundaries the contract is explicit about: Show.this is canonical only for
MySQL SHOW (a Postgres SHOW carries the verbatim config-parameter name, e.g.
search_path); and the Create/Alter/Drop object-type vocabulary is deliberately
not exported as constants because which objects are structured is
verb/dialect-dependent (DROP TRIGGER structures, CREATE TRIGGER is a Command).
The Command node's this/expression stay verbatim by design for round-trip
fidelity. Documented in statement_discriminators.go, enforced by
TestStatementDiscriminatorContract.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UpLPXA4aqraDVKB84Gwxi2
@sjincho
sjincho force-pushed the sjcho/expressions/command-keyword-discriminator-contract branch from 2d0a587 to a85c092 Compare August 5, 2026 10:40
@sjincho
sjincho merged commit bb17b5b into main Aug 5, 2026
5 checks passed
@sjincho
sjincho deleted the sjcho/expressions/command-keyword-discriminator-contract branch August 5, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant