diff --git a/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java b/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java index fe252e29bc68..cd054ebeb4df 100644 --- a/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java +++ b/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java @@ -46,6 +46,7 @@ import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlSelectKeyword; import org.apache.calcite.sql.SqlSetOption; +import org.apache.calcite.sql.SqlWindow; import org.apache.calcite.sql.fun.SqlBetweenOperator; import org.apache.calcite.sql.fun.SqlCase; import org.apache.calcite.sql.fun.SqlLikeOperator; @@ -803,8 +804,14 @@ private static Expression toExpression(SqlNode node) { if (node instanceof SqlDataTypeSpec) { // This is to handle expression like: CAST(col AS INT) return RequestUtils.getLiteralExpression(((SqlDataTypeSpec) node).getTypeName().getSimple()); - } else { + } else if (node instanceof SqlWindow) { + // Window definitions appear as operands of OVER calls. PinotQuery does not model window frames directly, but + // compiling them as literals keeps parsing/table-name extraction from failing on multi-stage window queries. + return RequestUtils.getLiteralExpression(node.toString()); + } else if (node instanceof SqlBasicCall) { return compileFunctionExpression((SqlBasicCall) node); + } else { + throw new SqlCompilationException("Unsupported sql node - " + node); } } } diff --git a/pinot-common/src/test/java/org/apache/pinot/common/utils/request/RequestUtilsTest.java b/pinot-common/src/test/java/org/apache/pinot/common/utils/request/RequestUtilsTest.java index 6ca5cf96fd62..a9bf016d51ec 100644 --- a/pinot-common/src/test/java/org/apache/pinot/common/utils/request/RequestUtilsTest.java +++ b/pinot-common/src/test/java/org/apache/pinot/common/utils/request/RequestUtilsTest.java @@ -67,7 +67,10 @@ public Object[][] queryProvider() { {"select foo from countries where bar > 1", Set.of("countries")}, {"select 1", null}, {"SET useMultiStageEngine=true; SELECT table1.foo, table2.bar FROM " - + "table1 JOIN table2 ON table1.id = table2.id LIMIT 10;", Set.of("table1", "table2")} + + "table1 JOIN table2 ON table1.id = table2.id LIMIT 10;", Set.of("table1", "table2")}, + {"SET useMultiStageEngine=true; SELECT foo, occurredAt, " + + "LAG(occurredAt) OVER (PARTITION BY foo ORDER BY occurredAt) AS laggedAt FROM events", + Set.of("events")} }; }