Skip to content

[CALCITE-7502] RelToSqlConverter creates invalid sql when converting …#4918

Merged
mihaibudiu merged 1 commit intoapache:mainfrom
ehds:fix-contains-over-missing-case-when
May 5, 2026
Merged

[CALCITE-7502] RelToSqlConverter creates invalid sql when converting …#4918
mihaibudiu merged 1 commit intoapache:mainfrom
ehds:fix-contains-over-missing-case-when

Conversation

@ehds
Copy link
Copy Markdown
Contributor

@ehds ehds commented May 5, 2026

…nested window contains SqlCaseWhen

Jira Link

CALCITE-7502

Changes Proposed

SqlImplementor.Result.containsOver() uses manual recursion to detect WINDOW nodes in a SQL tree, but only handles SqlSelect and SqlCall. Nodes such as SqlCase, SqlNodeList,
  SqlLiteral, and others are silently skipped.

When a SqlCase expression contains a windowed aggregate (e.g., 

CASE WHEN SUM(x) OVER (...)  > 1 THEN 1 ELSE 0 END)

 containsOver() returns false. This causes needNewSubQuery() to
   incorrectly conclude that a new sub-query is not required, leading to incorrectly merged SELECT clauses with overlapping window functions.

SQL:

SELECT 
  SUM (daily_sales) OVER (PARTITION BY product_name) AS sales 
FROM 
  (
    SELECT 
      product_name, 
      CASE WHEN SUM(product_id) OVER (PARTITION BY product_name) > 0 THEN 1 ELSE 0 END AS daily_sales 
    FROM 
      product
  ) subquery;
 

converted to LogicalPlan

LogicalProject(sales=[SUM($1) OVER (PARTITION BY $0)])
  LogicalProject(product_name=[$3], daily_sales=[CASE(>(SUM($1) OVER (PARTITION BY $3), 0), 1, 0)])
    JdbcTableScan(table=[[foodmart, product]]) 

and use RelToSqlConverter creates invalide sql,  it contains a nested window function.

SELECT 
  SUM(
    CASE WHEN (
      SUM(product_id) OVER (
        PARTITION BY product_name RANGE BETWEEN UNBOUNDED PRECEDING 
        AND UNBOUNDED FOLLOWING
      )
    ) > 0 THEN 1 ELSE 0 END
  ) OVER (
    PARTITION BY product_name RANGE BETWEEN UNBOUNDED PRECEDING 
    AND UNBOUNDED FOLLOWING
  ) AS sales 
FROM 
  foodmart.product

  Fix:

  Replace the manual recursion with a SqlBasicVisitor that properly traverses all SqlCall subtypes, including SqlCase.

@ehds ehds force-pushed the fix-contains-over-missing-case-when branch from 5f5326b to cee63d5 Compare May 5, 2026 15:32
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

@mihaibudiu mihaibudiu added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label May 5, 2026
@mihaibudiu
Copy link
Copy Markdown
Contributor

CI failed with a timeout, if it passes, I plan to merge.

@mihaibudiu mihaibudiu merged commit adb4174 into apache:main May 5, 2026
49 of 51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTM-will-merge-soon Overall PR looks OK. Only minor things left.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants