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

Reply via email to