Skip to content

Commit 330a4e5

Browse files
committed
Tolerant group by window function (returning original logical plan)
Signed-off-by: Yuanchun Shen <yuanchu@amazon.com>
1 parent d19ba53 commit 330a4e5

1 file changed

Lines changed: 48 additions & 5 deletions

File tree

core/src/main/java/org/opensearch/sql/calcite/validate/ValidationUtils.java

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.opensearch.sql.calcite.validate;
77

88
import java.nio.charset.Charset;
9+
import java.util.List;
910
import lombok.experimental.UtilityClass;
1011
import org.apache.calcite.rel.type.RelDataType;
1112
import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -86,9 +87,11 @@ public static RelDataType createUDTWithAttributes(
8687
/**
8788
* Special handling for nested window functions that fail validation due to a Calcite bug.
8889
*
89-
* <p>This method provides a workaround for a known issue in Calcite v1.41 where nested window
90-
* functions within CASE expressions fail validation incorrectly. Only {@code
91-
* CalcitePPLEventstatsIT#testMultipleEventstatsWithNullBucket} should be caught by this check.
90+
* <p>This method provides a workaround for 2 issues in Calcite v1.41
91+
*
92+
* <p>1. where nested window functions within CASE expressions fail validation incorrectly. Only
93+
* {@code CalcitePPLEventstatsIT#testMultipleEventstatsWithNullBucket} should be caught by this
94+
* case.
9295
*
9396
* <p><b>Calcite Bug (v1.41):</b> The {@code SqlImplementor.Result#containsOver()} method at
9497
* SqlImplementor.java:L2145 only checks {@code SqlBasicCall} nodes for window functions, missing
@@ -109,14 +112,54 @@ public static RelDataType createUDTWithAttributes(
109112
* SUM(CASE WHEN ... THEN (SUM(age) OVER (...)) END) OVER (...)
110113
* </pre>
111114
*
112-
* <p><b>TODO:</b> Remove this workaround when upgrading to a Calcite version that fixes the bug.
115+
* 2. Projections containing OVER as function operands are not moved down to subqueries. This
116+
* should catch test case {@code CalciteExplainIT.noPushDownForAggOnWindow}
117+
*
118+
* <p>The check {@code needNewSubquery} at {@link
119+
* org.apache.calcite.rel.rel2sql.SqlImplementor}#L1930 should return true for the following plan
120+
* as it contains window functions nested inside a function call, which should be in an inner
121+
* query if further aggregation is performed on top of it.
122+
*
123+
* <pre>
124+
* LogicalProject(age_str=[WIDTH_BUCKET(SAFE_CAST($8), 3, -(MAX(SAFE_CAST($8)) OVER (), MIN(SAFE_CAST($8)) OVER ()), MAX(SAFE_CAST($8)) OVER ())])
125+
* CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]])
126+
* </pre>
127+
*
128+
* As a result, it creates a SQL where window functions are in group-by:
129+
*
130+
* <pre>
131+
* GROUP BY WIDTH_BUCKET(...MAX(...) OVER ()...)
132+
* </pre>
133+
*
134+
* Ideally, it should have created a SQL like the following for test case noPushDownForAggOnWindow
135+
*
136+
* <pre>
137+
* SELECT COUNT(*) AS `count()`, `age_str`
138+
* FROM (
139+
* SELECT WIDTH_BUCKET(
140+
* SAFE_CAST(`age` AS STRING),
141+
* 3,
142+
* (MAX(SAFE_CAST(`age` AS STRING)) OVER (...)) - (MIN(SAFE_CAST(`age` AS STRING)) OVER (...)),
143+
* MAX(SAFE_CAST(`age` AS STRING)) OVER (...)
144+
* ) AS `age_str`
145+
* FROM `OpenSearch`.`opensearch-sql_test_index_account`
146+
* ) subquery
147+
* GROUP BY `age_str`
148+
* ORDER BY 2
149+
* </pre>
150+
*
151+
* <p><b>TODO:</b> Remove this workaround when upgrading to a Calcite version that fixes the bugs.
113152
*
114153
* @param e the exception to check
115154
* @return {@code true} if the exception should be tolerated as a known Calcite bug, {@code false}
116155
* otherwise
117156
*/
118157
public static boolean tolerantValidationException(Exception e) {
158+
List<String> acceptableErrorMessages =
159+
List.of(
160+
"Aggregate expressions cannot be nested",
161+
"Windowed aggregate expression is illegal in GROUP BY clause");
119162
return e.getMessage() != null
120-
&& e.getMessage().contains("Aggregate expressions cannot be nested");
163+
&& acceptableErrorMessages.stream().anyMatch(e.getMessage()::contains);
121164
}
122165
}

0 commit comments

Comments
 (0)