This is an automated email from the ASF dual-hosted git repository.
mbudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new efa4d44bb6 [CALCITE-6604] Add support for SqlWindowTableFunction in
RelToSql Converter
efa4d44bb6 is described below
commit efa4d44bb61e80568b18844feb7838f162936dc8
Author: ehds <[email protected]>
AuthorDate: Sun Sep 29 21:55:00 2024 +0800
[CALCITE-6604] Add support for SqlWindowTableFunction in RelToSql Converter
Add WindowTableFunctionScanContext to convert RexCall(SqlWindowFunction) to
SqlNdoe.
First convert SqlWindowFunction to SqlCall without PARAM_DATA.
Finally reconstruct a new SqlCall with PARAM_DATA as the first operand.
---
.../calcite/rel/rel2sql/RelToSqlConverter.java | 25 ++++++++++-
.../apache/calcite/rel/rel2sql/SqlImplementor.java | 48 ++++++++++++++++++++++
.../calcite/rel/rel2sql/RelToSqlConverterTest.java | 21 ++++++++++
3 files changed, 92 insertions(+), 2 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
index 118451e379..f80c358bac 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
@@ -81,6 +81,7 @@ import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlTableRef;
import org.apache.calcite.sql.SqlUpdate;
import org.apache.calcite.sql.SqlUtil;
+import org.apache.calcite.sql.SqlWindowTableFunction;
import org.apache.calcite.sql.fun.SqlInternalOperators;
import org.apache.calcite.sql.fun.SqlMinMaxAggFunction;
import org.apache.calcite.sql.fun.SqlSingleValueAggFunction;
@@ -117,6 +118,8 @@ import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import static com.google.common.base.Preconditions.checkArgument;
+
import static org.apache.calcite.rex.RexLiteral.stringValue;
import static java.util.Objects.requireNonNull;
@@ -1286,13 +1289,31 @@ public class RelToSqlConverter extends SqlImplementor
public Result visit(TableFunctionScan e) {
final List<SqlNode> inputSqlNodes = new ArrayList<>();
+ final List<SqlNode> fieldNodes = new ArrayList<>();
+
+ final int fieldCount = e.getRowType().getFieldCount();
final int inputSize = e.getInputs().size();
+
+ for (int i = 0; i < fieldCount; i++) {
+ fieldNodes.add(new SqlIdentifier(e.getRowType().getFieldNames().get(i),
POS));
+ }
+
for (int i = 0; i < inputSize; i++) {
final Result x = visitInput(e, i);
inputSqlNodes.add(x.asStatement());
}
- final Context context = tableFunctionScanContext(inputSqlNodes);
- SqlNode callNode = context.toSql(null, e.getCall());
+
+ SqlNode callNode = null;
+ if (((RexCall) e.getCall()).getOperator() instanceof
SqlWindowTableFunction) {
+ checkArgument(inputSqlNodes.size() == 1,
+ "Number of input sql nodes for SqlWindowTableFunction must be 1.");
+ final Context context =
windowTableFunctionScanContext(inputSqlNodes.get(0), fieldNodes);
+ callNode = context.toSql(null, e.getCall());
+ } else {
+ final Context context = tableFunctionScanContext(inputSqlNodes);
+ callNode = context.toSql(null, e.getCall());
+ }
+
// Convert to table function call, "TABLE($function_name(xxx))"
SqlNode tableCall =
new SqlBasicCall(SqlStdOperatorTable.COLLECTION_TABLE,
diff --git
a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
index 20242f6e6e..a5f6afeb91 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
@@ -83,6 +83,7 @@ import org.apache.calcite.sql.SqlSetOperator;
import org.apache.calcite.sql.SqlTableRef;
import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.SqlWindow;
+import org.apache.calcite.sql.SqlWindowTableFunction;
import org.apache.calcite.sql.fun.SqlCase;
import org.apache.calcite.sql.fun.SqlCountAggFunction;
import org.apache.calcite.sql.fun.SqlInternalOperators;
@@ -1606,6 +1607,11 @@ public abstract class SqlImplementor {
return new TableFunctionScanContext(dialect, inputSqlNodes);
}
+ public Context windowTableFunctionScanContext(SqlNode inputTableNode,
+ List<SqlNode> inputFieldNodes) {
+ return new WindowTableFunctionScanContext(dialect, inputTableNode,
inputFieldNodes);
+ }
+
/** Context for translating MATCH_RECOGNIZE clause. */
public class MatchRecognizeContext extends AliasContext {
protected MatchRecognizeContext(SqlDialect dialect,
@@ -1719,6 +1725,48 @@ public abstract class SqlImplementor {
}
}
+
+ /**
+ * Context for translating call of a WindowTableFunction from {@link
RexNode} to
+ * {@link SqlNode}.*/
+ class WindowTableFunctionScanContext extends BaseContext {
+ private final SqlNode inputTableNode;
+ private final List<SqlNode> inputFieldNodes;
+
+ WindowTableFunctionScanContext(SqlDialect dialect,
+ SqlNode inputTableNode,
+ List<SqlNode> inputFieldNodes) {
+ super(dialect, inputFieldNodes.size());
+ this.inputFieldNodes = inputFieldNodes;
+ this.inputTableNode = inputTableNode;
+ }
+
+ @Override public SqlNode field(int ordinal) {
+ return inputFieldNodes.get(ordinal);
+ }
+
+ private boolean isWindowTableFunctionRex(RexNode rex) {
+ return (rex instanceof RexCall)
+ && (((RexCall) rex).getOperator() instanceof SqlWindowTableFunction);
+ }
+
+ @Override public SqlNode toSql(@Nullable RexProgram program, RexNode rex) {
+ if (isWindowTableFunctionRex(rex)) {
+ // Convert SqlWindowTableFunction operator without the PARAM_DATA to
sqlNode.
+ SqlNode callNode = super.toSql(null, rex);
+ // Reconstruct the callNode with inputTableNode as the PARAM_DATA.
+ List<SqlNode> operandList = new ArrayList<>();
+ operandList.add(inputTableNode);
+ operandList.addAll(((SqlBasicCall) callNode).getOperandList());
+ callNode =
+ new SqlBasicCall(((SqlBasicCall) callNode).getOperator(),
+ operandList, callNode.getParserPosition());
+ return callNode;
+ }
+ return super.toSql(program, rex);
+ };
+ }
+
/** Result of implementing a node. */
public class Result {
final SqlNode node;
diff --git
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 85a39de8fd..0a0fc7cd35 100644
---
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -8248,6 +8248,27 @@ class RelToSqlConverterTest {
sql(query).ok(expected);
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6604">[CALCITE-6604]
+ * Add support for SqlWindowTableFunction in RelToSql Converter </a>. */
+ @Test void testWindowTableFunctionScan() {
+ final String query = "SELECT *\n"
+ + "FROM TABLE(TUMBLE(TABLE \"employee\",
DESCRIPTOR(\"hire_date\"), INTERVAL '1' MINUTE))";
+ final String expected = "SELECT *\n"
+ + "FROM TABLE(TUMBLE((SELECT *\n"
+ + "FROM \"foodmart\".\"employee\"), DESCRIPTOR(\"hire_date\"),
INTERVAL '1' MINUTE))";
+ sql(query).ok(expected);
+ }
+
+ @Test void testWindowTableFunctionScanWithSubQuery() {
+ final String query = "SELECT * \n"
+ + "FROM TABLE(TUMBLE((SELECT \"employee_id\", \"hire_date\" FROM
\"employee\"), DESCRIPTOR(\"hire_date\"), INTERVAL '1' MINUTE))";
+ final String expected = "SELECT *\n"
+ + "FROM TABLE(TUMBLE((SELECT \"employee_id\", \"hire_date\"\n"
+ + "FROM \"foodmart\".\"employee\"), DESCRIPTOR(\"hire_date\"),
INTERVAL '1' MINUTE))";
+ sql(query).ok(expected);
+ }
+
/** Test case for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-3593">[CALCITE-3593]
* RelToSqlConverter changes target of ambiguous HAVING clause with a Project