Skip to content

DuckDB: accept digit separators in numeric literals - #2797

Merged
manticore-projects merged 2 commits into
JSQLParser:masterfrom
guizmaii:duckdb-numeric-underscores
Oct 13, 2026
Merged

manticore-projects merged 2 commits into
JSQLParser:masterfrom
guizmaii:duckdb-numeric-underscores

Conversation

@guizmaii

@guizmaii guizmaii commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

For DuckDB, which accepts _ between digits in numeric literals (docs), as does PostgreSQL 16.

MySQL identifiers may start with digits, so 2024_01 is a column or table there. Separators are therefore opt-in:

Input Default (unchanged) withDigitSeparators() / Dialect.POSTGRESQL
1_000 Column 1_000 LongValue 1000
92_000.0 error DoubleValue 92000.0
1e1_0 Column 1e1_0 DoubleValue 1e10
LIMIT 1_000 LIMIT column 1_000 LIMIT 1000
FROM 2024_01 table 2024_01 error
  • New Feature.allowDigitSeparators (default false) with withDigitSeparators(); Dialect.POSTGRESQL enables it.
  • Behaviour change for Dialect.POSTGRESQL only: 2024_01 is now LongValue 202401 instead of a column, as PostgreSQL never allows unquoted digit-led identifiers (PostgreSQL < 16 reads 1_000 as 1 AS _000).
  • S_LONG accepts _ between digits. Under the feature, the lexical action drops the separators from the image, so the ~30 grammar actions that read number tokens (Long.valueOf(token.image), ...) need no change. 1_000 deparses as 1000.
  • Without the feature, the action cuts the token back to what master lexes (the identifier 2024_01, or .5 before _5). The default output is identical to master on the whole DuckDB test suite below.
  • checkGrammarAmbiguity: no conflicts. ./gradlew check: 10,125 tests, 0 failures.
  • DuckDB's own test suite (test/sql, 70,729 statements): default mode identical to master; with the feature, 10 more parse, none less.

`1_000_000`, `92_000.0` and `1e1_0` are numbers in DuckDB and
PostgreSQL 16, but MySQL reads `2024_01` as an identifier. The new
`Feature.allowDigitSeparators`, enabled by the PostgreSQL dialect,
drops the separators from the token image, so every consumer of number
tokens keeps working. Without it, lexing is unchanged.
@guizmaii
guizmaii marked this pull request as ready for review October 13, 2026 08:33
Copilot AI balanced review requested due to automatic review settings October 13, 2026 08:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@manticore-projects
manticore-projects merged commit ac8a4f0 into JSQLParser:master Oct 13, 2026
10 checks passed
@manticore-projects

Copy link
Copy Markdown
Contributor

Good one, thank you!

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.

3 participants