Skip to content

Add ANSI_QUOTES and SQL mode validation#452

Open
JanJakes wants to merge 5 commits into
trunkfrom
ansi-quotes
Open

Add ANSI_QUOTES and SQL mode validation#452
JanJakes wants to merge 5 commits into
trunkfrom
ansi-quotes

Conversation

@JanJakes

@JanJakes JanJakes commented Jul 15, 2026

Copy link
Copy Markdown
Member

Summary

This PR improves SQL mode handling and adds ANSI_QUOTES and ANSII support. This includes:

  • SQL mode storage: SQL modes use MySQL's native bitmap and canonical order.
  • Validation: Named and numeric assignments are validated with MySQL-compatible errors.
  • ANSI_QUOTES: ANSI_QUOTES is supported by the driver, standalone parser, and native lexer.
  • ANSI Composite ANSI SQL mode is expanded into its component modes.
  • Quoted identifiers: Fixed backslash behavior in quoted identifiers.
  • Native builds: Lexer constants are regenerated, and the generator's monorepo path is fixed.

Why

The ANSI_QUOTES SQL mode support keeps reappearing in our recent performance optimization and parser experiments. This PR extracts and completes that functionality.

Additionally, the driver stored arbitrary mode names, accepted invalid assignments, always treated double quotes as string delimiters, did not expand did not expand composite SQL modes, and applied string escaping to quoted identifiers. The standalone parser and native lexer lacked equivalent quoted-identifier handling.

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 Lexer benchmark

Changes to lexer-related files were detected and triggered a benchmark:

Config Base (QPS) This PR (QPS) Speedup
no JIT 73,936 73,693 1.00×
tracing JIT 150,578 156,031 1.04×

Note: Hosted runners are noisy, and absolute numbers vary. Treat the results with caution and verify them locally.

To reproduce locally:

cd packages/mysql-on-sqlite && composer run bench-lexer

@JanJakes JanJakes changed the title Add ANSI_QUOTES SQL mode support Add ANSI_QUOTES and SQL mode validation Jul 15, 2026
@JanJakes
JanJakes force-pushed the ansi-quotes branch 11 times, most recently from b8d6367 to 3f11622 Compare July 17, 2026 07:50
Map supported SQL mode names to their native MySQL bit values and use the bitmap as the driver's internal representation. Serialize active modes by bit position so duplicates collapse and @@sql_mode follows MySQL's canonical order.
JanJakes added 4 commits July 17, 2026 11:05
Validate SQL mode names and numeric masks before changing the session state. Report invalid values with MySQL's SQLSTATE 42000 and error 1231, while retaining MySQL's handling for empty list components and incorrect value types.
When ANSI_QUOTES is active, MySQL treats a double-quoted sequence as a
quoted identifier rather than a string literal. Emulate this in the lexer
by emitting a backtick-quoted identifier token for double-quoted text when
the mode is set, mirroring how NO_BACKSLASH_ESCAPES already alters
tokenization. The driver already forwards its active SQL modes to the lexer,
so no further wiring is needed.

See: https://dev.mysql.com/doc/refman/8.4/en/sql-mode.html#sqlmode_ansi_quotes
MySQL's composite ANSI mode is shorthand for a set of component modes. Expand
it when sql_mode is set and store the resulting list, so that "@@sql_mode" and
individual mode checks reflect the components:

  REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY

REAL_AS_FLOAT and ONLY_FULL_GROUP_BY are stored but not yet respected by the
emulation.

The driver is the source of truth for SQL modes, but the lexer also recognizes
the composite ANSI mode directly so it stays correct when used standalone,
applying the components that affect tokenization: PIPES_AS_CONCAT, IGNORE_SPACE,
and ANSI_QUOTES.

See: https://dev.mysql.com/doc/refman/8.4/en/sql-mode.html#sqlmode_ansi
MySQL does not process backslash escape sequences inside quoted identifiers;
the bounding quote is escaped only by doubling it. The lexer was applying
string-literal backslash escaping to backtick identifiers (and, with the new
ANSI_QUOTES support, to double-quoted identifiers), both when scanning for the
closing quote and when unquoting the value.

As a result, an identifier like `a\nb` resolved to "a<newline>b", and `a\`
(a trailing backslash) failed to tokenize because the backslash was treated as
escaping the closing quote. Restrict backslash escaping to string literals so
identifiers preserve backslashes verbatim.

See: https://dev.mysql.com/doc/refman/8.4/en/identifiers.html
@JanJakes
JanJakes marked this pull request as ready for review July 17, 2026 12:27
@JanJakes
JanJakes requested a review from brandonpayton July 17, 2026 12:28
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