Skip to content

DuckDB: Add SUMMARIZE query support - #2450

Open
t8y2 wants to merge 4 commits into
apache:mainfrom
t8y2:dev/duckdb-summarize
Open

t8y2 wants to merge 4 commits into
apache:mainfrom
t8y2:dev/duckdb-summarize

Conversation

@t8y2

@t8y2 t8y2 commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Adds DuckDB SUMMARIZE support for named tables and query inputs such as SELECT, FROM, VALUES, parenthesized queries, and CTEs.

The syntax is represented as a query AST node so it can also be used in subqueries, for example SELECT column_name FROM (SUMMARIZE SELECT 42 AS answer).

Reference: https://duckdb.org/docs/stable/guides/meta/summarize.html

@codecov-commenter

codecov-commenter commented Sep 23, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.42857% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.03%. Comparing base (393c2c3) to head (d640273).

Files with missing lines Patch % Lines
src/ast/spans.rs 0.00% 2 Missing ⚠️
src/parser/mod.rs 95.23% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2450      +/-   ##
==========================================
+ Coverage   81.02%   81.03%   +0.01%     
==========================================
  Files          42       42              
  Lines       33436    33471      +35     
  Branches    33436    33471      +35     
==========================================
+ Hits        27090    27123      +33     
- Misses       2789     2792       +3     
+ Partials     3557     3556       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread tests/sqlparser_duckdb.rs
duckdb().verified_stmt("SUMMARIZE VALUES (1.0), (6754950520)");
duckdb().verified_stmt("SUMMARIZE (SELECT 42 AS answer)");
duckdb().verified_stmt("SUMMARIZE WITH users AS (SELECT 1 AS id) SELECT * FROM users");
duckdb().verified_stmt("SELECT column_name FROM (SUMMARIZE SELECT 42 AS answer)");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You should cover SUMMARIZE as a scalar subquery. DuckDB 1.4.4 accepts SELECT (SUMMARIZE users), but this branch fails with Expected: ), found: users.

Suggested change
duckdb().verified_stmt("SELECT column_name FROM (SUMMARIZE SELECT 42 AS answer)");
duckdb().verified_stmt("SELECT column_name FROM (SUMMARIZE SELECT 42 AS answer)");
duckdb().verified_stmt("SELECT (SUMMARIZE users)");

Comment thread src/parser/mod.rs
Comment on lines 20997 to 20998

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You should let peek_sub_query recognise SUMMARIZE. DuckDB 1.4.4 accepts SELECT (SUMMARIZE users), but this branch fails with Expected: ), found: users because the expression parser only treats SELECT and WITH as subquery heads.

Suggested change
self.peek_one_of_keywords(&[Keyword::SELECT, Keyword::WITH])
.is_some()
|| (self.dialect.supports_summarize() && self.peek_keyword(Keyword::SUMMARIZE))

@LucaCappelletti94 LucaCappelletti94 added the waiting on contributor The review needs further refinements by its author label Sep 24, 2026
@t8y2

t8y2 commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both comments have been addressed in ddebcee:

  • peek_sub_query now recognizes SUMMARIZE for the DuckDB dialect.
  • Scalar subquery coverage now includes table and query targets, nested expressions, dialect gating, and the missing-target error path.

The workflows for the latest commit are currently waiting for maintainer approval. Could you please re-review the changes and approve the Actions runs when convenient?

@LucaCappelletti94 LucaCappelletti94 added waiting on reviewer PR needs to be reviewed and removed waiting on contributor The review needs further refinements by its author labels Sep 25, 2026

@LucaCappelletti94 LucaCappelletti94 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since the fuzzer found a bug in this code, please run it on this branch before the next round. fuzz_duckdb_accepts checks DuckDbDialect against DuckDB's own parser and fails when DuckDB accepts a SELECT that the dialect rejects. That is how SUMMARIZE value turned up. fuzz_parse_roundtrip fails when the SQL that Display renders no longer parses.

To start it, from fuzz/ on nightly (see docs/fuzzing.md):

cargo install cargo-fuzz
cd fuzz
cargo +nightly fuzz run fuzz_duckdb_accepts fuzz_seeds -- -max_total_time=600
cargo +nightly fuzz run fuzz_parse_roundtrip fuzz_seeds -- -max_total_time=600

Crashes land in fuzz/artifacts/<target>/ and replay with cargo +nightly fuzz run <target> <crash-file>. Some of them also fail on main, so rewrite each one without SUMMARIZE (for example SUMMARIZE t as SELECT * FROM t). If it still fails, the gap predates this PR. If it only fails with SUMMARIZE, it needs fixing here.

If you find bugs that predate this PR, and most likely you will, if you have time we would certainly appreciate contributions to fix them.

Comment thread src/parser/mod.rs
Comment on lines +15187 to +15192
Keyword::VALUES,
Keyword::VALUE,
Keyword::FROM,
Keyword::TABLE,
])
.is_some()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You should route VALUES to the query branch only when a ( follows, and drop VALUE. DuckDB 1.4.4 reads SUMMARIZE value and SUMMARIZE values as tables named value and values and rejects SUMMARIZE VALUE (1), but this branch fails both table forms with Expected: (, found: EOF. The fuzz_duckdb_accepts oracle reports it.

Suggested change
Keyword::VALUES,
Keyword::VALUE,
Keyword::FROM,
Keyword::TABLE,
])
.is_some()
Keyword::FROM,
Keyword::TABLE,
])
.is_some()
|| (self.peek_keyword(Keyword::VALUES)
&& self.peek_nth_token_ref(1).token == Token::LParen)

Comment thread tests/sqlparser_duckdb.rs
duckdb().verified_stmt("SUMMARIZE 'users'");
duckdb().verified_stmt("SUMMARIZE SELECT * FROM users");
duckdb().verified_stmt("SUMMARIZE FROM users");
duckdb().verified_stmt("SUMMARIZE VALUES (1.0), (6754950520)");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You should cover the table names that collide with row constructors. Both lines fail on the current head and pass with the change above.

Suggested change
duckdb().verified_stmt("SUMMARIZE VALUES (1.0), (6754950520)");
duckdb().verified_stmt("SUMMARIZE VALUES (1.0), (6754950520)");
duckdb().verified_stmt("SUMMARIZE value");
duckdb().verified_stmt("SUMMARIZE values");

@LucaCappelletti94 LucaCappelletti94 added waiting on contributor The review needs further refinements by its author and removed waiting on reviewer PR needs to be reviewed labels Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DuckDB waiting on contributor The review needs further refinements by its author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants