Skip to content

docs: specify where semantic checks belong (Syntax vs Semantics) - #25540

Draft
alamb wants to merge 1 commit into
apache:mainfrom
alamb:alamb/syntax-vs-semantics-docs
Draft

alamb wants to merge 1 commit into
apache:mainfrom
alamb:alamb/syntax-vs-semantics-docs

Conversation

@alamb

@alamb alamb commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

When reviewing PRs we regularly ask contributors to move a check out of the SQL
parser or the SQL planner, because:

  1. The parser checks syntax, not meaning (this is
    stated explicitly by sqlparser,
    but nowhere in DataFusion's own docs)
  2. A semantic check made in SqlToRel does not apply to plans built by the
    DataFrame API, Substrait, datafusion-proto, or other query languages built
    on DataFusion

Today the only statement of this in DataFusion is implicit, in the
planning overview,
which describes where each phase happens but never says which kind of check
belongs where. That makes the review feedback look like a matter of taste, and
new checks keep landing in the wrong layer.

What changes are included in this PR?

A new specification page, Syntax vs Semantics
(docs/source/contributor-guide/specification/syntax-vs-semantics.md), which:

  • Defines syntax vs semantic checks, with examples of each
  • States that DFParser checks syntax only, and why (no catalog/schema access,
    the AST is also used for round tripping, and parser checks are skipped by
    every non-SQL frontend), quoting sqlparser's Syntax vs Semantics section
  • States that semantic checks belong on the LogicalPlan, in a node's
    try_new in datafusion-expr, so that every frontend passes through them
  • Includes a table mapping each kind of check to its layer (parser, SqlToRel,
    try_new, AnalyzerRule/invariants, execution)
  • Describes what legitimately stays in SqlToRel (unsupported SQL constructs
    that have no plan representation, and Diagnostic/span context on errors)
  • Recommends .slt tests for the user visible error, so that tests survive a
    check moving between layers
  • Lists real examples from the codebase, both checks in the right place and
    checks in the wrong place

It also cross links the new page from the three places a contributor is likely
to be when they write such a check: the DFParser docs, the crate level
architecture docs in datafusion/core/src/lib.rs, and the "Extending SQL"
library user guide.

Examples in the doc

In the right place (single check, all frontends):

  • Filter::try_new: non boolean predicates and window functions in a predicate
  • check_aggregate_and_window_nesting, from Aggregate::try_new / Window::try_new
  • Union::try_new, the TypeCoercion analyzer rule, assert_valid_semantic_plan

In the wrong place (SQL only), listed as existing violations rather than precedents:

  • Aggregates in WHERE (datafusion/sql/src/select.rs). The same query via the
    DataFrame API builds the plan and fails much later in physical planning:

    // SQL: SELECT * FROM t WHERE sum(a) > 0
    Error during planning: Aggregate functions are not allowed in the WHERE clause. Consider using HAVING instead
    
    // DataFrame: df.filter(sum(col("a")).gt(lit(0)))
    Error during planning: Aggregate function 'sum(CAST(t.a AS Int64))' is not supported in this position. Aggregate functions are supported in the SELECT list, HAVING and ORDER BY of a query with GROUP BY
    

    Contrast with window functions in WHERE, checked in Filter::try_new, where
    SQL and the DataFrame API give the same error.

  • 'IF NOT EXISTS' cannot coexist with 'REPLACE' and Constraints on Partition Columns are not supported, rejected in DFParser although both statements parse

  • Column reference is not allowed in the DEFAULT expression, rejected in SqlToRel

What is the testing strategy for this PR?

Docs only, so there are no new tests. ./ci/scripts/doc_prettier_check.sh,
cargo fmt --all -- --check, and RUSTDOCFLAGS="-D warnings" cargo doc -p datafusion-sql --no-deps (for the new intra doc link) all pass. The error
messages quoted in the new page were produced by running the queries against
this branch rather than written from memory.

Are there any user-facing changes?

No code changes. New contributor documentation, plus rustdoc pointers to it.

Adds a `Syntax vs Semantics` specification that states explicitly what
sqlparser's README states for the parser and what DataFusion's planning
docs only imply: the parser checks syntax, and semantic checks belong on
the LogicalPlan so they apply to every frontend (SQL, DataFrame,
Substrait, custom planners) rather than to SQL alone.

Also cross links the new page from `DFParser`, the crate level
architecture docs, and the "Extending SQL" guide.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation sql SQL Planner core Core DataFusion crate labels Sep 20, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.39%. Comparing base (0e3c398) to head (b5100d9).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main   #25540    +/-   ##
========================================
  Coverage   82.38%   82.39%            
========================================
  Files        1138     1138            
  Lines      434492   434623   +131     
  Branches   434492   434623   +131     
========================================
+ Hits       357975   358097   +122     
+ Misses      54873    54857    -16     
- Partials    21644    21669    +25     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Core DataFusion crate documentation Improvements or additions to documentation sql SQL Planner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants