This is an automated email from the ASF dual-hosted git repository.

jhyde pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 77bb696  [CALCITE-4795] In class SqlBasicCall, make the "operands" 
field private (part 2)
77bb696 is described below

commit 77bb696d020bea4467151109ffed4ced53ff0c2d
Author: Julian Hyde <[email protected]>
AuthorDate: Thu Sep 23 00:33:47 2021 -0700

    [CALCITE-4795] In class SqlBasicCall, make the "operands" field private 
(part 2)
    
    This commit is part 2 of 2, after release 1.28, and removes
    APIs marked 'deprecated to be removed before 1.29'.
    
    The 'operands' field is now an immutable list (that may
    contain null values). If a user calls setOperand, a new list
    is created. Therefore operands do not need to be cloned when
    the call is cloned.
    
    The 'expanded' field has been removed, because it is typically
    false. There is a sub-class where isExpanded() returns true.
---
 .../calcite/rel/rel2sql/RelToSqlConverter.java     |  14 +--
 .../calcite/rex/RexSqlStandardConvertletTable.java |  39 +++----
 .../java/org/apache/calcite/sql/SqlBasicCall.java  | 118 ++++++++++++---------
 .../calcite/sql/SqlNullTreatmentOperator.java      |   4 +-
 .../java/org/apache/calcite/sql/SqlOperator.java   |   4 +-
 .../calcite/sql/fun/SqlStdOperatorTable.java       |   3 +-
 .../calcite/sql/validate/SqlValidatorImpl.java     |  11 +-
 .../calcite/sql2rel/StandardConvertletTable.java   |   3 +-
 .../apache/calcite/util/ImmutableNullableList.java |   4 +-
 9 files changed, 105 insertions(+), 95 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 a8173fd..3dec153 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
@@ -1139,13 +1139,13 @@ public class RelToSqlConverter extends SqlImplementor
     final Context context = tableFunctionScanContext(inputSqlNodes);
     SqlNode callNode = context.toSql(null, e.getCall());
     // Convert to table function call, "TABLE($function_name(xxx))"
-    SqlNode tableCall = new SqlBasicCall(
-        SqlStdOperatorTable.COLLECTION_TABLE,
-        new SqlNode[] {callNode},
-        SqlParserPos.ZERO);
-    SqlNode select = new SqlSelect(
-        SqlParserPos.ZERO, null, SqlNodeList.SINGLETON_STAR, tableCall,
-        null, null, null, null, null, null, null, SqlNodeList.EMPTY);
+    SqlNode tableCall =
+        new SqlBasicCall(SqlStdOperatorTable.COLLECTION_TABLE,
+            ImmutableList.of(callNode), SqlParserPos.ZERO);
+    SqlNode select =
+        new SqlSelect(SqlParserPos.ZERO, null, SqlNodeList.SINGLETON_STAR,
+            tableCall, null, null, null, null, null, null, null,
+            SqlNodeList.EMPTY);
     return result(select, ImmutableList.of(Clause.SELECT), e, null);
   }
 
diff --git 
a/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java 
b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
index a828867..18b3c9d 100644
--- 
a/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
+++ 
b/core/src/main/java/org/apache/calcite/rex/RexSqlStandardConvertletTable.java
@@ -31,7 +31,6 @@ import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -153,7 +152,8 @@ public class RexSqlStandardConvertletTable
     final SqlOperator op = call.getOperator();
     final List<RexNode> operands = call.getOperands();
 
-    final SqlNode[] exprs = convertExpressionList(converter, operands);
+    final @Nullable List<@Nullable SqlNode> exprs =
+        convertExpressionList(converter, operands);
     if (exprs == null) {
       return null;
     }
@@ -163,17 +163,16 @@ public class RexSqlStandardConvertletTable
         SqlParserPos.ZERO);
   }
 
-  private static SqlNode @Nullable [] convertExpressionList(
+  private static @Nullable List<@Nullable SqlNode> convertExpressionList(
       RexToSqlNodeConverter converter,
       List<RexNode> nodes) {
-    final SqlNode[] exprs = new SqlNode[nodes.size()];
-    for (int i = 0; i < nodes.size(); i++) {
-      RexNode node = nodes.get(i);
-      SqlNode converted = converter.convertNode(node);
+    final List<@Nullable SqlNode> exprs = new ArrayList<>();
+    for (RexNode node : nodes) {
+      @Nullable SqlNode converted = converter.convertNode(node);
       if (converted == null) {
         return null;
       }
-      exprs[i] = converted;
+      exprs.add(converted);
     }
     return exprs;
   }
@@ -198,20 +197,15 @@ public class RexSqlStandardConvertletTable
   private void registerTypeAppendOp(final SqlOperator op) {
     registerOp(
         op, (converter, call) -> {
-          SqlNode[] operands =
+          @Nullable List<@Nullable SqlNode> operandList =
               convertExpressionList(converter, call.operands);
-          if (operands == null) {
+          if (operandList == null) {
             return null;
           }
-          List<SqlNode> operandList =
-              new ArrayList<>(Arrays.asList(operands));
           SqlDataTypeSpec typeSpec =
               SqlTypeUtil.convertTypeToSpec(call.getType());
           operandList.add(typeSpec);
-          return new SqlBasicCall(
-              op,
-              operandList.toArray(new SqlNode[0]),
-              SqlParserPos.ZERO);
+          return new SqlBasicCall(op, operandList, SqlParserPos.ZERO);
         });
   }
 
@@ -225,7 +219,7 @@ public class RexSqlStandardConvertletTable
     registerOp(
         op, (converter, call) -> {
           assert op instanceof SqlCaseOperator;
-          SqlNode[] operands =
+          @Nullable List<@Nullable SqlNode> operands =
               convertExpressionList(converter, call.operands);
           if (operands == null) {
             return null;
@@ -233,13 +227,13 @@ public class RexSqlStandardConvertletTable
           SqlNodeList whenList = new SqlNodeList(SqlParserPos.ZERO);
           SqlNodeList thenList = new SqlNodeList(SqlParserPos.ZERO);
           int i = 0;
-          while (i < operands.length - 1) {
-            whenList.add(operands[i]);
+          while (i < operands.size() - 1) {
+            whenList.add(operands.get(i));
             ++i;
-            thenList.add(operands[i]);
+            thenList.add(operands.get(i));
             ++i;
           }
-          SqlNode elseExpr = operands[i];
+          SqlNode elseExpr = operands.get(i);
           return op.createCall(null, SqlParserPos.ZERO, null, whenList, 
thenList, elseExpr);
         });
   }
@@ -254,7 +248,8 @@ public class RexSqlStandardConvertletTable
     }
 
     @Override public @Nullable SqlNode convertCall(RexToSqlNodeConverter 
converter, RexCall call) {
-      SqlNode[] operands = convertExpressionList(converter, call.operands);
+      @Nullable List<@Nullable SqlNode> operands =
+          convertExpressionList(converter, call.operands);
       if (operands == null) {
         return null;
       }
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlBasicCall.java 
b/core/src/main/java/org/apache/calcite/sql/SqlBasicCall.java
index 246748f..a3bb120 100755
--- a/core/src/main/java/org/apache/calcite/sql/SqlBasicCall.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlBasicCall.java
@@ -21,7 +21,6 @@ import org.apache.calcite.util.ImmutableNullableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -32,63 +31,50 @@ import static 
org.apache.calcite.linq4j.Nullness.castNonNull;
  */
 public class SqlBasicCall extends SqlCall {
   private SqlOperator operator;
-
-  /** Array of operands.
-   *
-   * @deprecated Use the methods {@link #getOperandList()} and
-   * {@link #setOperand(int, SqlNode)}. To be removed before 1.29.
-   */
-  @Deprecated // to be removed before 1.29
-  public final @Nullable SqlNode[] operands;
-
-  private final List<@Nullable SqlNode> operandList;
+  private List<@Nullable SqlNode> operandList;
   private final @Nullable SqlLiteral functionQuantifier;
-  private final boolean expanded;
 
+  @Deprecated // to be removed before 2.0
   public SqlBasicCall(
       SqlOperator operator,
       @Nullable SqlNode[] operands,
       SqlParserPos pos) {
-    this(operator, operands, pos, null, false);
+    this(operator, ImmutableNullableList.copyOf(operands), pos, null);
   }
 
   /** Creates a SqlBasicCall.
    *
-   * @deprecated Use
-   * {@link #SqlBasicCall(SqlOperator, SqlNode[], SqlParserPos, SqlLiteral)}
-   * followed by {@link #withExpanded(boolean)}. To be removed before 1.29.
-   */
-  @Deprecated // to be removed before 1.29
+   * <p>It is not expanded; call {@link #withExpanded withExpanded(true)}
+   * to expand. */
   public SqlBasicCall(
       SqlOperator operator,
-      @Nullable SqlNode[] operands,
-      SqlParserPos pos,
-      boolean expanded,
-      @Nullable SqlLiteral functionQualifier) {
-    this(operator, operands, pos, functionQualifier, expanded);
+      List<? extends @Nullable SqlNode> operandList,
+      SqlParserPos pos) {
+    this(operator, operandList, pos, null);
   }
 
-  /** Creates an unexpanded SqlBasicCall. */
+  @Deprecated // to be removed before 2.0
   public SqlBasicCall(
       SqlOperator operator,
       @Nullable SqlNode[] operands,
       SqlParserPos pos,
       @Nullable SqlLiteral functionQualifier) {
-    this(operator, operands, pos, functionQualifier, false);
+    this(operator, ImmutableNullableList.copyOf(operands), pos,
+        functionQualifier);
   }
 
-  /** Private constructor. */
-  private SqlBasicCall(
+  /** Creates a SqlBasicCall with an optional function qualifier.
+   *
+   * <p>It is not expanded; call {@link #withExpanded withExpanded(true)}
+   * to expand. */
+  public SqlBasicCall(
       SqlOperator operator,
-      @Nullable SqlNode[] operands,
+      List<? extends @Nullable SqlNode> operandList,
       SqlParserPos pos,
-      @Nullable SqlLiteral functionQualifier,
-      boolean expanded) {
+      @Nullable SqlLiteral functionQualifier) {
     super(pos);
     this.operator = Objects.requireNonNull(operator, "operator");
-    this.operands = operands;
-    this.operandList = Arrays.asList(operands);
-    this.expanded = expanded;
+    this.operandList = ImmutableNullableList.copyOf(operandList);
     this.functionQuantifier = functionQualifier;
   }
 
@@ -96,20 +82,25 @@ public class SqlBasicCall extends SqlCall {
     return operator.getKind();
   }
 
-  @Override public boolean isExpanded() {
-    return expanded;
-  }
-
+  /** Sets whether this call is expanded.
+   *
+   * @see #isExpanded() */
   public SqlCall withExpanded(boolean expanded) {
-    return expanded == this.expanded ? this
-        : new SqlBasicCall(operator, operandList.toArray(new SqlNode[0]), pos,
-            functionQuantifier, expanded);
+    return !expanded
+        ? this
+        : new ExpandedBasicCall(operator, operandList, pos,
+            functionQuantifier);
   }
 
   @Override public void setOperand(int i, @Nullable SqlNode operand) {
-    operandList.set(i, operand);
+    operandList = set(operandList, i, operand);
   }
 
+  /** Sets the operator (or function) that is being called.
+   *
+   * <p>This method is used by the validator to set a more refined version of
+   * the same operator (for instance, a version where overloading has been
+   * resolved); use with care. */
   public void setOperator(SqlOperator operator) {
     this.operator = Objects.requireNonNull(operator, "operator");
   }
@@ -118,19 +109,9 @@ public class SqlBasicCall extends SqlCall {
     return operator;
   }
 
-  /** Returns the array of operands.
-   *
-   * @deprecated Use the methods {@link #getOperandList()} and
-   * {@link #setOperand(int, SqlNode)}. To be removed before 1.29.
-   */
-  @Deprecated // to be removed before 1.29
-  public @Nullable SqlNode[] getOperands() {
-    return operands;
-  }
-
   @SuppressWarnings("nullness")
   @Override public List<SqlNode> getOperandList() {
-    return ImmutableNullableList.copyOf(operandList);
+    return operandList;
   }
 
   @SuppressWarnings("unchecked")
@@ -150,4 +131,37 @@ public class SqlBasicCall extends SqlCall {
     return getOperator().createCall(getFunctionQuantifier(), pos, operandList);
   }
 
+  /** Sets the {@code i}th element of {@code list} to value {@code e}, creating
+   * an immutable copy of the list. */
+  private static <E> List<@Nullable E> set(List<E> list, int i, @Nullable E e) 
{
+    if (i == 0 && list.size() == 1) {
+      // short-cut case where the contents of the previous list can be ignored
+      return ImmutableNullableList.of(e);
+    }
+    //noinspection unchecked
+    @Nullable E[] objects = (E[]) list.toArray();
+    objects[i] = e;
+    return ImmutableNullableList.copyOf(objects);
+  }
+
+  /** Sub-class of {@link org.apache.calcite.sql.SqlBasicCall}
+   * for which {@link #isExpanded()} returns true. */
+  private static class ExpandedBasicCall extends SqlBasicCall {
+    ExpandedBasicCall(SqlOperator operator,
+        List<? extends @Nullable SqlNode> operandList, SqlParserPos pos,
+        @Nullable SqlLiteral functionQualifier) {
+      super(operator, operandList, pos, functionQualifier);
+    }
+
+    @Override public boolean isExpanded() {
+      return true;
+    }
+
+    @Override public SqlCall withExpanded(boolean expanded) {
+      return expanded
+          ? this
+          : new SqlBasicCall(getOperator(), getOperandList(), pos,
+              getFunctionQuantifier());
+    }
+  }
 }
diff --git 
a/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java 
b/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java
index d70046f..590aac2 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java
@@ -21,6 +21,7 @@ import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
+import org.apache.calcite.util.ImmutableNullableList;
 
 import com.google.common.base.Preconditions;
 
@@ -47,7 +48,8 @@ public class SqlNullTreatmentOperator extends 
SqlSpecialOperator {
   @Override public SqlCall createCall(@Nullable SqlLiteral functionQualifier,
       SqlParserPos pos, @Nullable SqlNode... operands) {
     // As super.createCall, but don't union the positions
-    return new SqlBasicCall(this, operands, pos, functionQualifier);
+    return new SqlBasicCall(this, ImmutableNullableList.copyOf(operands), pos,
+        functionQualifier);
   }
 
   @Override public void unparse(SqlWriter writer, SqlCall call, int leftPrec,
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java 
b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
index 4d89a12..3dd7105 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java
@@ -33,6 +33,7 @@ import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorImpl;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
+import org.apache.calcite.util.ImmutableNullableList;
 import org.apache.calcite.util.Litmus;
 import org.apache.calcite.util.Util;
 
@@ -274,7 +275,8 @@ public abstract class SqlOperator {
       SqlParserPos pos,
       @Nullable SqlNode... operands) {
     pos = pos.plusAll(operands);
-    return new SqlBasicCall(this, operands, pos, functionQualifier);
+    return new SqlBasicCall(this, ImmutableNullableList.copyOf(operands), pos,
+        functionQualifier);
   }
 
   /** Not supported. Choose between
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 3385743..342719f 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -2622,8 +2622,7 @@ public class SqlStdOperatorTable extends 
ReflectiveSqlOperatorTable {
 
   /** Creates a copy of a call with a new operator. */
   private static SqlCall copy(SqlCall call, SqlOperator operator) {
-    final List<SqlNode> list = call.getOperandList();
-    return new SqlBasicCall(operator, list.toArray(new SqlNode[0]),
+    return new SqlBasicCall(operator, call.getOperandList(),
         call.getParserPosition());
   }
 
diff --git 
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java 
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 0f607d9..99eb9f9 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -1821,7 +1821,7 @@ public class SqlValidatorImpl implements 
SqlValidatorWithHints {
           // actually a call to a function. Construct a fake
           // call to this function, so we can use the regular
           // operator validation.
-          return new SqlBasicCall(operator, SqlNode.EMPTY_ARRAY,
+          return new SqlBasicCall(operator, ImmutableList.of(),
               id.getParserPosition(), null).withExpanded(true);
         }
       }
@@ -6443,14 +6443,11 @@ public class SqlValidatorImpl implements 
SqlValidatorWithHints {
           && !DynamicRecordType.isDynamicStarColName(Util.last(id.names))) {
         // Convert a column ref into ITEM(*, 'col_name')
         // for a dynamic star field in dynTable's rowType.
-        SqlNode[] inputs = new SqlNode[2];
-        inputs[0] = fqId;
-        inputs[1] = SqlLiteral.createCharString(
-            Util.last(id.names),
-            id.getParserPosition());
         return new SqlBasicCall(
             SqlStdOperatorTable.ITEM,
-            inputs,
+            ImmutableList.of(fqId,
+                SqlLiteral.createCharString(Util.last(id.names),
+                    id.getParserPosition())),
             id.getParserPosition());
       }
       return fqId;
diff --git 
a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java 
b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index 9e0bc9e..f02a986 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -1152,8 +1152,7 @@ public class StandardConvertletTable extends 
ReflectiveConvertletTable {
 
   private RexNode toRex(SqlRexContext cx, SqlBasicCall call, SqlFunction f) {
     final SqlCall call2 =
-        new SqlBasicCall(f, call.getOperandList().toArray(new SqlNode[0]),
-            call.getParserPosition());
+        new SqlBasicCall(f, call.getOperandList(), call.getParserPosition());
     final SqlRexConvertlet convertlet = requireNonNull(get(call2));
     return convertlet.convertCall(cx, call2);
   }
diff --git 
a/core/src/main/java/org/apache/calcite/util/ImmutableNullableList.java 
b/core/src/main/java/org/apache/calcite/util/ImmutableNullableList.java
index 45fa177..2d88c11 100644
--- a/core/src/main/java/org/apache/calcite/util/ImmutableNullableList.java
+++ b/core/src/main/java/org/apache/calcite/util/ImmutableNullableList.java
@@ -20,6 +20,8 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 
+import org.checkerframework.checker.nullness.qual.Nullable;
+
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -120,7 +122,7 @@ public class ImmutableNullableList<E> extends 
AbstractList<E> {
   }
 
   /** Creates an immutable list of 1 element. */
-  public static <E> List<E> of(E e1) {
+  public static <E> List<E> of(@Nullable E e1) {
     //noinspection unchecked
     return e1 == null ? (List<E>) SINGLETON_NULL : ImmutableList.of(e1);
   }

Reply via email to