You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by dm...@apache.org on 2023/03/06 12:29:12 UTC

[calcite] 01/01: [CALCITE-5160] ANY/SOME, ALL operators should support collection expressions

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

dmsysolyatin pushed a commit to branch CALCITE-5160-v3
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit 534fb8a0d4913f15a4ed29bb1d697b660f4297aa
Author: dssysolyatin <dm...@gmail.com>
AuthorDate: Mon Jun 13 18:25:46 2022 +0300

    [CALCITE-5160] ANY/SOME, ALL operators should support collection expressions
---
 .../calcite/adapter/enumerable/RexImpTable.java    | 452 +++++++++----------
 .../org/apache/calcite/runtime/SqlFunctions.java   | 495 +++++++++++++--------
 .../calcite/sql/fun/SqlQuantifyOperator.java       |  59 ++-
 .../calcite/sql/fun/SqlStdOperatorTable.java       | 258 ++++++-----
 .../apache/calcite/sql2rel/SqlToRelConverter.java  | 370 +++++++--------
 .../calcite/sql2rel/StandardConvertletTable.java   |  84 ++--
 .../org/apache/calcite/util/BuiltInMethod.java     |   5 +
 site/_docs/reference.md                            |   8 +-
 .../org/apache/calcite/test/SqlOperatorTest.java   | 381 +++++++++++-----
 9 files changed, 1202 insertions(+), 910 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 3a03c67e68..9ea9b4cf3e 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -29,6 +29,7 @@ import org.apache.calcite.linq4j.tree.ConstantExpression;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.ExpressionType;
 import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.linq4j.tree.FunctionExpression;
 import org.apache.calcite.linq4j.tree.MemberExpression;
 import org.apache.calcite.linq4j.tree.MethodCallExpression;
 import org.apache.calcite.linq4j.tree.NewExpression;
@@ -60,6 +61,7 @@ import org.apache.calcite.sql.SqlTypeConstructorFunction;
 import org.apache.calcite.sql.SqlWindowTableFunction;
 import org.apache.calcite.sql.fun.SqlJsonArrayAggAggFunction;
 import org.apache.calcite.sql.fun.SqlJsonObjectAggAggFunction;
+import org.apache.calcite.sql.fun.SqlQuantifyOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.fun.SqlTrimFunction;
 import org.apache.calcite.sql.type.SqlTypeName;
@@ -186,172 +188,12 @@ import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_MICROS;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_MILLIS;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_SECONDS;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.XML_TRANSFORM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ABS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ACOS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.AND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ANY_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARG_MAX;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARG_MIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ASCII;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ASIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ATAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ATAN2;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.BIT_AND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.BIT_OR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.BIT_XOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CARDINALITY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CAST;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CBRT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CEIL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHARACTER_LENGTH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHAR_LENGTH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CLASSIFIER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COALESCE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COLLECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CONCAT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COUNT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_CATALOG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_DATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_PATH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_ROLE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIME;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIMESTAMP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DATETIME_PLUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DEFAULT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DEGREES;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DENSE_RANK;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DIVIDE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DIVIDE_INTEGER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ELEMENT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EQUALS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EVERY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EXP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EXTRACT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.FIRST_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.FLOOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.FUSION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GROUPING;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GROUPING_ID;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.HOP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.INITCAP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.INTERSECTION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_A_SET;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_EMPTY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_FALSE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_SCALAR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_A_SET;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_EMPTY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_FALSE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_SCALAR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_NULL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_TRUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NULL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_TRUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ITEM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAYAGG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_EXISTS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECTAGG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_QUERY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_TYPE_OPERATOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_VALUE_EXPRESSION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAST;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAST_DAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LAST_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LEAD;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LESS_THAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LIKE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LISTAGG;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOCALTIME;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOCALTIMESTAMP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOG10;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOWER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MAX;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MEMBER_OF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS_DATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MOD;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MODE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTIPLY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_EXCEPT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_EXCEPT_DISTINCT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_INTERSECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_INTERSECT_DISTINCT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_UNION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_UNION_DISTINCT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NEXT_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_EQUALS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_SUBMULTISET_OF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NTH_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NTILE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OCTET_LENGTH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OVERLAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PI;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PLUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POSITION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POWER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RADIANS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RAND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RAND_INTEGER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RANK;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REGR_COUNT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REINTERPRET;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REPLACE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROUND;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROW;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROW_NUMBER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SESSION;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SESSION_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIGN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIMILAR_TO;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SINGLE_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SLICE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SOME;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.STRUCT_ACCESS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBMULTISET_OF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUM0;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SYSTEM_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TAN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TIMESTAMP_ADD;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TIMESTAMP_DIFF;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRIM;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRUNCATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TUMBLE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_MINUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_PLUS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UPPER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.USER;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.*;
 
 import static java.util.Objects.requireNonNull;
 
 /**
  * Contains implementations of Rex operators as Java code.
- *
  * <p>Immutable.
  */
 public class RexImpTable {
@@ -399,8 +241,10 @@ public class RexImpTable {
     private final Map<SqlOperator, Supplier<? extends TableFunctionCallImplementor>>
         tvfImplementorMap = new HashMap<>();
 
-    /** Populates this Builder with implementors for all Calcite built-in and
-     * library operators. */
+    /**
+     * Populates this Builder with implementors for all Calcite built-in and
+     * library operators.
+     */
     Builder populate() {
       defineMethod(THROW_UNLESS, BuiltInMethod.THROW_UNLESS.method, NullPolicy.NONE);
       defineMethod(ROW, BuiltInMethod.ARRAY.method, NullPolicy.ALL);
@@ -503,8 +347,10 @@ public class RexImpTable {
       return populate2();
     }
 
-    /** Second step of population. The {@code populate} method grew too large,
-     * and we factored this out. Feel free to decompose further. */
+    /**
+     * Second step of population. The {@code populate} method grew too large,
+     * and we factored this out. Feel free to decompose further.
+     */
     Builder populate2() {
       // datetime
       map.put(DATETIME_PLUS, new DatetimeArithmeticImplementor());
@@ -513,15 +359,15 @@ public class RexImpTable {
       map.put(FLOOR,
           new FloorImplementor(BuiltInMethod.FLOOR.method.getName(),
               BuiltInMethod.UNIX_TIMESTAMP_FLOOR.method,
-            BuiltInMethod.UNIX_DATE_FLOOR.method,
-            BuiltInMethod.CUSTOM_TIMESTAMP_FLOOR.method,
-            BuiltInMethod.CUSTOM_DATE_FLOOR.method));
+              BuiltInMethod.UNIX_DATE_FLOOR.method,
+              BuiltInMethod.CUSTOM_TIMESTAMP_FLOOR.method,
+              BuiltInMethod.CUSTOM_DATE_FLOOR.method));
       map.put(CEIL,
           new FloorImplementor(BuiltInMethod.CEIL.method.getName(),
               BuiltInMethod.UNIX_TIMESTAMP_CEIL.method,
-            BuiltInMethod.UNIX_DATE_CEIL.method,
-            BuiltInMethod.CUSTOM_TIMESTAMP_CEIL.method,
-            BuiltInMethod.CUSTOM_DATE_CEIL.method));
+              BuiltInMethod.UNIX_DATE_CEIL.method,
+              BuiltInMethod.CUSTOM_TIMESTAMP_CEIL.method,
+              BuiltInMethod.CUSTOM_DATE_CEIL.method));
       map.put(TIMESTAMP_ADD,
           new TimestampAddImplementor("timestampAdd",
               BuiltInMethod.CUSTOM_TIMESTAMP_ADD.method,
@@ -743,6 +589,19 @@ public class RexImpTable {
       map.put(CURRENT_ROLE, systemFunctionImplementor);
       map.put(CURRENT_CATALOG, systemFunctionImplementor);
 
+      defineQuantify(SOME_EQ, EQUALS);
+      defineQuantify(SOME_GT, GREATER_THAN);
+      defineQuantify(SOME_GE, GREATER_THAN_OR_EQUAL);
+      defineQuantify(SOME_LE, LESS_THAN_OR_EQUAL);
+      defineQuantify(SOME_LT, LESS_THAN);
+      defineQuantify(SOME_NE, NOT_EQUALS);
+      defineQuantify(ALL_EQ, EQUALS);
+      defineQuantify(ALL_GT, GREATER_THAN);
+      defineQuantify(ALL_GE, GREATER_THAN_OR_EQUAL);
+      defineQuantify(ALL_LE, LESS_THAN_OR_EQUAL);
+      defineQuantify(ALL_LT, LESS_THAN);
+      defineQuantify(ALL_NE, NOT_EQUALS);
+
       // Current time functions
       map.put(CURRENT_TIME, systemFunctionImplementor);
       map.put(CURRENT_TIMESTAMP, systemFunctionImplementor);
@@ -821,7 +680,7 @@ public class RexImpTable {
         try {
           return constructor.newInstance();
         } catch (InstantiationException | IllegalAccessException
-            | InvocationTargetException e) {
+                 | InvocationTargetException e) {
           throw new IllegalStateException(
               "Error while creating aggregate implementor " + constructor, e);
         }
@@ -850,6 +709,11 @@ public class RexImpTable {
           new BinaryImplementor(nullPolicy, true, expressionType,
               backupMethodName));
     }
+
+    private void defineQuantify(SqlQuantifyOperator operator, SqlBinaryOperator binaryOperator) {
+      map.put(operator,
+          new QuantifyCollectionImplementor(binaryOperator, requireNonNull(map.get(binaryOperator))));
+    }
   }
 
   public static CallImplementor createImplementor(
@@ -1004,26 +868,36 @@ public class RexImpTable {
     return true;
   }
 
-  /** Strategy what an operator should return if one of its
-   * arguments is null. */
+  /**
+   * Strategy what an operator should return if one of its
+   * arguments is null.
+   */
   public enum NullAs {
-    /** The most common policy among the SQL built-in operators. If
-     * one of the arguments is null, returns null. */
+    /**
+     * The most common policy among the SQL built-in operators. If
+     * one of the arguments is null, returns null.
+     */
     NULL,
 
-    /** If one of the arguments is null, the function returns
-     * false. Example: {@code IS NOT NULL}. */
+    /**
+     * If one of the arguments is null, the function returns
+     * false. Example: {@code IS NOT NULL}.
+     */
     FALSE,
 
-    /** If one of the arguments is null, the function returns
-     * true. Example: {@code IS NULL}. */
+    /**
+     * If one of the arguments is null, the function returns
+     * true. Example: {@code IS NULL}.
+     */
     TRUE,
 
-    /** It is not possible for any of the arguments to be null.  If
+    /**
+     * It is not possible for any of the arguments to be null.  If
      * the argument type is nullable, the enclosing code will already
      * have performed a not-null check. This may allow the operator
      * implementor to generate a more efficient implementation, for
-     * example, by avoiding boxing or unboxing. */
+     * example, by avoiding boxing or unboxing.
+     */
     NOT_POSSIBLE,
 
     /** Return false if result is not null, true if result is null. */
@@ -1036,8 +910,10 @@ public class RexImpTable {
       return nullable ? NULL : NOT_POSSIBLE;
     }
 
-    /** Adapts an expression with "normal" result to one that adheres to
-     * this particular policy. */
+    /**
+     * Adapts an expression with "normal" result to one that adheres to
+     * this particular policy.
+     */
     public Expression handle(Expression x) {
       switch (Primitive.flavor(x.getType())) {
       case PRIMITIVE:
@@ -1093,11 +969,12 @@ public class RexImpTable {
     return Expressions.constant(null, type);
   }
 
-  /** Multiplies an expression by a constant and divides by another constant,
+  /**
+   * Multiplies an expression by a constant and divides by another constant,
    * optimizing appropriately.
-   *
    * <p>For example, {@code multiplyDivide(e, 10, 1000)} returns
-   * {@code e / 100}. */
+   * {@code e / 100}.
+   */
   public static Expression multiplyDivide(Expression e, BigDecimal multiplier,
       BigDecimal divider) {
     if (multiplier.equals(BigDecimal.ONE)) {
@@ -1230,8 +1107,10 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for the {@code ARG_MIN} and {@code ARG_MAX} aggregate
-   * functions. */
+  /**
+   * Implementor for the {@code ARG_MIN} and {@code ARG_MAX} aggregate
+   * functions.
+   */
   static class ArgMinMaxImplementor extends StrictAggImplementor {
     @Override protected void implementNotNullReset(AggContext info,
         AggResetContext reset) {
@@ -1332,8 +1211,10 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for the {@code COLLECT} and {@code ARRAY_AGG}
-   * aggregate functions. */
+  /**
+   * Implementor for the {@code COLLECT} and {@code ARRAY_AGG}
+   * aggregate functions.
+   */
   static class CollectImplementor extends StrictAggImplementor {
     @Override protected void implementNotNullReset(AggContext info,
         AggResetContext reset) {
@@ -1491,8 +1372,10 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for the {@code FUSION} and {@code ARRAY_CONCAT_AGG}
-   * aggregate functions. */
+  /**
+   * Implementor for the {@code FUSION} and {@code ARRAY_CONCAT_AGG}
+   * aggregate functions.
+   */
   static class FusionImplementor extends StrictAggImplementor {
     @Override protected void implementNotNullReset(AggContext info,
         AggResetContext reset) {
@@ -1698,6 +1581,7 @@ public class RexImpTable {
           int curentPosition; // position in for-win-agg-loop
           int startIndex;     // index of start of window
           Comparable @Nullable [] rows;  // accessed via WinAggAddContext.compareRows
+
           @SuppressWarnings("nullness")
           void sample() {
             if (curentPosition > startIndex) {
@@ -1755,8 +1639,10 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for the {@code FIRST_VALUE} and {@code LAST_VALUE}
-   * windowed aggregate functions. */
+  /**
+   * Implementor for the {@code FIRST_VALUE} and {@code LAST_VALUE}
+   * windowed aggregate functions.
+   */
   static class FirstLastValueImplementor implements WinAggImplementor {
     private final SeekType seekType;
 
@@ -1786,7 +1672,7 @@ public class RexImpTable {
 
       return Expressions.condition(winResult.hasRows(),
           winResult.rowTranslator(
-              winResult.computeIndex(Expressions.constant(0), seekType))
+                  winResult.computeIndex(Expressions.constant(0), seekType))
               .translate(winResult.rexArguments().get(0), info.returnType()),
           getDefaultValue(info.returnType()));
     }
@@ -1806,8 +1692,10 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for the {@code NTH_VALUE}
-   * windowed aggregate function. */
+  /**
+   * Implementor for the {@code NTH_VALUE}
+   * windowed aggregate function.
+   */
   static class NthValueImplementor implements WinAggImplementor {
     @Override public List<Type> getStateType(AggContext info) {
       return Collections.emptyList();
@@ -1864,8 +1752,10 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for the {@code LEAD} and {@code LAG} windowed
-   * aggregate functions. */
+  /**
+   * Implementor for the {@code LEAD} and {@code LAG} windowed
+   * aggregate functions.
+   */
   static class LeadLagImplementor implements WinAggImplementor {
     private final boolean isLead;
 
@@ -2118,18 +2008,20 @@ public class RexImpTable {
           BuiltInMethod.TRIM.method,
           Expressions.constant(
               flag == SqlTrimFunction.Flag.BOTH
-              || flag == SqlTrimFunction.Flag.LEADING),
+                  || flag == SqlTrimFunction.Flag.LEADING),
           Expressions.constant(
               flag == SqlTrimFunction.Flag.BOTH
-              || flag == SqlTrimFunction.Flag.TRAILING),
+                  || flag == SqlTrimFunction.Flag.TRAILING),
           argValueList.get(1),
           argValueList.get(2),
           Expressions.constant(strict));
     }
   }
 
-  /** Implementor for the {@code MONTHNAME} and {@code DAYNAME} functions.
-   * Each takes a {@link java.util.Locale} argument. */
+  /**
+   * Implementor for the {@code MONTHNAME} and {@code DAYNAME} functions.
+   * Each takes a {@link java.util.Locale} argument.
+   */
   private static class PeriodNameImplementor extends MethodNameImplementor {
     private final BuiltInMethod timestampMethod;
     private final BuiltInMethod dateMethod;
@@ -2265,7 +2157,7 @@ public class RexImpTable {
         }
         final TimeUnitRange timeUnitRange =
             (TimeUnitRange) requireNonNull(translator.getLiteralValue(operand1),
-            "timeUnitRange");
+                "timeUnitRange");
         switch (timeUnitRange) {
         case YEAR:
         case ISOYEAR:
@@ -2460,7 +2352,6 @@ public class RexImpTable {
    * Implementor for JSON_VALUE function, convert to solid format
    * "JSON_VALUE(json_doc, path, empty_behavior, empty_default, error_behavior, error default)"
    * in order to simplify the runtime implementation.
-   *
    * <p>We should avoid this when we support
    * variable arguments function.
    */
@@ -2491,7 +2382,7 @@ public class RexImpTable {
             if (exprVal == SqlJsonEmptyOrError.EMPTY) {
               if (defaultSymbolIdx >= 0
                   && translator.getLiteralValue(leftExprs.get(defaultSymbolIdx))
-                      == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
+                  == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
                 defaultValueOnEmpty = leftExprs.get(i - 1);
                 emptyBehavior = leftExprs.get(defaultSymbolIdx);
               } else {
@@ -2500,7 +2391,7 @@ public class RexImpTable {
             } else if (exprVal == SqlJsonEmptyOrError.ERROR) {
               if (defaultSymbolIdx >= 0
                   && translator.getLiteralValue(leftExprs.get(defaultSymbolIdx))
-                      == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
+                  == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
                 defaultValueOnError = leftExprs.get(i - 1);
                 errorBehavior = leftExprs.get(defaultSymbolIdx);
               } else {
@@ -2523,10 +2414,11 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for SQL functions that generates calls to a given method name.
-   *
+  /**
+   * Implementor for SQL functions that generates calls to a given method name.
    * <p>Use this, as opposed to {@link MethodImplementor}, if the SQL function
-   * is overloaded; then you can use one implementor for several overloads. */
+   * is overloaded; then you can use one implementor for several overloads.
+   */
   private static class MethodNameImplementor extends AbstractRexCallImplementor {
     protected final String methodName;
 
@@ -2548,8 +2440,10 @@ public class RexImpTable {
 
   /** Implementor for binary operators. */
   private static class BinaryImplementor extends AbstractRexCallImplementor {
-    /** Types that can be arguments to comparison operators such as
-     * {@code <}. */
+    /**
+     * Types that can be arguments to comparison operators such as
+     * {@code <}.
+     */
     private static final List<Primitive> COMP_OP_TYPES =
         ImmutableList.of(
             Primitive.BYTE,
@@ -2945,7 +2839,7 @@ public class RexImpTable {
       final RelDataType targetType =
           nullifyType(translator.typeFactory, call.getType(), false);
       return translator.translateCast(sourceType,
-              targetType, argValueList.get(0));
+          targetType, argValueList.get(0));
     }
 
     private static RelDataType nullifyType(JavaTypeFactory typeFactory,
@@ -3016,6 +2910,7 @@ public class RexImpTable {
         new ArrayConcatImplementor();
     private MethodImplementor stringConcatImplementor
         = new MethodImplementor(BuiltInMethod.STRING_CONCAT.method, NullPolicy.STRICT, false);
+
     ConcatImplementor() {
       super(NullPolicy.STRICT, false);
     }
@@ -3113,10 +3008,11 @@ public class RexImpTable {
     }
   }
 
-  /** Implementor for SQL system functions.
-   *
+  /**
+   * Implementor for SQL system functions.
    * <p>Several of these are represented internally as constant values, set
-   * per execution. */
+   * per execution.
+   */
   private static class SystemFunctionImplementor
       extends AbstractRexCallImplementor {
     SystemFunctionImplementor() {
@@ -3190,6 +3086,7 @@ public class RexImpTable {
     DatetimeArithmeticImplementor() {
       super(NullPolicy.STRICT, false);
     }
+
     @Override String getVariableName() {
       return "dateTime_arithmetic";
     }
@@ -3392,13 +3289,10 @@ public class RexImpTable {
 
   /**
    * Abstract implementation of the {@link RexCallImplementor} interface.
-   *
    * <p>It is not always safe to execute the {@link RexCall} directly due to
    * the special null arguments. Therefore, the generated code logic is
    * conditional correspondingly.
-   *
    * <p>For example, {@code a + b} will generate two declaration statements:
-   *
    * <blockquote>
    * <code>
    * final Integer xxx_value = (a_isNull || b_isNull) ? null : plus(a, b);<br>
@@ -3422,7 +3316,7 @@ public class RexImpTable {
         final List<RexToLixTranslator.Result> arguments) {
       final List<Expression> argIsNullList = new ArrayList<>();
       final List<Expression> argValueList = new ArrayList<>();
-      for (RexToLixTranslator.Result result: arguments) {
+      for (RexToLixTranslator.Result result : arguments) {
         argIsNullList.add(result.isNullVariable);
         argValueList.add(result.valueVariable);
       }
@@ -3478,12 +3372,11 @@ public class RexImpTable {
       // the implementation's type is correct, we can't convert it.
       final SqlOperator op = call.getOperator();
       final Type returnType = translator.typeFactory.getJavaClass(call.getType());
-      final boolean noConvert = (returnType == null)
-              || (returnType == callValue.getType())
-              || (op instanceof SqlUserDefinedTableMacro)
-              || (op instanceof SqlUserDefinedTableFunction);
+      final boolean noConvert = (returnType == callValue.getType())
+          || (op instanceof SqlUserDefinedTableMacro)
+          || (op instanceof SqlUserDefinedTableFunction);
       final Expression convertedCallValue =
-              noConvert
+          noConvert
               ? callValue
               : EnumUtils.convert(callValue, returnType);
 
@@ -3504,8 +3397,8 @@ public class RexImpTable {
     }
 
     // E.g., "final boolean xxx_isNull = xxx_value == null"
-    private ParameterExpression genIsNullStatement(
-        final RexToLixTranslator translator, final ParameterExpression value) {
+    protected final ParameterExpression genIsNullStatement(
+        final RexToLixTranslator translator, final Expression value) {
       final ParameterExpression isNullVariable =
           Expressions.parameter(Boolean.TYPE,
               translator.getBlockBuilder().newName(getVariableName() + "_isNull"));
@@ -3555,8 +3448,10 @@ public class RexImpTable {
       return harmonizedArgValues;
     }
 
-    /** Under null check, it is safe to unbox the operands before entering the
-     * implementor. */
+    /**
+     * Under null check, it is safe to unbox the operands before entering the
+     * implementor.
+     */
     private List<Expression> unboxIfNecessary(final List<Expression> argValueList) {
       List<Expression> unboxValueList = argValueList;
       if (nullPolicy == NullPolicy.STRICT || nullPolicy == NullPolicy.ANY
@@ -3597,7 +3492,6 @@ public class RexImpTable {
 
   /**
    * Implementor for the {@code AND} operator.
-   *
    * <p>If any of the arguments are false, result is false;
    * else if any arguments are null, result is null;
    * else true.
@@ -3614,7 +3508,7 @@ public class RexImpTable {
     @Override public RexToLixTranslator.Result implement(final RexToLixTranslator translator,
         final RexCall call, final List<RexToLixTranslator.Result> arguments) {
       final List<Expression> argIsNullList = new ArrayList<>();
-      for (RexToLixTranslator.Result result: arguments) {
+      for (RexToLixTranslator.Result result : arguments) {
         argIsNullList.add(result.isNullVariable);
       }
       final List<Expression> nullAsTrue =
@@ -3635,14 +3529,9 @@ public class RexImpTable {
       final ParameterExpression valueVariable =
           Expressions.parameter(valueExpression.getType(),
               translator.getBlockBuilder().newName(getVariableName() + "_value"));
-      final Expression isNullExpression = translator.checkNull(valueVariable);
-      final ParameterExpression isNullVariable =
-          Expressions.parameter(Boolean.TYPE,
-              translator.getBlockBuilder().newName(getVariableName() + "_isNull"));
+      final ParameterExpression isNullVariable = genIsNullStatement(translator, valueExpression);
       translator.getBlockBuilder().add(
           Expressions.declare(Modifier.FINAL, valueVariable, valueExpression));
-      translator.getBlockBuilder().add(
-          Expressions.declare(Modifier.FINAL, isNullVariable, isNullExpression));
       return new RexToLixTranslator.Result(isNullVariable, valueVariable);
     }
 
@@ -3655,7 +3544,6 @@ public class RexImpTable {
 
   /**
    * Implementor for the {@code OR} operator.
-   *
    * <p>If any of the arguments are true, result is true;
    * else if any arguments are null, result is null;
    * else false.
@@ -3672,7 +3560,7 @@ public class RexImpTable {
     @Override public RexToLixTranslator.Result implement(final RexToLixTranslator translator,
         final RexCall call, final List<RexToLixTranslator.Result> arguments) {
       final List<Expression> argIsNullList = new ArrayList<>();
-      for (RexToLixTranslator.Result result: arguments) {
+      for (RexToLixTranslator.Result result : arguments) {
         argIsNullList.add(result.isNullVariable);
       }
       final List<Expression> nullAsFalse =
@@ -3712,7 +3600,6 @@ public class RexImpTable {
 
   /**
    * Implementor for the {@code NOT} operator.
-   *
    * <p>If any of the arguments are false, result is true;
    * else if any arguments are null, result is null;
    * else false.
@@ -3734,7 +3621,6 @@ public class RexImpTable {
 
   /**
    * Implementation that calls a given {@link java.lang.reflect.Method}.
-   *
    * <p>When method is not static, a new instance of the required class is
    * created.
    */
@@ -4049,6 +3935,88 @@ public class RexImpTable {
     }
   }
 
+  /**
+   * Implements
+   * <a href="https://www.postgresql.org/docs/current/functions-comparisons.html#id-1.5.8.30.16">
+   * ANY/SOME</a> and
+   * <a href="https://www.postgresql.org/docs/current/functions-comparisons.html#id-1.5.8.30.17">ALL</a>
+   * operators when the argument is an array or multiset expression.
+   */
+  private static class QuantifyCollectionImplementor extends AbstractRexCallImplementor {
+    private final SqlBinaryOperator binaryOperator;
+    private final RexCallImplementor binaryImplementor;
+
+    QuantifyCollectionImplementor(SqlBinaryOperator binaryOperator, RexCallImplementor binaryImplementor) {
+      super(NullPolicy.ANY, false);
+      this.binaryOperator = binaryOperator;
+      this.binaryImplementor = binaryImplementor;
+    }
+
+    @Override String getVariableName() {
+      return "quantify";
+    }
+
+    @Override Expression implementSafe(RexToLixTranslator translator, RexCall call,
+        List<Expression> argValueList) {
+      Expression left = argValueList.get(0);
+      Expression right = argValueList.get(1);
+      final RelDataType rightComponentType =
+          requireNonNull(call.getOperands().get(1).getType().getComponentType());
+      // If the array expression yields a null array, the result of SOME|ALL will be null
+      if (rightComponentType.getSqlTypeName() == SqlTypeName.NULL) {
+        return NULL_EXPR;
+      }
+
+      // final T _quantify_left_value = <>
+      // <Function1|Predicate1> lambda = new org.apache.calcite.linq4j.function.<Function1|Predicate1>() {
+      //    public Boolean apply(T el) {
+      //       return <binaryImplementor code>;
+      //    }
+      // }
+      // if the lambda returns java.lang.Boolean then the lambda can return null:
+      // return org.apache.calcite.runtime.SqlFunctions.<nullableExists|nullableSome>(_list, lambda)
+      // otherwise:
+      // return org.apache.calcite.linq4j.function.Functions.<exists|all>(_list, lambda)
+      BlockBuilder predicateLambdaBuilder = new BlockBuilder();
+      final ParameterExpression leftExpr =
+          Expressions.parameter(left.getType(), translator.getBlockBuilder().newName("_" + getVariableName() + "_left_value"));
+      // left should have final modifier otherwise it can not be passed to lambda
+      translator.getBlockBuilder().add(Expressions.declare(Modifier.FINAL, leftExpr, left));
+      RexNode leftRex = call.getOperands().get(0);
+      final ParameterExpression predicateArg =
+          Expressions.parameter(translator.typeFactory.getJavaClass(rightComponentType), "el");
+      final RexToLixTranslator.Result condition =
+          binaryImplementor.implement(
+              translator, (RexCall) translator.builder.makeCall(binaryOperator,
+              leftRex, translator.builder.makeDynamicParam(rightComponentType, 0)),
+          ImmutableList.of(
+              new RexToLixTranslator.Result(genIsNullStatement(translator, leftExpr), leftExpr),
+              new RexToLixTranslator.Result(genIsNullStatement(translator, predicateArg), predicateArg)));
+      predicateLambdaBuilder.add(Expressions.return_(null, condition.valueVariable));
+      final FunctionExpression<?> predicate = Expressions.lambda(predicateLambdaBuilder.toBlock(), predicateArg);
+      return Expressions.call(getMethod(condition.valueVariable.getType(), call.getKind()), right, predicate);
+    }
+
+    private Method getMethod(Type comparisonReturnType, SqlKind kind) {
+      switch (kind) {
+      case SOME:
+        return Primitive.is(comparisonReturnType)
+            ? BuiltInMethod.COLLECTION_EXISTS.method
+            // if the array contains any null elements and no true comparison result is obtained,
+            // the result of SOME will be null, not false.
+            : BuiltInMethod.COLLECTION_NULLABLE_EXISTS.method;
+      case ALL:
+        return Primitive.is(comparisonReturnType)
+            ? BuiltInMethod.COLLECTION_ALL.method
+            // if the array contains any null elements and no false comparison result is obtained,
+            // the result of ALL will be null, not true.
+            : BuiltInMethod.COLLECTION_NULLABLE_ALL.method;
+      default:
+        throw new IllegalArgumentException("Unknown quantify operator" + kind + ". Only support SOME,ALL.");
+      }
+    }
+  }
+
   /** Implements the {@code SESSION} table function. */
   private static class SessionImplementor implements TableFunctionCallImplementor {
     @Override public Expression implement(RexToLixTranslator translator,
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index abbec30a08..e5e121d8ee 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -100,11 +100,9 @@ import static java.util.Objects.requireNonNull;
 
 /**
  * Helper methods to implement SQL functions in generated code.
- *
  * <p>Not present: and, or, not (builtin operators are better, because they
  * use lazy evaluation. Implementations do not check for null values; the
  * calling code must do that.
- *
  * <p>Many of the functions do not check for null values. This is intentional.
  * If null arguments are possible, the code-generation framework checks for
  * nulls before calling the functions.
@@ -148,19 +146,22 @@ public class SqlFunctions {
         };
       };
 
-  /** Holds, for each thread, a map from sequence name to sequence current
+  /**
+   * Holds, for each thread, a map from sequence name to sequence current
    * value.
-   *
    * <p>This is a straw man of an implementation whose main goal is to prove
    * that sequences can be parsed, validated and planned. A real application
-   * will want persistent values for sequences, shared among threads. */
+   * will want persistent values for sequences, shared among threads.
+   */
   private static final ThreadLocal<@Nullable Map<String, AtomicLong>> THREAD_SEQUENCES =
       ThreadLocal.withInitial(HashMap::new);
 
   private static final Pattern PATTERN_0_STAR_E = Pattern.compile("0*E");
 
-  /** A byte string consisting of a single byte that is the ASCII space
-   * character (0x20). */
+  /**
+   * A byte string consisting of a single byte that is the ASCII space
+   * character (0x20).
+   */
   private static final ByteString SINGLE_SPACE_BYTE_STRING =
       ByteString.of("20", 16);
 
@@ -205,10 +206,11 @@ public class SqlFunctions {
   private SqlFunctions() {
   }
 
-  /** Internal THROW_UNLESS(condition, message) function.
-   *
+  /**
+   * Internal THROW_UNLESS(condition, message) function.
    * <p>The method is marked {@link NonDeterministic} to prevent the generator
-   * from storing its value as a constant. */
+   * from storing its value as a constant.
+   */
   @NonDeterministic
   public static boolean throwUnless(boolean condition, String message) {
     if (!condition) {
@@ -248,22 +250,22 @@ public class SqlFunctions {
   }
 
   /** SQL MD5(string) function. */
-  public static String md5(String string)  {
+  public static String md5(String string) {
     return DigestUtils.md5Hex(string.getBytes(UTF_8));
   }
 
   /** SQL MD5(string) function for binary string. */
-  public static String md5(ByteString string)  {
+  public static String md5(ByteString string) {
     return DigestUtils.md5Hex(string.getBytes());
   }
 
   /** SQL SHA1(string) function. */
-  public static String sha1(String string)  {
+  public static String sha1(String string) {
     return DigestUtils.sha1Hex(string.getBytes(UTF_8));
   }
 
   /** SQL SHA1(string) function for binary string. */
-  public static String sha1(ByteString string)  {
+  public static String sha1(ByteString string) {
     return DigestUtils.sha1Hex(string.getBytes());
   }
 
@@ -659,10 +661,11 @@ public class SqlFunctions {
     return s.substring(len - n);
   }
 
-  /** SQL CHAR(integer) function, as in MySQL and Spark.
-   *
+  /**
+   * SQL CHAR(integer) function, as in MySQL and Spark.
    * <p>Returns the ASCII character of {@code n} modulo 256,
-   * or null if {@code n} &lt; 0. */
+   * or null if {@code n} &lt; 0.
+   */
   public static @Nullable String charFromAscii(int n) {
     if (n < 0) {
       return null;
@@ -670,9 +673,10 @@ public class SqlFunctions {
     return String.valueOf(Character.toChars(n % 256));
   }
 
-  /** SQL CHR(integer) function, as in Oracle and Postgres.
-   *
-   * <p>Returns the UTF-8 character whose code is {@code n}. */
+  /**
+   * SQL CHR(integer) function, as in Oracle and Postgres.
+   * <p>Returns the UTF-8 character whose code is {@code n}.
+   */
   public static String charFromUtf8(int n) {
     return String.valueOf(Character.toChars(n));
   }
@@ -725,7 +729,7 @@ public class SqlFunctions {
     }
     int j = s.length();
     if (right) {
-      for (;;) {
+      for (; ; ) {
         if (j == 0) {
           return "";
         }
@@ -737,7 +741,7 @@ public class SqlFunctions {
     }
     int i = 0;
     if (left) {
-      for (;;) {
+      for (; ; ) {
         if (i == j) {
           return "";
         }
@@ -764,7 +768,7 @@ public class SqlFunctions {
   private static ByteString trim_(ByteString s, boolean left, boolean right) {
     int j = s.length();
     if (right) {
-      for (;;) {
+      for (; ; ) {
         if (j == 0) {
           return ByteString.EMPTY;
         }
@@ -776,7 +780,7 @@ public class SqlFunctions {
     }
     int i = 0;
     if (left) {
-      for (;;) {
+      for (; ; ) {
         if (i == j) {
           return ByteString.EMPTY;
         }
@@ -866,20 +870,26 @@ public class SqlFunctions {
 
   // =
 
-  /** SQL <code>=</code> operator applied to BigDecimal values (neither may be
-   * null). */
+  /**
+   * SQL <code>=</code> operator applied to BigDecimal values (neither may be
+   * null).
+   */
   public static boolean eq(BigDecimal b0, BigDecimal b1) {
     return b0.stripTrailingZeros().equals(b1.stripTrailingZeros());
   }
 
-  /** SQL <code>=</code> operator applied to Object[] values (neither may be
-   * null). */
+  /**
+   * SQL <code>=</code> operator applied to Object[] values (neither may be
+   * null).
+   */
   public static boolean eq(@Nullable Object @Nullable [] b0, @Nullable Object @Nullable [] b1) {
     return Arrays.deepEquals(b0, b1);
   }
 
-  /** SQL <code>=</code> operator applied to Object values (including String;
-   * neither side may be null). */
+  /**
+   * SQL <code>=</code> operator applied to Object values (including String;
+   * neither side may be null).
+   */
   public static boolean eq(Object b0, Object b1) {
     return b0.equals(b1);
   }
@@ -889,8 +899,10 @@ public class SqlFunctions {
     return comparator.compare(s0, s1) == 0;
   }
 
-  /** SQL <code>=</code> operator applied to Object values (at least one operand
-   * has ANY type; neither may be null). */
+  /**
+   * SQL <code>=</code> operator applied to Object values (at least one operand
+   * has ANY type; neither may be null).
+   */
   public static boolean eqAny(Object b0, Object b1) {
     if (b0.getClass().equals(b1.getClass())) {
       // The result of SqlFunctions.eq(BigDecimal, BigDecimal) makes more sense
@@ -922,8 +934,10 @@ public class SqlFunctions {
     return b0.compareTo(b1) != 0;
   }
 
-  /** SQL <code>&lt;gt;</code> operator applied to Object values (including
-   * String; neither side may be null). */
+  /**
+   * SQL <code>&lt;gt;</code> operator applied to Object values (including
+   * String; neither side may be null).
+   */
   public static boolean ne(Object b0, Object b1) {
     return !eq(b0, b1);
   }
@@ -933,8 +947,10 @@ public class SqlFunctions {
     return !eq(s0, s1, comparator);
   }
 
-  /** SQL <code>&lt;gt;</code> operator applied to Object values (at least one
-   *  operand has ANY type, including String; neither may be null). */
+  /**
+   * SQL <code>&lt;gt;</code> operator applied to Object values (at least one
+   * operand has ANY type, including String; neither may be null).
+   */
   public static boolean neAny(Object b0, Object b1) {
     return !eqAny(b0, b1);
   }
@@ -966,8 +982,10 @@ public class SqlFunctions {
     return b0.compareTo(b1) < 0;
   }
 
-  /** Returns whether {@code b0} is less than {@code b1}
-   * (or {@code b1} is null). Helper for {@code ARG_MIN}. */
+  /**
+   * Returns whether {@code b0} is less than {@code b1}
+   * (or {@code b1} is null). Helper for {@code ARG_MIN}.
+   */
   public static <T extends Comparable<T>> boolean ltNullable(T b0, T b1) {
     return b1 == null || b0 != null && b0.compareTo(b1) < 0;
   }
@@ -1040,8 +1058,10 @@ public class SqlFunctions {
     return b0.compareTo(b1) <= 0;
   }
 
-  /** SQL <code>&le;</code> operator applied to Object values (at least one
-   * operand has ANY type; neither may be null). */
+  /**
+   * SQL <code>&le;</code> operator applied to Object values (at least one
+   * operand has ANY type; neither may be null).
+   */
   public static boolean leAny(Object b0, Object b1) {
     if (b0.getClass().equals(b1.getClass())
         && b0 instanceof Comparable) {
@@ -1081,8 +1101,10 @@ public class SqlFunctions {
     return b0.compareTo(b1) > 0;
   }
 
-  /** Returns whether {@code b0} is greater than {@code b1}
-   * (or {@code b1} is null). Helper for {@code ARG_MAX}. */
+  /**
+   * Returns whether {@code b0} is greater than {@code b1}
+   * (or {@code b1} is null). Helper for {@code ARG_MAX}.
+   */
   public static <T extends Comparable<T>> boolean gtNullable(T b0, T b1) {
     return b1 == null || b0 != null && b0.compareTo(b1) > 0;
   }
@@ -1115,8 +1137,10 @@ public class SqlFunctions {
     return b0 > b1;
   }
 
-  /** SQL <code>&gt;</code> operator applied to Object values (at least one
-   * operand has ANY type; neither may be null). */
+  /**
+   * SQL <code>&gt;</code> operator applied to Object values (at least one
+   * operand has ANY type; neither may be null).
+   */
   public static boolean gtAny(Object b0, Object b1) {
     if (b0.getClass().equals(b1.getClass())
         && b0 instanceof Comparable) {
@@ -1156,8 +1180,10 @@ public class SqlFunctions {
     return b0.compareTo(b1) >= 0;
   }
 
-  /** SQL <code>&ge;</code> operator applied to Object values (at least one
-   * operand has ANY type; neither may be null). */
+  /**
+   * SQL <code>&ge;</code> operator applied to Object values (at least one
+   * operand has ANY type; neither may be null).
+   */
   public static boolean geAny(Object b0, Object b1) {
     if (b0.getClass().equals(b1.getClass())
         && b0 instanceof Comparable) {
@@ -1177,14 +1203,18 @@ public class SqlFunctions {
     return b0 + b1;
   }
 
-  /** SQL <code>+</code> operator applied to int values; left side may be
-   * null. */
+  /**
+   * SQL <code>+</code> operator applied to int values; left side may be
+   * null.
+   */
   public static @PolyNull Integer plus(@PolyNull Integer b0, int b1) {
     return b0 == null ? castNonNull(null) : (b0 + b1);
   }
 
-  /** SQL <code>+</code> operator applied to int values; right side may be
-   * null. */
+  /**
+   * SQL <code>+</code> operator applied to int values; right side may be
+   * null.
+   */
   public static @PolyNull Integer plus(int b0, @PolyNull Integer b1) {
     return b1 == null ? castNonNull(null) : (b0 + b1);
   }
@@ -1214,8 +1244,10 @@ public class SqlFunctions {
     return (b0 == null || b1 == null) ? castNonNull(null) : b0.add(b1);
   }
 
-  /** SQL <code>+</code> operator applied to Object values (at least one operand
-   * has ANY type; either may be null). */
+  /**
+   * SQL <code>+</code> operator applied to Object values (at least one operand
+   * has ANY type; either may be null).
+   */
   public static @PolyNull Object plusAny(@PolyNull Object b0,
       @PolyNull Object b1) {
     if (b0 == null || b1 == null) {
@@ -1236,14 +1268,18 @@ public class SqlFunctions {
     return b0 - b1;
   }
 
-  /** SQL <code>-</code> operator applied to int values; left side may be
-   * null. */
+  /**
+   * SQL <code>-</code> operator applied to int values; left side may be
+   * null.
+   */
   public static @PolyNull Integer minus(@PolyNull Integer b0, int b1) {
     return b0 == null ? castNonNull(null) : (b0 - b1);
   }
 
-  /** SQL <code>-</code> operator applied to int values; right side may be
-   * null. */
+  /**
+   * SQL <code>-</code> operator applied to int values; right side may be
+   * null.
+   */
   public static @PolyNull Integer minus(int b0, @PolyNull Integer b1) {
     return b1 == null ? castNonNull(null) : (b0 - b1);
   }
@@ -1273,8 +1309,10 @@ public class SqlFunctions {
     return (b0 == null || b1 == null) ? castNonNull(null) : b0.subtract(b1);
   }
 
-  /** SQL <code>-</code> operator applied to Object values (at least one operand
-   * has ANY type; either may be null). */
+  /**
+   * SQL <code>-</code> operator applied to Object values (at least one operand
+   * has ANY type; either may be null).
+   */
   public static @PolyNull Object minusAny(@PolyNull Object b0, @PolyNull Object b1) {
     if (b0 == null || b1 == null) {
       return castNonNull(null);
@@ -1294,14 +1332,18 @@ public class SqlFunctions {
     return b0 / b1;
   }
 
-  /** SQL <code>/</code> operator applied to int values; left side may be
-   * null. */
+  /**
+   * SQL <code>/</code> operator applied to int values; left side may be
+   * null.
+   */
   public static @PolyNull Integer divide(@PolyNull Integer b0, int b1) {
     return b0 == null ? castNonNull(null) : (b0 / b1);
   }
 
-  /** SQL <code>/</code> operator applied to int values; right side may be
-   * null. */
+  /**
+   * SQL <code>/</code> operator applied to int values; right side may be
+   * null.
+   */
   public static @PolyNull Integer divide(int b0, @PolyNull Integer b1) {
     return b1 == null ? castNonNull(null) : (b0 / b1);
   }
@@ -1334,8 +1376,10 @@ public class SqlFunctions {
         : b0.divide(b1, MathContext.DECIMAL64);
   }
 
-  /** SQL <code>/</code> operator applied to Object values (at least one operand
-   * has ANY type; either may be null). */
+  /**
+   * SQL <code>/</code> operator applied to Object values (at least one operand
+   * has ANY type; either may be null).
+   */
   public static @PolyNull Object divideAny(@PolyNull Object b0,
       @PolyNull Object b1) {
     if (b0 == null || b1 == null) {
@@ -1366,14 +1410,18 @@ public class SqlFunctions {
     return b0 * b1;
   }
 
-  /** SQL <code>*</code> operator applied to int values; left side may be
-   * null. */
+  /**
+   * SQL <code>*</code> operator applied to int values; left side may be
+   * null.
+   */
   public static @PolyNull Integer multiply(@PolyNull Integer b0, int b1) {
     return b0 == null ? castNonNull(null) : (b0 * b1);
   }
 
-  /** SQL <code>*</code> operator applied to int values; right side may be
-   * null. */
+  /**
+   * SQL <code>*</code> operator applied to int values; right side may be
+   * null.
+   */
   public static @PolyNull Integer multiply(int b0, @PolyNull Integer b1) {
     return b1 == null ? castNonNull(null) : (b0 * b1);
   }
@@ -1404,8 +1452,10 @@ public class SqlFunctions {
     return (b0 == null || b1 == null) ? castNonNull(null) : b0.multiply(b1);
   }
 
-  /** SQL <code>*</code> operator applied to Object values (at least one operand
-   * has ANY type; either may be null). */
+  /**
+   * SQL <code>*</code> operator applied to Object values (at least one operand
+   * has ANY type; either may be null).
+   */
   public static @PolyNull Object multiplyAny(@PolyNull Object b0,
       @PolyNull Object b1) {
     if (b0 == null || b1 == null) {
@@ -1463,9 +1513,8 @@ public class SqlFunctions {
 
   /**
    * Utility for bitwise function applied to two byteString values.
-   *
-   * @param b0 The first byteString value operand of bitwise function.
-   * @param b1 The second byteString value operand of bitwise function.
+   * @param b0    The first byteString value operand of bitwise function.
+   * @param b1    The second byteString value operand of bitwise function.
    * @param bitOp BitWise binary operator.
    * @return ByteString after bitwise operation.
    */
@@ -1738,6 +1787,7 @@ public class SqlFunctions {
   }
 
   // ACOS
+
   /** SQL <code>ACOS</code> operator applied to BigDecimal values. */
   public static double acos(BigDecimal b0) {
     return Math.acos(b0.doubleValue());
@@ -1749,6 +1799,7 @@ public class SqlFunctions {
   }
 
   // ASIN
+
   /** SQL <code>ASIN</code> operator applied to BigDecimal values. */
   public static double asin(BigDecimal b0) {
     return Math.asin(b0.doubleValue());
@@ -1760,6 +1811,7 @@ public class SqlFunctions {
   }
 
   // ATAN
+
   /** SQL <code>ATAN</code> operator applied to BigDecimal values. */
   public static double atan(BigDecimal b0) {
     return Math.atan(b0.doubleValue());
@@ -1771,6 +1823,7 @@ public class SqlFunctions {
   }
 
   // ATAN2
+
   /** SQL <code>ATAN2</code> operator applied to double/BigDecimal values. */
   public static double atan2(double b0, BigDecimal b1) {
     return Math.atan2(b0, b1.doubleValue());
@@ -1792,6 +1845,7 @@ public class SqlFunctions {
   }
 
   // CBRT
+
   /** SQL <code>CBRT</code> operator applied to BigDecimal values. */
   public static double cbrt(BigDecimal b) {
     return cbrt(b.doubleValue());
@@ -1803,6 +1857,7 @@ public class SqlFunctions {
   }
 
   // COS
+
   /** SQL <code>COS</code> operator applied to BigDecimal values. */
   public static double cos(BigDecimal b0) {
     return Math.cos(b0.doubleValue());
@@ -1814,6 +1869,7 @@ public class SqlFunctions {
   }
 
   // COSH
+
   /** SQL <code>COSH</code> operator applied to BigDecimal values. */
   public static double cosh(BigDecimal b) {
     return cosh(b.doubleValue());
@@ -1825,6 +1881,7 @@ public class SqlFunctions {
   }
 
   // COT
+
   /** SQL <code>COT</code> operator applied to BigDecimal values. */
   public static double cot(BigDecimal b0) {
     return 1.0d / Math.tan(b0.doubleValue());
@@ -1836,6 +1893,7 @@ public class SqlFunctions {
   }
 
   // DEGREES
+
   /** SQL <code>DEGREES</code> operator applied to BigDecimal values. */
   public static double degrees(BigDecimal b0) {
     return Math.toDegrees(b0.doubleValue());
@@ -1847,6 +1905,7 @@ public class SqlFunctions {
   }
 
   // RADIANS
+
   /** SQL <code>RADIANS</code> operator applied to BigDecimal values. */
   public static double radians(BigDecimal b0) {
     return Math.toRadians(b0.doubleValue());
@@ -1858,6 +1917,7 @@ public class SqlFunctions {
   }
 
   // SQL ROUND
+
   /** SQL <code>ROUND</code> operator applied to int values. */
   public static int sround(int b0) {
     return sround(b0, 0);
@@ -1900,6 +1960,7 @@ public class SqlFunctions {
   }
 
   // SQL TRUNCATE
+
   /** SQL <code>TRUNCATE</code> operator applied to int values. */
   public static int struncate(int b0) {
     return struncate(b0, 0);
@@ -1938,6 +1999,7 @@ public class SqlFunctions {
   }
 
   // SIGN
+
   /** SQL <code>SIGN</code> operator applied to int values. */
   public static int sign(int b0) {
     return Integer.signum(b0);
@@ -1959,6 +2021,7 @@ public class SqlFunctions {
   }
 
   // SIN
+
   /** SQL <code>SIN</code> operator applied to BigDecimal values. */
   public static double sin(BigDecimal b0) {
     return Math.sin(b0.doubleValue());
@@ -1970,6 +2033,7 @@ public class SqlFunctions {
   }
 
   // SINH
+
   /** SQL <code>SINH</code> operator applied to BigDecimal values. */
   public static double sinh(BigDecimal b) {
     return sinh(b.doubleValue());
@@ -1981,6 +2045,7 @@ public class SqlFunctions {
   }
 
   // TAN
+
   /** SQL <code>TAN</code> operator applied to BigDecimal values. */
   public static double tan(BigDecimal b0) {
     return Math.tan(b0.doubleValue());
@@ -1992,6 +2057,7 @@ public class SqlFunctions {
   }
 
   // TANH
+
   /** SQL <code>TANH</code> operator applied to BigDecimal values. */
   public static double tanh(BigDecimal b) {
     return tanh(b.doubleValue());
@@ -2156,8 +2222,8 @@ public class SqlFunctions {
   public static boolean toBoolean(Object o) {
     return o instanceof Boolean ? (Boolean) o
         : o instanceof Number ? toBoolean((Number) o)
-        : o instanceof String ? toBoolean((String) o)
-        : (Boolean) cannotConvert(o, boolean.class);
+            : o instanceof String ? toBoolean((String) o)
+                : (Boolean) cannotConvert(o, boolean.class);
   }
 
   // Don't need parseByte etc. - Byte.parseByte is sufficient.
@@ -2165,7 +2231,7 @@ public class SqlFunctions {
   public static byte toByte(Object o) {
     return o instanceof Byte ? (Byte) o
         : o instanceof Number ? toByte((Number) o)
-        : Byte.parseByte(o.toString());
+            : Byte.parseByte(o.toString());
   }
 
   public static byte toByte(Number number) {
@@ -2191,8 +2257,8 @@ public class SqlFunctions {
   public static short toShort(Object o) {
     return o instanceof Short ? (Short) o
         : o instanceof Number ? toShort((Number) o)
-        : o instanceof String ? toShort((String) o)
-        : (Short) cannotConvert(o, short.class);
+            : o instanceof String ? toShort((String) o)
+                : (Short) cannotConvert(o, short.class);
   }
 
   /**
@@ -2200,11 +2266,9 @@ public class SqlFunctions {
    * ({@link java.sql.Date}) to the internal representation type
    * (number of days since January 1st, 1970 as {@code int})
    * in the local time zone.
-   *
    * <p>Since a time zone is not available, the date is converted to represent
    * the same date as a Unix date in UTC as the {@link java.sql.Date} value in
    * the local time zone.
-   *
    * @see #toInt(java.sql.Date, TimeZone)
    * @see #internalToDate(int) converse method
    */
@@ -2216,12 +2280,10 @@ public class SqlFunctions {
    * Converts a SQL DATE value from the Java type
    * ({@link java.sql.Date}) to the internal representation type
    * (number of days since January 1st, 1970 as {@code int}).
-   *
    * <p>The {@link java.sql.Date} class uses the standard Gregorian calendar
    * which switches from the Julian calendar to the Gregorian calendar in
    * October 1582. For compatibility with ISO-8601, the internal representation
    * is converted to use the proleptic Gregorian calendar.
-   *
    * <p>If the date contains a partial day, it will be rounded to a full day
    * depending on the milliseconds value. If the milliseconds value is positive,
    * it will be rounded down to the closest full day. If the milliseconds value
@@ -2236,11 +2298,9 @@ public class SqlFunctions {
    * ({@link java.sql.Date}) to the internal representation type
    * (number of days since January 1st, 1970 as {@link Integer})
    * in the local time zone.
-   *
    * <p>Since a time zone is not available, the date is converted to represent
    * the same date as a Unix date in UTC as the {@link java.sql.Date} value in
    * the local time zone.
-   *
    * @see #toInt(java.sql.Date, TimeZone)
    * @see #internalToDate(Integer) converse method
    */
@@ -2254,7 +2314,6 @@ public class SqlFunctions {
    * Converts a nullable SQL DATE value from the Java type
    * ({@link java.sql.Date}) to the internal representation type
    * (number of days since January 1st, 1970 as {@link Integer}).
-   *
    * @see #toInt(java.sql.Date, TimeZone)
    */
   public static @PolyNull Integer toIntOptional(java.sql.@PolyNull Date v,
@@ -2269,7 +2328,6 @@ public class SqlFunctions {
    * ({@link java.sql.Time}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@code int})
    * in the local time zone.
-   *
    * @see #toIntOptional(java.sql.Time)
    * @see #internalToTime(int) converse method
    */
@@ -2281,7 +2339,6 @@ public class SqlFunctions {
    * Converts a nullable SQL TIME value from the Java type
    * ({@link java.sql.Time}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@link Integer}).
-   *
    * @see #toInt(java.sql.Time)
    * @see #internalToTime(Integer) converse method
    */
@@ -2300,10 +2357,10 @@ public class SqlFunctions {
   public static int toInt(Object o) {
     return o instanceof Integer ? (Integer) o
         : o instanceof Number ? toInt((Number) o)
-        : o instanceof String ? toInt((String) o)
-        : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
-        : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
-        : (Integer) cannotConvert(o, int.class);
+            : o instanceof String ? toInt((String) o)
+                : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
+                    : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
+                        : (Integer) cannotConvert(o, int.class);
   }
 
   public static @PolyNull Integer toIntOptional(@PolyNull Object o) {
@@ -2314,11 +2371,9 @@ public class SqlFunctions {
    * Converts a SQL TIMESTAMP value from the Java type
    * ({@link java.util.Date}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@code long}).
-   *
    * <p>Since a time zone is not available, converts the timestamp to represent
    * the same date and time as a Unix timestamp in UTC as the
    * {@link java.util.Date} value in the local time zone.
-   *
    * <p>The {@link java.util.Date} class uses the standard Gregorian calendar
    * which switches from the Julian calendar to the Gregorian calendar in
    * October 1582. For compatibility with ISO-8601, converts the internal
@@ -2332,11 +2387,9 @@ public class SqlFunctions {
    * Converts a SQL TIMESTAMP value from the Java type
    * ({@link Timestamp}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@code long}).
-   *
    * <p>Since a time zone is not available, converts the timestamp to represent
    * the same date and time as a Unix timestamp in UTC as the
    * {@link Timestamp} value in the local time zone.
-   *
    * @see #toLong(Timestamp, TimeZone)
    * @see #internalToTimestamp(Long) converse method
    */
@@ -2348,11 +2401,9 @@ public class SqlFunctions {
    * Converts a SQL TIMESTAMP value from the Java type
    * ({@link Timestamp}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@code long}).
-   *
    * <p>For backwards compatibility, time zone offsets are calculated in
    * relation to the local time zone instead of UTC. Providing the default time
    * zone or {@code null} will return the timestamp unmodified.
-   *
    * <p>The {@link Timestamp} class uses the standard Gregorian calendar which
    * switches from the Julian calendar to the Gregorian calendar in
    * October 1582. For compatibility with ISO-8601, the internal representation
@@ -2367,7 +2418,6 @@ public class SqlFunctions {
    * ({@link Timestamp}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@link Long})
    * in the local time zone.
-   *
    * @see #toLong(Timestamp, TimeZone)
    * @see #internalToTimestamp(Long) converse method
    */
@@ -2379,7 +2429,6 @@ public class SqlFunctions {
    * Converts a nullable SQL TIMESTAMP value from the Java type
    * ({@link Timestamp}) to the internal representation type
    * (number of milliseconds since January 1st, 1970 as {@link Long}).
-   *
    * @see #toLong(Timestamp, TimeZone)
    */
   public static @PolyNull Long toLongOptional(@PolyNull Timestamp v,
@@ -2404,12 +2453,12 @@ public class SqlFunctions {
   public static long toLong(Object o) {
     return o instanceof Long ? (Long) o
         : o instanceof Number ? toLong((Number) o)
-        : o instanceof String ? toLong((String) o)
-        : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
-        : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
-        : o instanceof java.sql.Timestamp ? toLong((java.sql.Timestamp) o)
-        : o instanceof java.util.Date ? toLong((java.util.Date) o)
-        : (Long) cannotConvert(o, long.class);
+            : o instanceof String ? toLong((String) o)
+                : o instanceof java.sql.Date ? toInt((java.sql.Date) o)
+                    : o instanceof java.sql.Time ? toInt((java.sql.Time) o)
+                        : o instanceof java.sql.Timestamp ? toLong((java.sql.Timestamp) o)
+                            : o instanceof java.util.Date ? toLong((java.util.Date) o)
+                                : (Long) cannotConvert(o, long.class);
   }
 
   public static @PolyNull Long toLongOptional(@PolyNull Object o) {
@@ -2427,8 +2476,8 @@ public class SqlFunctions {
   public static float toFloat(Object o) {
     return o instanceof Float ? (Float) o
         : o instanceof Number ? toFloat((Number) o)
-        : o instanceof String ? toFloat((String) o)
-        : (Float) cannotConvert(o, float.class);
+            : o instanceof String ? toFloat((String) o)
+                : (Float) cannotConvert(o, float.class);
   }
 
   public static double toDouble(String s) {
@@ -2442,8 +2491,8 @@ public class SqlFunctions {
   public static double toDouble(Object o) {
     return o instanceof Double ? (Double) o
         : o instanceof Number ? toDouble((Number) o)
-        : o instanceof String ? toDouble((String) o)
-        : (Double) cannotConvert(o, double.class);
+            : o instanceof String ? toDouble((String) o)
+                : (Double) cannotConvert(o, double.class);
   }
 
   public static BigDecimal toBigDecimal(String s) {
@@ -2455,8 +2504,8 @@ public class SqlFunctions {
     // Not so "int". If it isn't a long, go straight to double.
     return number instanceof BigDecimal ? (BigDecimal) number
         : number instanceof BigInteger ? new BigDecimal((BigInteger) number)
-        : number instanceof Long ? new BigDecimal(number.longValue())
-        : new BigDecimal(number.doubleValue());
+            : number instanceof Long ? new BigDecimal(number.longValue())
+                : new BigDecimal(number.doubleValue());
   }
 
   public static BigDecimal toBigDecimal(Object o) {
@@ -2468,17 +2517,14 @@ public class SqlFunctions {
    * Converts a SQL DATE value from the internal representation type
    * (number of days since January 1st, 1970) to the Java type
    * ({@link java.sql.Date}).
-   *
    * <p>Since a time zone is not available, converts the date to represent the
    * same date as a {@link java.sql.Date} in the local time zone as the Unix
    * date in UTC.
-   *
    * <p>The Unix date should be the number of days since January 1st, 1970
    * using the proleptic Gregorian calendar as defined by ISO-8601. The
    * returned {@link java.sql.Date} object will use the standard Gregorian
    * calendar which switches from the Julian calendar to the Gregorian calendar
    * in October 1582.
-   *
    * @see #internalToDate(Integer)
    * @see #toInt(java.sql.Date) converse method
    */
@@ -2491,7 +2537,6 @@ public class SqlFunctions {
    * Converts a nullable SQL DATE value from the internal representation type
    * (number of days since January 1st, 1970) to the Java type
    * ({@link java.sql.Date}).
-   *
    * @see #internalToDate(int)
    * @see #toIntOptional(java.sql.Date) converse method
    */
@@ -2503,7 +2548,6 @@ public class SqlFunctions {
    * Converts a SQL TIME value from the internal representation type
    * (number of milliseconds since January 1st, 1970) to the Java type
    * ({@link java.sql.Time}).
-   *
    * @see #internalToTime(Integer)
    * @see #toInt(java.sql.Time) converse method
    */
@@ -2515,7 +2559,6 @@ public class SqlFunctions {
    * Converts a nullable SQL TIME value from the internal representation type
    * (number of milliseconds since January 1st, 1970) to the Java type
    * ({@link java.sql.Time}).
-   *
    * @see #internalToTime(Integer)
    * @see #toIntOptional(java.sql.Time) converse method
    */
@@ -2599,17 +2642,14 @@ public class SqlFunctions {
    * (number of milliseconds since January 1st, 1970) to the Java Type
    * ({@link Timestamp})
    * in the local time zone.
-   *
    * <p>Since a time zone is not available, the timestamp is converted to
    * represent the same timestamp as a {@link Timestamp} in the local time zone
    * as the Unix timestamp in UTC.
-   *
    * <p>The Unix timestamp should be the number of milliseconds since
    * January 1st, 1970 using the proleptic Gregorian calendar as defined by
    * ISO-8601. The returned {@link Timestamp} object will use the standard
    * Gregorian calendar which switches from the Julian calendar to the
    * Gregorian calendar in October 1582.
-   *
    * @see #internalToTimestamp(Long)
    * @see #toLong(Timestamp, TimeZone)
    * @see #toLongOptional(Timestamp)
@@ -2631,7 +2671,6 @@ public class SqlFunctions {
    * type (number of milliseconds since January 1st, 1970) to the Java Type
    * ({@link Timestamp})
    * in the local time zone.
-   *
    * @see #internalToTimestamp(long)
    * @see #toLong(Timestamp)
    * @see #toLong(Timestamp, TimeZone)
@@ -2727,8 +2766,10 @@ public class SqlFunctions {
     return (int) LocalDate.of(year, month, day).toEpochDay();
   }
 
-  /** SQL {@code DATE(TIMESTAMP)} and
-   * {@code DATE(TIMESTAMP WITH LOCAL TIME ZONE)} functions. */
+  /**
+   * SQL {@code DATE(TIMESTAMP)} and
+   * {@code DATE(TIMESTAMP WITH LOCAL TIME ZONE)} functions.
+   */
   public static int date(long timestampMillis) {
     // Calcite represents dates as Unix integers (days since epoch).
     // Unix time ignores leap seconds; every day has the exact same number of
@@ -2747,8 +2788,10 @@ public class SqlFunctions {
         .toEpochDay();
   }
 
-  /** SQL {@code DATETIME(<year>, <month>, <day>, <hour>, <minute>, <second>)}
-   * function. */
+  /**
+   * SQL {@code DATETIME(<year>, <month>, <day>, <hour>, <minute>, <second>)}
+   * function.
+   */
   public static long datetime(int year, int month, int day, int hour,
       int minute, int second) {
     // BigQuery's DATETIME function returns a Calcite TIMESTAMP,
@@ -2772,8 +2815,10 @@ public class SqlFunctions {
     return daysSinceEpoch * DateTimeUtils.MILLIS_PER_DAY + millisSinceMidnight;
   }
 
-  /** SQL {@code DATETIME(TIMESTAMP WITH LOCAL TIME ZONE)} function;
-   * returns a Calcite TIMESTAMP. */
+  /**
+   * SQL {@code DATETIME(TIMESTAMP WITH LOCAL TIME ZONE)} function;
+   * returns a Calcite TIMESTAMP.
+   */
   public static long datetime(long millisSinceEpoch) {
     // BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL TIME
     // ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2781,8 +2826,10 @@ public class SqlFunctions {
     return millisSinceEpoch;
   }
 
-  /** SQL {@code DATETIME(TIMESTAMP, timeZone)} function;
-   * returns a Calcite TIMESTAMP. */
+  /**
+   * SQL {@code DATETIME(TIMESTAMP, timeZone)} function;
+   * returns a Calcite TIMESTAMP.
+   */
   public static long datetime(long millisSinceEpoch, String timeZone) {
     // BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL TIME
     // ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2865,8 +2912,10 @@ public class SqlFunctions {
         .toEpochMilli();
   }
 
-  /** SQL {@code TIMESTAMP(<timestamp>)} function; returns a TIMESTAMP WITH
-   * LOCAL TIME ZONE. */
+  /**
+   * SQL {@code TIMESTAMP(<timestamp>)} function; returns a TIMESTAMP WITH
+   * LOCAL TIME ZONE.
+   */
   public static long timestamp(long millisSinceEpoch) {
     // BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL
     // TIME ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2874,8 +2923,10 @@ public class SqlFunctions {
     return millisSinceEpoch;
   }
 
-  /** SQL {@code TIMESTAMP(<timestamp>, <timeZone>)} function; returns a
-   * TIMESTAMP WITH LOCAL TIME ZONE. */
+  /**
+   * SQL {@code TIMESTAMP(<timestamp>, <timeZone>)} function; returns a
+   * TIMESTAMP WITH LOCAL TIME ZONE.
+   */
   public static long timestamp(long millisSinceEpoch, String timeZone) {
     // BigQuery TIMESTAMP and DATETIME values (Calcite TIMESTAMP WITH LOCAL
     // TIME ZONE and TIMESTAMP, respectively) are represented internally as
@@ -2895,8 +2946,10 @@ public class SqlFunctions {
         * DateTimeUtils.MILLIS_PER_SECOND);
   }
 
-  /** SQL {@code TIME(<timestamp>)} and {@code TIME(<timestampLtz>)}
-   * functions. */
+  /**
+   * SQL {@code TIME(<timestamp>)} and {@code TIME(<timestampLtz>)}
+   * functions.
+   */
   public static int time(long timestampMillis) {
     // Calcite represents time as Unix integers (milliseconds since midnight).
     // Unix time ignores leap seconds; every day has the same number of
@@ -3016,8 +3069,10 @@ public class SqlFunctions {
     return s.indexOf(seek, from0) + 1;
   }
 
-  /** SQL {@code POSITION(seek IN string FROM integer)} function for byte
-   * strings. */
+  /**
+   * SQL {@code POSITION(seek IN string FROM integer)} function for byte
+   * strings.
+   */
   public static int position(ByteString seek, ByteString s, int from) {
     final int from0 = from - 1;
     if (from0 > s.length() || from0 < 0) {
@@ -3057,9 +3112,8 @@ public class SqlFunctions {
 
   /**
    * SQL {@code DAYNAME} function, applied to a TIMESTAMP argument.
-   *
    * @param timestamp Milliseconds from epoch
-   * @param locale Locale
+   * @param locale    Locale
    * @return Name of the weekday in the given locale
    */
   public static String dayNameWithTimestamp(long timestamp, Locale locale) {
@@ -3069,8 +3123,7 @@ public class SqlFunctions {
 
   /**
    * SQL {@code DAYNAME} function, applied to a DATE argument.
-   *
-   * @param date Days since epoch
+   * @param date   Days since epoch
    * @param locale Locale
    * @return Name of the weekday in the given locale
    */
@@ -3081,9 +3134,8 @@ public class SqlFunctions {
 
   /**
    * SQL {@code MONTHNAME} function, applied to a TIMESTAMP argument.
-   *
    * @param timestamp Milliseconds from epoch
-   * @param locale Locale
+   * @param locale    Locale
    * @return Name of the month in the given locale
    */
   public static String monthNameWithTimestamp(long timestamp, Locale locale) {
@@ -3093,8 +3145,7 @@ public class SqlFunctions {
 
   /**
    * SQL {@code MONTHNAME} function, applied to a DATE argument.
-   *
-   * @param date Days from epoch
+   * @param date   Days from epoch
    * @param locale Locale
    * @return Name of the month in the given locale
    */
@@ -3105,7 +3156,6 @@ public class SqlFunctions {
 
   /**
    * Converts a date (days since epoch) to a {@link LocalDate}.
-   *
    * @param date days since epoch
    * @return localDate
    */
@@ -3118,7 +3168,6 @@ public class SqlFunctions {
 
   /**
    * Converts a timestamp (milliseconds since epoch) to a {@link LocalDate}.
-   *
    * @param timestamp milliseconds from epoch
    * @return localDate
    */
@@ -3127,14 +3176,18 @@ public class SqlFunctions {
     return dateToLocalDate(date);
   }
 
-  /** Converts a timestamp (milliseconds since epoch)
-   * to a date (days since epoch). */
+  /**
+   * Converts a timestamp (milliseconds since epoch)
+   * to a date (days since epoch).
+   */
   public static int timestampToDate(long timestamp) {
     return (int) (timestamp / DateTimeUtils.MILLIS_PER_DAY);
   }
 
-  /** Converts a timestamp (milliseconds since epoch)
-   * to a time (milliseconds since midnight). */
+  /**
+   * Converts a timestamp (milliseconds since epoch)
+   * to a time (milliseconds since midnight).
+   */
   public static int timestampToTime(long timestamp) {
     return (int) (timestamp % DateTimeUtils.MILLIS_PER_DAY);
   }
@@ -3201,12 +3254,13 @@ public class SqlFunctions {
     return DataContext.Variable.LOCALE.get(root);
   }
 
-  /** SQL {@code DATEADD} function applied to a custom time frame.
-   *
+  /**
+   * SQL {@code DATEADD} function applied to a custom time frame.
    * <p>Custom time frames are created as part of a {@link TimeFrameSet}.
    * This method retrieves the session's time frame set from the
    * {@link DataContext.Variable#TIME_FRAME_SET} variable, then looks up the
-   * time frame by name. */
+   * time frame by name.
+   */
   public static int customDateAdd(DataContext root,
       String timeFrameName, int interval, int date) {
     final TimeFrameSet timeFrameSet =
@@ -3215,10 +3269,11 @@ public class SqlFunctions {
     return timeFrameSet.addDate(date, interval, timeFrame);
   }
 
-  /** SQL {@code TIMESTAMPADD} function applied to a custom time frame.
-   *
+  /**
+   * SQL {@code TIMESTAMPADD} function applied to a custom time frame.
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static long customTimestampAdd(DataContext root,
       String timeFrameName, long interval, long timestamp) {
     final TimeFrameSet timeFrameSet =
@@ -3227,10 +3282,11 @@ public class SqlFunctions {
     return timeFrameSet.addTimestamp(timestamp, interval, timeFrame);
   }
 
-  /** SQL {@code DATEDIFF} function applied to a custom time frame.
-   *
+  /**
+   * SQL {@code DATEDIFF} function applied to a custom time frame.
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static int customDateDiff(DataContext root,
       String timeFrameName, int date, int date2) {
     final TimeFrameSet timeFrameSet =
@@ -3239,10 +3295,11 @@ public class SqlFunctions {
     return timeFrameSet.diffDate(date, date2, timeFrame);
   }
 
-  /** SQL {@code TIMESTAMPDIFF} function applied to a custom time frame.
-   *
+  /**
+   * SQL {@code TIMESTAMPDIFF} function applied to a custom time frame.
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static long customTimestampDiff(DataContext root,
       String timeFrameName, long timestamp, long timestamp2) {
     final TimeFrameSet timeFrameSet =
@@ -3251,11 +3308,12 @@ public class SqlFunctions {
     return timeFrameSet.diffTimestamp(timestamp, timestamp2, timeFrame);
   }
 
-  /** SQL {@code FLOOR} function applied to a {@code DATE} value
+  /**
+   * SQL {@code FLOOR} function applied to a {@code DATE} value
    * and a custom time frame.
-   *
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static int customDateFloor(DataContext root,
       String timeFrameName, int date) {
     final TimeFrameSet timeFrameSet =
@@ -3264,11 +3322,12 @@ public class SqlFunctions {
     return timeFrameSet.floorDate(date, timeFrame);
   }
 
-  /** SQL {@code CEIL} function applied to a {@code DATE} value
+  /**
+   * SQL {@code CEIL} function applied to a {@code DATE} value
    * and a custom time frame.
-   *
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static int customDateCeil(DataContext root,
       String timeFrameName, int date) {
     final TimeFrameSet timeFrameSet =
@@ -3277,11 +3336,12 @@ public class SqlFunctions {
     return timeFrameSet.ceilDate(date, timeFrame);
   }
 
-  /** SQL {@code FLOOR} function applied to a {@code TIMESTAMP} value
+  /**
+   * SQL {@code FLOOR} function applied to a {@code TIMESTAMP} value
    * and a custom time frame.
-   *
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static long customTimestampFloor(DataContext root,
       String timeFrameName, long timestamp) {
     final TimeFrameSet timeFrameSet =
@@ -3290,11 +3350,12 @@ public class SqlFunctions {
     return timeFrameSet.floorTimestamp(timestamp, timeFrame);
   }
 
-  /** SQL {@code CEIL} function applied to a {@code TIMESTAMP} value
+  /**
+   * SQL {@code CEIL} function applied to a {@code TIMESTAMP} value
    * and a custom time frame.
-   *
    * <p>Custom time frames are created and accessed as described in
-   * {@link #customDateAdd}. */
+   * {@link #customDateAdd}.
+   */
   public static long customTimestampCeil(DataContext root,
       String timeFrameName, long timestamp) {
     final TimeFrameSet timeFrameSet =
@@ -3303,8 +3364,10 @@ public class SqlFunctions {
     return timeFrameSet.ceilTimestamp(timestamp, timeFrame);
   }
 
-  /** SQL {@code TRANSLATE(string, search_chars, replacement_chars)}
-   * function. */
+  /**
+   * SQL {@code TRANSLATE(string, search_chars, replacement_chars)}
+   * function.
+   */
   public static String translate3(String s, String search, String replacement) {
     return org.apache.commons.lang3.StringUtils.replaceChars(s, search, replacement);
   }
@@ -3314,8 +3377,10 @@ public class SqlFunctions {
     return s.replace(search, replacement);
   }
 
-  /** Helper for "array element reference". Caller has already ensured that
-   * array and index are not null. Index is 1-based, per SQL. */
+  /**
+   * Helper for "array element reference". Caller has already ensured that
+   * array and index are not null. Index is 1-based, per SQL.
+   */
   public static @Nullable Object arrayItem(List list, int item) {
     if (item < 1 || item > list.size()) {
       return null;
@@ -3323,13 +3388,16 @@ public class SqlFunctions {
     return list.get(item - 1);
   }
 
-  /** Helper for "map element reference". Caller has already ensured that
-   * array and index are not null. Index is 1-based, per SQL. */
+  /**
+   * Helper for "map element reference". Caller has already ensured that
+   * array and index are not null. Index is 1-based, per SQL.
+   */
   public static @Nullable Object mapItem(Map map, Object item) {
     return map.get(item);
   }
 
-  /** Implements the {@code [ ... ]} operator on an object whose type is not
+  /**
+   * Implements the {@code [ ... ]} operator on an object whose type is not
    * known until runtime.
    */
   public static @Nullable Object item(Object object, Object index) {
@@ -3576,7 +3644,7 @@ public class SqlFunctions {
         //noinspection unchecked
         return (Function1) LIST_AS_ENUMERABLE;
       } else {
-        return row -> p2(new Object[] { row }, fieldCounts, withOrdinality,
+        return row -> p2(new Object[]{row}, fieldCounts, withOrdinality,
             inputTypes);
       }
     }
@@ -3595,19 +3663,22 @@ public class SqlFunctions {
       Object inputObject = lists[i];
       switch (inputType) {
       case SCALAR:
-        @SuppressWarnings("unchecked") List<Comparable> list =
+        @SuppressWarnings("unchecked")
+        List<Comparable> list =
             (List<Comparable>) inputObject;
         enumerators.add(
             Linq4j.transform(
                 Linq4j.enumerator(list), FlatLists::of));
         break;
       case LIST:
-        @SuppressWarnings("unchecked") List<List<Comparable>> listList =
+        @SuppressWarnings("unchecked")
+        List<List<Comparable>> listList =
             (List<List<Comparable>>) inputObject;
         enumerators.add(Linq4j.enumerator(listList));
         break;
       case MAP:
-        @SuppressWarnings("unchecked") Map<Comparable, Comparable> map =
+        @SuppressWarnings("unchecked")
+        Map<Comparable, Comparable> map =
             (Map<Comparable, Comparable>) inputObject;
         Enumerator<Map.Entry<Comparable, Comparable>> enumerator =
             Linq4j.enumerator(map.entrySet());
@@ -3636,8 +3707,48 @@ public class SqlFunctions {
     return args;
   }
 
-  /** Similar to {@link Linq4j#product(Iterable)} but each resulting list
-   * implements {@link FlatLists.ComparableList}. */
+  /**
+   * Returns whether there is an element in {@code list} for which
+   * {@code predicate} is true. Also, if {@code predicate} returns null for any element of {@code list}
+   * and there are no true comparison result is obtained, the result will be null, not false.
+   */
+  public static @Nullable <E> Boolean nullableExists(List<? extends E> list,
+      Function1<E, Boolean> predicate) {
+    boolean nullExists = false;
+    for (E e : list) {
+      Boolean res = predicate.apply(e);
+      if (res == null) {
+        nullExists = true;
+      } else if (res) {
+        return true;
+      }
+    }
+    return nullExists ? null : false;
+  }
+
+  /**
+   * Returns whether {@code predicate} is true for all elements of
+   * {@code list}. Also, if {@code predicate} returns null for any element of {@code list}
+   * and there are no false comparison result is obtained, the result will be null, not true.
+   */
+  public static @Nullable <E> Boolean nullableAll(List<? extends E> list,
+      Function1<E, Boolean> predicate) {
+    boolean nullExists = false;
+    for (E e : list) {
+      Boolean res = predicate.apply(e);
+      if (res == null) {
+        nullExists = true;
+      } else if (!res) {
+        return false;
+      }
+    }
+    return nullExists ? null : true;
+  }
+
+  /**
+   * Similar to {@link Linq4j#product(Iterable)} but each resulting list
+   * implements {@link FlatLists.ComparableList}.
+   */
   public static <E extends Comparable> Enumerable<FlatLists.ComparableList<E>> product(
       final List<Enumerator<List<E>>> enumerators, final int fieldCount,
       final boolean withOrdinality) {
@@ -3652,7 +3763,6 @@ public class SqlFunctions {
   /**
    * Implements the {@code .} (field access) operator on an object
    * whose type is not known until runtime.
-   *
    * <p>A struct object can be represented in various ways by the
    * runtime and depends on the
    * {@link org.apache.calcite.adapter.enumerable.JavaRowFormat}.
@@ -3684,10 +3794,11 @@ public class SqlFunctions {
     }
   }
 
-  /** Enumerates over the cartesian product of the given lists, returning
+  /**
+   * Enumerates over the cartesian product of the given lists, returning
    * a comparable list for each row.
-   *
-   * @param <E> element type */
+   * @param <E> element type
+   */
   private static class ProductComparableListEnumerator<E extends Comparable>
       extends CartesianProductEnumerator<List<E>, FlatLists.ComparableList<E>> {
     final Object[] flatElements;
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
index 37250cd7cf..4eb1174238 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
@@ -16,20 +16,29 @@
  */
 package org.apache.calcite.sql.fun;
 
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.type.SqlTypeUtil;
+import org.apache.calcite.sql.validate.SqlValidator;
+import org.apache.calcite.sql.validate.SqlValidatorScope;
 
 import com.google.common.base.Preconditions;
 
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
 import java.util.Objects;
 
 /**
  * Definition of the SQL <code>ALL</code> and <code>SOME</code>operators.
- *
  * <p>Each is used in combination with a relational operator:
  * <code>&lt;</code>, <code>&le;</code>,
  * <code>&gt;</code>, <code>&ge;</code>,
  * <code>=</code>, <code>&lt;&gt;</code>.
- *
  * <p><code>ANY</code> is a synonym for <code>SOME</code>.
  */
 public class SqlQuantifyOperator extends SqlInOperator {
@@ -41,11 +50,10 @@ public class SqlQuantifyOperator extends SqlInOperator {
 
   /**
    * Creates a SqlQuantifyOperator.
-   *
-   * @param kind Either ALL or SOME
+   * @param kind           Either ALL or SOME
    * @param comparisonKind Either <code>&lt;</code>, <code>&le;</code>,
-   *   <code>&gt;</code>, <code>&ge;</code>,
-   *   <code>=</code> or <code>&lt;&gt;</code>.
+   *                       <code>&gt;</code>, <code>&ge;</code>,
+   *                       <code>=</code> or <code>&lt;&gt;</code>.
    */
   SqlQuantifyOperator(SqlKind kind, SqlKind comparisonKind) {
     super(comparisonKind.sql + " " + kind, kind);
@@ -59,4 +67,43 @@ public class SqlQuantifyOperator extends SqlInOperator {
     Preconditions.checkArgument(kind == SqlKind.SOME
         || kind == SqlKind.ALL);
   }
+
+  @Override public RelDataType deriveType(SqlValidator validator,
+      SqlValidatorScope scope, SqlCall call) {
+    final List<SqlNode> operands = call.getOperandList();
+    assert operands.size() == 2;
+
+    RelDataType typeForCollectionArgument = tryDeriveTypeForCollection(validator, scope, call);
+    if (typeForCollectionArgument != null) {
+      return typeForCollectionArgument;
+    }
+    return super.deriveType(validator, scope, call);
+  }
+
+  /**
+   * @param validator Validator
+   * @param scope     Scope of validation
+   * @param call      Call to this operator
+   * @return If SOME or ALL is applied to a collection, then the function
+   * returns type of call, otherwise it returns null.
+   */
+  public @Nullable RelDataType tryDeriveTypeForCollection(SqlValidator validator,
+      SqlValidatorScope scope, SqlCall call) {
+    final SqlNode left = call.operand(0);
+    final SqlNode right = call.operand(1);
+    if (right instanceof SqlNodeList && ((SqlNodeList) right).size() == 1) {
+      final RelDataType rightType = validator.deriveType(scope, ((SqlNodeList) right).get(0));
+      if (SqlTypeUtil.isCollection(rightType)) {
+        final RelDataType componentRightType = Objects.requireNonNull(rightType.getComponentType());
+        final RelDataType leftType = validator.deriveType(scope, left);
+        if (SqlTypeUtil.sameNamedType(componentRightType, leftType) ||
+            SqlTypeUtil.isNull(leftType) || SqlTypeUtil.isNull(componentRightType)) {
+          return validator.getTypeFactory().createTypeWithNullability(
+              validator.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN),
+              rightType.isNullable() || componentRightType.isNullable() || leftType.isNullable());
+        }
+      }
+    }
+    return null;
+  }
 }
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 6c7f1cfc46..54c29442f7 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
@@ -196,38 +196,49 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    */
   public static final SqlSpecialOperator DEFAULT = new SqlDefaultOperator();
 
-  /** <code>FILTER</code> operator filters which rows are included in an
-   *  aggregate function. */
+  /**
+   * <code>FILTER</code> operator filters which rows are included in an
+   * aggregate function.
+   */
   public static final SqlFilterOperator FILTER = new SqlFilterOperator();
 
   /** <code>WITHIN_GROUP</code> operator performs aggregations on ordered data input. */
   public static final SqlWithinGroupOperator WITHIN_GROUP = new SqlWithinGroupOperator();
 
-  /** <code>WITHIN_DISTINCT</code> operator performs aggregations on distinct
-   * data input. */
+  /**
+   * <code>WITHIN_DISTINCT</code> operator performs aggregations on distinct
+   * data input.
+   */
   public static final SqlWithinDistinctOperator WITHIN_DISTINCT =
       new SqlWithinDistinctOperator();
 
-  /** {@code CUBE} operator, occurs within {@code GROUP BY} clause
-   * or nested within a {@code GROUPING SETS}. */
+  /**
+   * {@code CUBE} operator, occurs within {@code GROUP BY} clause
+   * or nested within a {@code GROUPING SETS}.
+   */
   public static final SqlInternalOperator CUBE =
       new SqlRollupOperator("CUBE", SqlKind.CUBE);
 
-  /** {@code ROLLUP} operator, occurs within {@code GROUP BY} clause
-   * or nested within a {@code GROUPING SETS}. */
+  /**
+   * {@code ROLLUP} operator, occurs within {@code GROUP BY} clause
+   * or nested within a {@code GROUPING SETS}.
+   */
   public static final SqlInternalOperator ROLLUP =
       new SqlRollupOperator("ROLLUP", SqlKind.ROLLUP);
 
-  /** {@code GROUPING SETS} operator, occurs within {@code GROUP BY} clause
-   * or nested within a {@code GROUPING SETS}. */
+  /**
+   * {@code GROUPING SETS} operator, occurs within {@code GROUP BY} clause
+   * or nested within a {@code GROUPING SETS}.
+   */
   public static final SqlInternalOperator GROUPING_SETS =
       new SqlRollupOperator("GROUPING SETS", SqlKind.GROUPING_SETS);
 
-  /** {@code GROUPING(c1 [, c2, ...])} function.
-   *
+  /**
+   * {@code GROUPING(c1 [, c2, ...])} function.
    * <p>Occurs in similar places to an aggregate
    * function ({@code SELECT}, {@code HAVING} clause, etc. of an aggregate
-   * query), but not technically an aggregate function. */
+   * query), but not technically an aggregate function.
+   */
   public static final SqlAggFunction GROUPING =
       new SqlGroupingFunction("GROUPING");
 
@@ -235,16 +246,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   public static final SqlAggFunction GROUP_ID =
       new SqlGroupIdFunction();
 
-  /** {@code GROUPING_ID} function is a synonym for {@code GROUPING}.
-   *
+  /**
+   * {@code GROUPING_ID} function is a synonym for {@code GROUPING}.
    * <p>Some history. The {@code GROUPING} function is in the SQL standard,
    * and originally supported only one argument. {@code GROUPING_ID} is not
    * standard (though supported in Oracle and SQL Server) and supports one or
    * more arguments.
-   *
    * <p>The SQL standard has changed to allow {@code GROUPING} to have multiple
    * arguments. It is now equivalent to {@code GROUPING_ID}, so we made
-   * {@code GROUPING_ID} a synonym for {@code GROUPING}. */
+   * {@code GROUPING_ID} a synonym for {@code GROUPING}.
+   */
   public static final SqlAggFunction GROUPING_ID =
       new SqlGroupingFunction("GROUPING_ID");
 
@@ -253,7 +264,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * String and array-to-array concatenation operator, '<code>||</code>'.
-   *
    * @see SqlLibraryOperators#CONCAT_FUNCTION
    */
   public static final SqlBinaryOperator CONCAT =
@@ -291,7 +301,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * Arithmetic remainder operator, '<code>%</code>',
    * an alternative to {@link #MOD} allowed if under certain conformance levels.
-   *
    * @see SqlConformance#isPercentRemainderAllowed
    */
   public static final SqlBinaryOperator PERCENT_REMAINDER =
@@ -304,13 +313,17 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
           null,
           OperandTypes.EXACT_NUMERIC_EXACT_NUMERIC);
 
-  /** The {@code RAND_INTEGER([seed, ] bound)} function, which yields a random
-   * integer, optionally with seed. */
+  /**
+   * The {@code RAND_INTEGER([seed, ] bound)} function, which yields a random
+   * integer, optionally with seed.
+   */
   public static final SqlRandIntegerFunction RAND_INTEGER =
       new SqlRandIntegerFunction();
 
-  /** The {@code RAND([seed])} function, which yields a random double,
-   * optionally with seed. */
+  /**
+   * The {@code RAND([seed])} function, which yields a random double,
+   * optionally with seed.
+   */
   public static final SqlRandFunction RAND = new SqlRandFunction();
 
   /**
@@ -430,8 +443,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   public static final SqlBinaryOperator NOT_IN =
       new SqlInOperator(SqlKind.NOT_IN);
 
-  /** Operator that tests whether its left operand is included in the range of
-   * values covered by search arguments. */
+  /**
+   * Operator that tests whether its left operand is included in the range of
+   * values covered by search arguments.
+   */
   public static final SqlInternalOperator SEARCH =
       new SqlSearchOperator();
 
@@ -478,6 +493,21 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   public static final SqlQuantifyOperator ALL_NE =
       new SqlQuantifyOperator(SqlKind.ALL, SqlKind.NOT_EQUALS);
 
+  public static final List<SqlQuantifyOperator> QUANTIFY_OPERATORS =
+      ImmutableList.of(SqlStdOperatorTable.SOME_EQ,
+      SqlStdOperatorTable.SOME_GT,
+      SqlStdOperatorTable.SOME_GE,
+      SqlStdOperatorTable.SOME_LE,
+      SqlStdOperatorTable.SOME_LT,
+      SqlStdOperatorTable.SOME_NE,
+
+      SqlStdOperatorTable.ALL_EQ,
+      SqlStdOperatorTable.ALL_GT,
+      SqlStdOperatorTable.ALL_GE,
+      SqlStdOperatorTable.ALL_LE,
+      SqlStdOperatorTable.ALL_LT,
+      SqlStdOperatorTable.ALL_NE);
+
   /**
    * Logical less-than operator, '<code>&lt;</code>'.
    */
@@ -506,7 +536,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * Infix arithmetic minus operator, '<code>-</code>'.
-   *
    * <p>Its precedence is less than the prefix {@link #UNARY_PLUS +}
    * and {@link #UNARY_MINUS -} operators.
    */
@@ -589,9 +618,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * Multiset {@code MEMBER OF}, which returns whether a element belongs to a
    * multiset.
-   *
    * <p>For example, the following returns <code>false</code>:
-   *
    * <blockquote>
    * <code>'green' MEMBER OF MULTISET ['red','almost green','blue']</code>
    * </blockquote>
@@ -602,17 +629,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * Submultiset. Checks to see if an multiset is a sub-set of another
    * multiset.
-   *
    * <p>For example, the following returns <code>false</code>:
-   *
    * <blockquote>
    * <code>MULTISET ['green'] SUBMULTISET OF
    * MULTISET['red', 'almost green', 'blue']</code>
    * </blockquote>
-   *
    * <p>The following returns <code>true</code>, in part because multisets are
    * order-independent:
-   *
    * <blockquote>
    * <code>MULTISET ['blue', 'red'] SUBMULTISET OF
    * MULTISET ['red', 'almost green', 'blue']</code>
@@ -913,7 +936,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * Prefix arithmetic minus operator, '<code>-</code>'.
-   *
    * <p>Its precedence is greater than the infix '{@link #PLUS +}' and
    * '{@link #MINUS -}' operators.
    */
@@ -928,7 +950,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * Prefix arithmetic plus operator, '<code>+</code>'.
-   *
    * <p>Its precedence is greater than the infix '{@link #PLUS +}' and
    * '{@link #MINUS -}' operators.
    */
@@ -1009,7 +1030,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    */
   public static final SqlBasicAggFunction ARG_MAX =
       SqlBasicAggFunction.create("ARG_MAX", SqlKind.ARG_MAX,
-          ReturnTypes.ARG0_NULLABLE_IF_EMPTY, OperandTypes.ANY_COMPARABLE)
+              ReturnTypes.ARG0_NULLABLE_IF_EMPTY, OperandTypes.ANY_COMPARABLE)
           .withGroupOrder(Optionality.FORBIDDEN)
           .withFunctionType(SqlFunctionCategory.SYSTEM);
 
@@ -1287,10 +1308,8 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * A special operator for the subtraction of two DATETIMEs. The format of
    * DATETIME subtraction is:
-   *
    * <blockquote><code>"(" &lt;datetime&gt; "-" &lt;datetime&gt; ")"
    * &lt;interval qualifier&gt;</code></blockquote>
-   *
    * <p>This operator is special since it needs to hold the
    * additional interval qualifier specification.</p>
    */
@@ -1360,7 +1379,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    * The "table function derived table" operator, which a table-valued
    * function into a relation, e.g. "<code>SELECT * FROM
    * TABLE(ramp(5))</code>".
-   *
    * <p>This operator has function syntax (with one argument), whereas
    * {@link #EXPLICIT_TABLE} is a prefix operator.
    */
@@ -1513,9 +1531,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The <code>OVER</code> operator, which applies an aggregate functions to a
    * {@link SqlWindow window}.
-   *
    * <p>Operands are as follows:
-   *
    * <ol>
    * <li>name of window function ({@link org.apache.calcite.sql.SqlCall})</li>
    * <li>window name ({@link org.apache.calcite.sql.SqlLiteral}) or window
@@ -1547,15 +1563,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The character substring function: <code>SUBSTRING(string FROM start [FOR
    * length])</code>.
-   *
    * <p>If the length parameter is a constant, the length of the result is the
    * minimum of the length of the input and that length. Otherwise it is the
    * length of the input.
    */
   public static final SqlFunction SUBSTRING = new SqlSubstringFunction();
 
-  /** The {@code REPLACE(string, search, replace)} function. Not standard SQL,
-   * but in Oracle and Postgres. */
+  /**
+   * The {@code REPLACE(string, search, replace)} function. Not standard SQL,
+   * but in Oracle and Postgres.
+   */
   public static final SqlFunction REPLACE =
       SqlBasicFunction.create("REPLACE", ReturnTypes.ARG0_NULLABLE_VARYING,
           OperandTypes.STRING_STRING_STRING, SqlFunctionCategory.STRING);
@@ -1566,7 +1583,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The <code>TRANSLATE(<i>char_value</i> USING <i>translation_name</i>)</code> function
    * alters the character set of a string value from one base character set to another.
-   *
    * <p>It is defined in the SQL standard. See also the non-standard
    * {@link SqlLibraryOperators#TRANSLATE3}, which has a different purpose.
    */
@@ -1620,8 +1636,8 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
           OperandTypes.CHARACTER,
           SqlFunctionCategory.STRING);
 
-  /** The {@code POWER(numeric, numeric)} function.
-   *
+  /**
+   * The {@code POWER(numeric, numeric)} function.
    * <p>The return type is always {@code DOUBLE} since we don't know
    * what the result type will be by just looking at the operand types. For
    * example {@code POWER(INTEGER, INTEGER)} can return a non-INTEGER if the
@@ -1641,15 +1657,14 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * Arithmetic remainder function {@code MOD}.
-   *
    * @see #PERCENT_REMAINDER
    */
   public static final SqlFunction MOD =
       // Return type is same as divisor (2nd operand)
       // SQL2003 Part2 Section 6.27, Syntax Rules 9
       SqlBasicFunction.create(SqlKind.MOD,
-          ReturnTypes.NULLABLE_MOD,
-          OperandTypes.EXACT_NUMERIC_EXACT_NUMERIC)
+              ReturnTypes.NULLABLE_MOD,
+              OperandTypes.EXACT_NUMERIC_EXACT_NUMERIC)
           .withFunctionType(SqlFunctionCategory.NUMERIC);
 
   /** The {@code LN(numeric)} function. */
@@ -1781,14 +1796,14 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /** The {@code PI} function. */
   public static final SqlFunction PI =
       SqlBasicFunction.create("PI", ReturnTypes.DOUBLE, OperandTypes.NILADIC,
-          SqlFunctionCategory.NUMERIC)
+              SqlFunctionCategory.NUMERIC)
           .withSyntax(SqlSyntax.FUNCTION_ID);
 
   /** {@code FIRST} function to be used within {@code MATCH_RECOGNIZE}. */
   public static final SqlFunction FIRST =
       SqlBasicFunction.create(SqlKind.FIRST,
-          ReturnTypes.ARG0_NULLABLE,
-          OperandTypes.ANY_NUMERIC)
+              ReturnTypes.ARG0_NULLABLE,
+              OperandTypes.ANY_NUMERIC)
           .withFunctionType(SqlFunctionCategory.MATCH_RECOGNIZE);
 
   /** {@code LAST} function to be used within {@code MATCH_RECOGNIZE}. */
@@ -1804,7 +1819,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /** {@code NEXT} function to be used within {@code MATCH_RECOGNIZE}. */
   public static final SqlFunction NEXT =
       SqlBasicFunction.create(SqlKind.NEXT, ReturnTypes.ARG0_NULLABLE,
-          OperandTypes.ANY_NUMERIC)
+              OperandTypes.ANY_NUMERIC)
           .withFunctionType(SqlFunctionCategory.MATCH_RECOGNIZE);
 
   /** {@code CLASSIFIER} function to be used within {@code MATCH_RECOGNIZE}. */
@@ -1815,7 +1830,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /** {@code MATCH_NUMBER} function to be used within {@code MATCH_RECOGNIZE}. */
   public static final SqlFunction MATCH_NUMBER =
       SqlBasicFunction.create(SqlKind.MATCH_NUMBER, ReturnTypes.BIGINT_NULLABLE,
-          OperandTypes.NILADIC)
+              OperandTypes.NILADIC)
           .withFunctionType(SqlFunctionCategory.MATCH_RECOGNIZE);
 
   public static final SqlFunction NULLIF = new SqlNullifFunction();
@@ -1938,23 +1953,18 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * The SQL <code>CAST</code> operator.
-   *
    * <p>The SQL syntax is
-   *
    * <blockquote><code>CAST(<i>expression</i> AS <i>type</i>)</code>
    * </blockquote>
-   *
    * <p>When the CAST operator is applies as a {@link SqlCall}, it has two
    * arguments: the expression and the type. The type must not include a
    * constraint, so <code>CAST(x AS INTEGER NOT NULL)</code>, for instance, is
    * invalid.</p>
-   *
    * <p>When the CAST operator is applied as a <code>RexCall</code>, the
    * target type is simply stored as the return type, not an explicit operand.
    * For example, the expression <code>CAST(1 + 2 AS DOUBLE)</code> will
    * become a call to <code>CAST</code> with the expression <code>1 + 2</code>
    * as its only operand.</p>
-   *
    * <p>The <code>RexCall</code> form can also have a type which contains a
    * <code>NOT NULL</code> constraint. When this expression is implemented, if
    * the value is NULL, an exception will be thrown.</p>
@@ -2079,12 +2089,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    * The item operator {@code [ ... ]}, used to access a given element of an
    * array, map or struct. For example, {@code myArray[3]}, {@code "myMap['foo']"},
    * {@code myStruct[2]} or {@code myStruct['fieldName']}.
-   *
    * <p>The SQL standard calls the ARRAY variant a
    * &lt;array element reference&gt;. Index is 1-based. The standard says
    * to raise "data exception - array element error" but we currently return
    * null.</p>
-   *
    * <p>MAP is not standard SQL.</p>
    */
   public static final SqlOperator ITEM = new SqlItemOperator();
@@ -2105,7 +2113,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The internal "$SLICE" operator takes a multiset of records and returns a
    * multiset of the first column of those records.
-   *
    * <p>It is introduced when multisets of scalar types are created, in order
    * to keep types consistent. For example, <code>MULTISET [5]</code> has type
    * <code>INTEGER MULTISET</code> but is translated to an expression of type
@@ -2113,7 +2120,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    * representation of multisets, every element must be a record. Applying the
    * "$SLICE" operator to this result converts the type back to an <code>
    * INTEGER MULTISET</code> multiset value.
-   *
    * <p><code>$SLICE</code> is often translated away when the multiset type is
    * converted back to scalar values.
    */
@@ -2131,13 +2137,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The internal "$ELEMENT_SLICE" operator returns the first field of the
    * only element of a multiset.
-   *
    * <p>It is introduced when multisets of scalar types are created, in order
    * to keep types consistent. For example, <code>ELEMENT(MULTISET [5])</code>
    * is translated to <code>$ELEMENT_SLICE(MULTISET (VALUES ROW (5
    * EXPR$0))</code> It is translated away when the multiset type is converted
    * back to scalar values.</p>
-   *
    * <p>NOTE: jhyde, 2006/1/9: Usages of this operator are commented out, but
    * I'm not deleting the operator, because some multiset tests are disabled,
    * and we may need this operator to get them working!</p>
@@ -2193,7 +2197,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /**
    * The internal {@code $STRUCT_ACCESS} operator is used to access a
    * field of a record.
-   *
    * <p>In contrast with {@link #DOT} operator, it never appears in an
    * {@link SqlNode} tree and allows to access fields by position and
    * not by name.
@@ -2216,12 +2219,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   public static final SqlAggFunction COLLECT =
       SqlBasicAggFunction
           .create(SqlKind.COLLECT, ReturnTypes.TO_MULTISET, OperandTypes.ANY)
-      .withFunctionType(SqlFunctionCategory.SYSTEM)
-      .withGroupOrder(Optionality.OPTIONAL);
+          .withFunctionType(SqlFunctionCategory.SYSTEM)
+          .withGroupOrder(Optionality.OPTIONAL);
 
   /**
    * {@code PERCENTILE_CONT} inverse distribution aggregate function.
-   *
    * <p>The argument must be a numeric literal in the range 0 to 1 inclusive
    * (representing a percentage), and the return type is the type of the
    * {@code ORDER BY} expression.
@@ -2236,7 +2238,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   /**
    * {@code PERCENTILE_DISC} inverse distribution aggregate function.
-   *
    * <p>The argument must be a numeric literal in the range 0 to 1 inclusive
    * (representing a percentage), and the return type is the type of the
    * {@code ORDER BY} expression.
@@ -2275,16 +2276,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   public static final SqlOperator NEXT_VALUE =
       new SqlSequenceValueOperator(SqlKind.NEXT_VALUE);
 
-  /** The sequence current value function: <code>CURRENT VALUE FOR
-   * sequence</code>. */
+  /**
+   * The sequence current value function: <code>CURRENT VALUE FOR
+   * sequence</code>.
+   */
   public static final SqlOperator CURRENT_VALUE =
       new SqlSequenceValueOperator(SqlKind.CURRENT_VALUE);
 
   /**
    * The <code>TABLESAMPLE</code> operator.
-   *
    * <p>Examples:
-   *
    * <ul>
    * <li><code>&lt;query&gt; TABLESAMPLE SUBSTITUTE('sampleName')</code>
    * (non-standard)
@@ -2295,7 +2296,6 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
    * [REPEATABLE(&lt;seed&gt;)]</code> (standard, but not implemented for FTRS
    * yet)
    * </ul>
-   *
    * <p>Operand #0 is a query or table; Operand #1 is a {@link SqlSampleSpec}
    * wrapped in a {@link SqlLiteral}.
    */
@@ -2331,15 +2331,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
   /** SESSION as a table function. */
   public static final SqlFunction SESSION = new SqlSessionTableFunction();
 
-  /** The {@code TUMBLE} group function.
-   *
+  /**
+   * The {@code TUMBLE} group function.
    * <p>This operator is named "$TUMBLE" (not "TUMBLE") because it is created
    * directly by the parser, not by looking up an operator by name.
-   *
    * <p>Why did we add TUMBLE to the parser? Because we plan to support TUMBLE
    * as a table function (see [CALCITE-3272]); "TUMBLE" as a name will only be
    * used by the TUMBLE table function.
-   *
    * <p>After the TUMBLE table function is introduced, we plan to deprecate
    * this TUMBLE group function, and in fact all group functions. See
    * [CALCITE-3340] for details.
@@ -2355,13 +2353,17 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
         }
       };
 
-  /** The {@code TUMBLE_START} auxiliary function of
-   * the {@code TUMBLE} group function. */
+  /**
+   * The {@code TUMBLE_START} auxiliary function of
+   * the {@code TUMBLE} group function.
+   */
   public static final SqlGroupedWindowFunction TUMBLE_START =
       TUMBLE_OLD.auxiliary(SqlKind.TUMBLE_START);
 
-  /** The {@code TUMBLE_END} auxiliary function of
-   * the {@code TUMBLE} group function. */
+  /**
+   * The {@code TUMBLE_END} auxiliary function of
+   * the {@code TUMBLE} group function.
+   */
   public static final SqlGroupedWindowFunction TUMBLE_END =
       TUMBLE_OLD.auxiliary(SqlKind.TUMBLE_END);
 
@@ -2377,13 +2379,17 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
         }
       };
 
-  /** The {@code HOP_START} auxiliary function of
-   * the {@code HOP} group function. */
+  /**
+   * The {@code HOP_START} auxiliary function of
+   * the {@code HOP} group function.
+   */
   public static final SqlGroupedWindowFunction HOP_START =
       HOP_OLD.auxiliary(SqlKind.HOP_START);
 
-  /** The {@code HOP_END} auxiliary function of
-   * the {@code HOP} group function. */
+  /**
+   * The {@code HOP_END} auxiliary function of
+   * the {@code HOP} group function.
+   */
   public static final SqlGroupedWindowFunction HOP_END =
       HOP_OLD.auxiliary(SqlKind.HOP_END);
 
@@ -2399,35 +2405,42 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
         }
       };
 
-  /** The {@code SESSION_START} auxiliary function of
-   * the {@code SESSION} group function. */
+  /**
+   * The {@code SESSION_START} auxiliary function of
+   * the {@code SESSION} group function.
+   */
   public static final SqlGroupedWindowFunction SESSION_START =
       SESSION_OLD.auxiliary(SqlKind.SESSION_START);
 
-  /** The {@code SESSION_END} auxiliary function of
-   * the {@code SESSION} group function. */
+  /**
+   * The {@code SESSION_END} auxiliary function of
+   * the {@code SESSION} group function.
+   */
   public static final SqlGroupedWindowFunction SESSION_END =
       SESSION_OLD.auxiliary(SqlKind.SESSION_END);
 
-  /** {@code |} operator to create alternate patterns
+  /**
+   * {@code |} operator to create alternate patterns
    * within {@code MATCH_RECOGNIZE}.
-   *
    * <p>If {@code p1} and {@code p2} are patterns then {@code p1 | p2} is a
-   * pattern that matches {@code p1} or {@code p2}. */
+   * pattern that matches {@code p1} or {@code p2}.
+   */
   public static final SqlBinaryOperator PATTERN_ALTER =
       new SqlBinaryOperator("|", SqlKind.PATTERN_ALTER, 70, true, null, null, null);
 
-  /** Operator to concatenate patterns within {@code MATCH_RECOGNIZE}.
-   *
+  /**
+   * Operator to concatenate patterns within {@code MATCH_RECOGNIZE}.
    * <p>If {@code p1} and {@code p2} are patterns then {@code p1 p2} is a
-   * pattern that matches {@code p1} followed by {@code p2}. */
+   * pattern that matches {@code p1} followed by {@code p2}.
+   */
   public static final SqlBinaryOperator PATTERN_CONCAT =
       new SqlBinaryOperator("", SqlKind.PATTERN_CONCAT, 80, true, null, null, null);
 
-  /** Operator to quantify patterns within {@code MATCH_RECOGNIZE}.
-   *
+  /**
+   * Operator to quantify patterns within {@code MATCH_RECOGNIZE}.
    * <p>If {@code p} is a pattern then {@code p{3, 5}} is a
-   * pattern that matches between 3 and 5 occurrences of {@code p}. */
+   * pattern that matches between 3 and 5 occurrences of {@code p}.
+   */
   public static final SqlSpecialOperator PATTERN_QUANTIFIER =
       new SqlSpecialOperator("PATTERN_QUANTIFIER", SqlKind.PATTERN_QUANTIFIER,
           90) {
@@ -2465,12 +2478,13 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
         }
       };
 
-  /** {@code PERMUTE} operator to combine patterns within
+  /**
+   * {@code PERMUTE} operator to combine patterns within
    * {@code MATCH_RECOGNIZE}.
-   *
    * <p>If {@code p1} and {@code p2} are patterns then {@code PERMUTE (p1, p2)}
    * is a pattern that matches all permutations of {@code p1} and
-   * {@code p2}. */
+   * {@code p2}.
+   */
   public static final SqlSpecialOperator PATTERN_PERMUTE =
       new SqlSpecialOperator("PATTERN_PERMUTE", SqlKind.PATTERN_PERMUTE, 100) {
         @Override public void unparse(SqlWriter writer, SqlCall call,
@@ -2488,10 +2502,11 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
         }
       };
 
-  /** {@code EXCLUDE} operator within {@code MATCH_RECOGNIZE}.
-   *
+  /**
+   * {@code EXCLUDE} operator within {@code MATCH_RECOGNIZE}.
    * <p>If {@code p} is a pattern then {@code {- p -} }} is a
-   * pattern that excludes {@code p} from the output. */
+   * pattern that excludes {@code p} from the output.
+   */
   public static final SqlSpecialOperator PATTERN_EXCLUDE =
       new SqlSpecialOperator("PATTERN_EXCLUDE", SqlKind.PATTERN_EXCLUDED,
           100) {
@@ -2523,8 +2538,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
     return instance;
   }
 
-  /** Returns the group function for which a given kind is an auxiliary
-   * function, or null if it is not an auxiliary function. */
+  /**
+   * Returns the group function for which a given kind is an auxiliary
+   * function, or null if it is not an auxiliary function.
+   */
   public static @Nullable SqlGroupedWindowFunction auxiliaryToGroup(SqlKind kind) {
     switch (kind) {
     case TUMBLE_START:
@@ -2541,11 +2558,12 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
     }
   }
 
-  /** Converts a call to a grouped auxiliary function
+  /**
+   * Converts a call to a grouped auxiliary function
    * to a call to the grouped window function. For other calls returns null.
-   *
    * <p>For example, converts {@code TUMBLE_START(rowtime, INTERVAL '1' HOUR))}
-   * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}. */
+   * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}.
+   */
   public static @Nullable SqlCall convertAuxiliaryToGroupCall(SqlCall call) {
     final SqlOperator op = call.getOperator();
     if (op instanceof SqlGroupedWindowFunction
@@ -2556,11 +2574,12 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
     return null;
   }
 
-  /** Converts a call to a grouped window function to a call to its auxiliary
+  /**
+   * Converts a call to a grouped window function to a call to its auxiliary
    * window function(s). For other calls returns null.
-   *
    * <p>For example, converts {@code TUMBLE_START(rowtime, INTERVAL '1' HOUR))}
-   * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}. */
+   * to {@code TUMBLE(rowtime, INTERVAL '1' HOUR))}.
+   */
   public static List<Pair<SqlNode, AuxiliaryConverter>> convertGroupToAuxiliaryCalls(
       SqlCall call) {
     final SqlOperator op = call.getOperator();
@@ -2625,11 +2644,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
     }
   }
 
-  /** Returns the binary operator that corresponds to this operator but in the opposite
+  /**
+   * Returns the binary operator that corresponds to this operator but in the opposite
    * direction. Or returns this, if its kind is not reversible.
-   *
    * <p>For example, {@code reverse(GREATER_THAN)} returns {@link #LESS_THAN}.
-   *
    * @deprecated Use {@link SqlOperator#reverse()}, but beware that it has
    * slightly different semantics
    */
@@ -2649,8 +2667,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
     }
   }
 
-  /** Returns the operator for {@code LIKE} with given case-sensitivity,
-   * optionally negated. */
+  /**
+   * Returns the operator for {@code LIKE} with given case-sensitivity,
+   * optionally negated.
+   */
   public static SqlOperator like(boolean negated, boolean caseSensitive) {
     if (negated) {
       if (caseSensitive) {
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index 581fa48a82..007533001b 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -225,7 +225,6 @@ import static java.util.Objects.requireNonNull;
  * Converts a SQL parse tree (consisting of
  * {@link org.apache.calcite.sql.SqlNode} objects) into a relational algebra
  * expression (consisting of {@link org.apache.calcite.rel.RelNode} objects).
- *
  * <p>The public entry points are: {@link #convertQuery},
  * {@link #convertExpression(SqlNode)}.
  */
@@ -245,8 +244,10 @@ public class SqlToRelConverter {
   protected static final Logger SQL2REL_LOGGER =
       CalciteTrace.getSqlToRelTracer();
 
-  /** Size of the smallest IN list that will be converted to a semijoin to a
-   * static table. */
+  /**
+   * Size of the smallest IN list that will be converted to a semijoin to a
+   * static table.
+   */
   public static final int DEFAULT_IN_SUB_QUERY_THRESHOLD = 20;
 
   @Deprecated // to be removed before 2.0
@@ -293,9 +294,9 @@ public class SqlToRelConverter {
   public final RelOptTable.ViewExpander viewExpander;
 
   //~ Constructors -----------------------------------------------------------
+
   /**
    * Creates a converter.
-   *
    * @param viewExpander    Preparing statement
    * @param validator       Validator
    * @param catalogReader   Schema
@@ -388,7 +389,6 @@ public class SqlToRelConverter {
   /**
    * Returns the number of dynamic parameters encountered during translation;
    * this must only be called after {@link #convertQuery}.
-   *
    * @return number of dynamic parameters
    */
   public int getDynamicParamCount() {
@@ -397,7 +397,6 @@ public class SqlToRelConverter {
 
   /**
    * Returns the type inferred for a dynamic parameter.
-   *
    * @param index 0-based index of dynamic parameter
    * @return inferred type, never null
    */
@@ -412,7 +411,6 @@ public class SqlToRelConverter {
   /**
    * Returns the current count of the number of dynamic parameters in an
    * EXPLAIN PLAN statement.
-   *
    * @param increment if true, increment the count
    * @return the current count before the optional increment
    */
@@ -424,8 +422,10 @@ public class SqlToRelConverter {
     return retVal;
   }
 
-  /** Returns the mapping of non-correlated sub-queries that have been converted
-   * to the constants that they evaluate to. */
+  /**
+   * Returns the mapping of non-correlated sub-queries that have been converted
+   * to the constants that they evaluate to.
+   */
   public Map<SqlNode, RexNode> getMapConvertedNonCorrSubqs() {
     return mapConvertedNonCorrSubqs;
   }
@@ -434,7 +434,6 @@ public class SqlToRelConverter {
    * Adds to the current map of non-correlated converted sub-queries the
    * elements from another map that contains non-correlated sub-queries that
    * have been converted by another SqlToRelConverter.
-   *
    * @param alreadyConvertedNonCorrSubqs the other map
    */
   public void addConvertedNonCorrSubqs(
@@ -445,7 +444,6 @@ public class SqlToRelConverter {
   /**
    * Sets a new SubQueryConverter. To have any effect, this must be called
    * before any convert method.
-   *
    * @param converter new SubQueryConverter
    */
   public void setSubQueryConverter(SubQueryConverter converter) {
@@ -455,7 +453,6 @@ public class SqlToRelConverter {
   /**
    * Sets the number of dynamic parameters in the current EXPLAIN PLAN
    * statement.
-   *
    * @param explainParamCount number of dynamic parameters in the statement
    */
   public void setDynamicParamCountInExplain(int explainParamCount) {
@@ -510,7 +507,6 @@ public class SqlToRelConverter {
   /**
    * If sub-query is correlated and decorrelation is enabled, performs
    * decorrelation.
-   *
    * @param query   Query
    * @param rootRel Root relational expression
    * @return New root relational expression after decorrelation
@@ -530,18 +526,15 @@ public class SqlToRelConverter {
    * Walks over a tree of relational expressions, replacing each
    * {@link RelNode} with a 'slimmed down' relational expression that projects
    * only the fields required by its consumer.
-   *
    * <p>This may make things easier for the optimizer, by removing crud that
    * would expand the search space, but is difficult for the optimizer itself
    * to do it, because optimizer rules must preserve the number and type of
    * fields. Hence, this transform that operates on the entire tree, similar
    * to the {@link RelStructuredTypeFlattener type-flattening transform}.
-   *
    * <p>Currently this functionality is disabled in farrago/luciddb; the
    * default implementation of this method does nothing.
-   *
    * @param ordered Whether the relational expression must produce results in
-   * a particular order (typically because it has an ORDER BY at top level)
+   *                a particular order (typically because it has an ORDER BY at top level)
    * @param rootRel Relational expression that is at the root of the tree
    * @return Trimmed relational expression
    */
@@ -571,7 +564,6 @@ public class SqlToRelConverter {
 
   /**
    * Creates a RelFieldTrimmer.
-   *
    * @return Field trimmer
    */
   protected RelFieldTrimmer newFieldTrimmer() {
@@ -580,7 +572,6 @@ public class SqlToRelConverter {
 
   /**
    * Converts an unvalidated query's parse tree into a relational expression.
-   *
    * @param query           Query to convert
    * @param needsValidation Whether to validate the query before converting;
    *                        <code>false</code> if the query has already been
@@ -779,6 +770,7 @@ public class SqlToRelConverter {
           .accept(
               new RelShuttleImpl() {
                 boolean attached = false;
+
                 @Override public RelNode visitChild(RelNode parent, int i, RelNode child) {
                   if (parent instanceof Hintable && !attached) {
                     attached = true;
@@ -796,12 +788,10 @@ public class SqlToRelConverter {
   /**
    * Having translated 'SELECT ... FROM ... [GROUP BY ...] [HAVING ...]', adds
    * a relational expression to make the results unique.
-   *
    * <p>If the SELECT clause contains duplicate expressions, adds
    * {@link org.apache.calcite.rel.logical.LogicalProject}s so that we are
    * grouping on the minimal set of keys. The performance gain isn't huge, but
    * it is difficult to detect these duplicate expressions later.
-   *
    * @param bb               Blackboard
    * @param checkForDupExprs Check for duplicate expressions
    */
@@ -887,10 +877,8 @@ public class SqlToRelConverter {
 
   /**
    * Converts a query's ORDER BY clause, if any.
-   *
    * <p>Ignores the ORDER BY clause if the query is not top-level and FETCH or
    * OFFSET are not present.
-   *
    * @param select        Query
    * @param bb            Blackboard
    * @param collation     Collation list
@@ -912,8 +900,8 @@ public class SqlToRelConverter {
         || select.getOrderList().isEmpty()) {
       assert removeSortInSubQuery(bb.top) || collation.getFieldCollations().isEmpty();
       if ((offset == null
-            || (offset instanceof SqlLiteral
-                && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
+          || (offset instanceof SqlLiteral
+          && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
           && fetch == null) {
         return;
       }
@@ -951,7 +939,6 @@ public class SqlToRelConverter {
 
   /**
    * Returns whether we should remove the sort for the subsequent query conversion.
-   *
    * @param top Whether the rel to convert is the root of the query
    */
   private boolean removeSortInSubQuery(boolean top) {
@@ -960,7 +947,6 @@ public class SqlToRelConverter {
 
   /**
    * Returns whether a given node contains a {@link SqlInOperator}.
-   *
    * @param node a RexNode tree
    */
   private static boolean containsInOperator(
@@ -985,8 +971,7 @@ public class SqlToRelConverter {
 
   /**
    * Push down all the NOT logical operators into any IN/NOT IN operators.
-   *
-   * @param scope Scope where {@code sqlNode} occurs
+   * @param scope   Scope where {@code sqlNode} occurs
    * @param sqlNode the root node from which to look for NOT operators
    * @return the transformed SqlNode representation with NOT pushed down.
    */
@@ -1072,8 +1057,8 @@ public class SqlToRelConverter {
 
       case NOT_IN:
         return reg(scope,
-           SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO,
-               call.getOperandList()));
+            SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO,
+                call.getOperandList()));
 
       case IN:
         return reg(scope,
@@ -1089,8 +1074,10 @@ public class SqlToRelConverter {
     return sqlNode;
   }
 
-  /** Registers with the validator a {@link SqlNode} that has been created
-   * during the Sql-to-Rel process. */
+  /**
+   * Registers with the validator a {@link SqlNode} that has been created
+   * during the Sql-to-Rel process.
+   */
   private static SqlNode reg(SqlValidatorScope scope, SqlNode e) {
     scope.getValidator().deriveType(scope, e);
     return e;
@@ -1098,7 +1085,6 @@ public class SqlToRelConverter {
 
   /**
    * Converts a WHERE clause.
-   *
    * @param bb    Blackboard
    * @param where WHERE clause, may be null
    */
@@ -1190,6 +1176,7 @@ public class SqlToRelConverter {
     case ALL:
       call = (SqlBasicCall) subQuery.node;
       query = call.operand(1);
+
       if (!config.isExpand() && !(query instanceof SqlNodeList)) {
         return;
       }
@@ -1463,9 +1450,8 @@ public class SqlToRelConverter {
    * Note: The ORDER BY clause for input table parameter differs from the
    * ORDER BY clause in some other contexts in that only columns may be sorted
    * (not arbitrary expressions).
-   *
-   * @param bb              Scope within which to resolve identifiers
-   * @param orderList       Order by clause, may be null
+   * @param bb        Scope within which to resolve identifiers
+   * @param orderList Order by clause, may be null
    * @return ordering of input table
    */
   private RelCollation buildCollation(Blackboard bb, SqlNodeList orderList) {
@@ -1628,7 +1614,6 @@ public class SqlToRelConverter {
   /**
    * Determines if a sub-query is non-correlated and if so, converts it to a
    * constant.
-   *
    * @param subQuery  the call that references the sub-query
    * @param bb        blackboard used to convert the sub-query
    * @param converted RelNode tree corresponding to the sub-query
@@ -1667,9 +1652,8 @@ public class SqlToRelConverter {
   /**
    * Converts the RelNode tree for a select statement to a select that
    * produces a single value.
-   *
    * @param query the query
-   * @param plan   the original RelNode tree corresponding to the statement
+   * @param plan  the original RelNode tree corresponding to the statement
    * @return the converted RelNode tree
    */
   public RelNode convertToSingleValueSubq(
@@ -1708,7 +1692,7 @@ public class SqlToRelConverter {
       SqlCall exprCall = (SqlCall) query;
       if (exprCall.getOperator()
           instanceof SqlValuesOperator
-              && Util.isSingleValue(exprCall)) {
+          && Util.isSingleValue(exprCall)) {
         return plan;
       }
     }
@@ -1721,7 +1705,6 @@ public class SqlToRelConverter {
 
   /**
    * Converts "x IN (1, 2, ...)" to "x=1 OR x=2 OR ...".
-   *
    * @param leftKeys   LHS
    * @param valuesList RHS
    * @param op         The operator (IN, NOT IN, &gt; SOME, ...)
@@ -1780,13 +1763,15 @@ public class SqlToRelConverter {
     }
   }
 
-  /** Ensures that an expression has a given {@link SqlTypeName}, applying a
+  /**
+   * Ensures that an expression has a given {@link SqlTypeName}, applying a
    * cast if necessary. If the expression already has the right type family,
-   * returns the expression unchanged. */
+   * returns the expression unchanged.
+   */
   private RexNode ensureSqlType(RelDataType type, RexNode node) {
     if (type.getSqlTypeName() == node.getType().getSqlTypeName()
         || (type.getSqlTypeName() == SqlTypeName.VARCHAR
-            && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
+        && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
       return node;
     }
     return rexBuilder.ensureType(type, node, true);
@@ -1799,7 +1784,6 @@ public class SqlToRelConverter {
    * ({@link org.apache.calcite.rel.logical.LogicalValues}) rather than a
    * predicate. A threshold of 0 forces usage of an inline table in all cases; a
    * threshold of Integer.MAX_VALUE forces usage of OR in all cases
-   *
    * @return threshold, default {@link #DEFAULT_IN_SUB_QUERY_THRESHOLD}
    */
   @Deprecated // to be removed before 2.0
@@ -1813,14 +1797,13 @@ public class SqlToRelConverter {
    * which outer joins that indicator to the original query. After performing
    * the outer join, the condition will be TRUE if the EXISTS condition holds,
    * NULL otherwise.
-   *
-   * @param seek           A query, for example 'select * from emp' or
-   *                       'values (1,2,3)' or '('Foo', 34)'.
-   * @param subQueryType   Whether sub-query is IN, EXISTS or scalar
-   * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
-   *     FALSE, UNKNOWN) will be required, or whether we can accept an
-   *     approximation (say representing UNKNOWN as FALSE)
-   * @param notIn Whether the operation is NOT IN
+   * @param seek         A query, for example 'select * from emp' or
+   *                     'values (1,2,3)' or '('Foo', 34)'.
+   * @param subQueryType Whether sub-query is IN, EXISTS or scalar
+   * @param logic        Whether the answer needs to be in full 3-valued logic (TRUE,
+   *                     FALSE, UNKNOWN) will be required, or whether we can accept an
+   *                     approximation (say representing UNKNOWN as FALSE)
+   * @param notIn        Whether the operation is NOT IN
    * @return join expression
    */
   private RelOptUtil.Exists convertExists(
@@ -1881,7 +1864,7 @@ public class SqlToRelConverter {
     final RelDataType rowType;
     if (targetRowType != null) {
       rowType =
-              SqlTypeUtil.keepSourceTypeAndTargetNullability(targetRowType, listType, typeFactory);
+          SqlTypeUtil.keepSourceTypeAndTargetNullability(targetRowType, listType, typeFactory);
     } else {
       rowType = SqlTypeUtil.promoteToRowType(typeFactory, listType, null);
     }
@@ -2023,17 +2006,16 @@ public class SqlToRelConverter {
   /**
    * Builds a list of all <code>IN</code> or <code>EXISTS</code> operators
    * inside SQL parse tree. Does not traverse inside queries.
-   *
    * @param bb                           blackboard
    * @param node                         the SQL parse tree
-   * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
-   *              FALSE, UNKNOWN) will be required, or whether we can accept
-   *              an approximation (say representing UNKNOWN as FALSE)
+   * @param logic                        Whether the answer needs to be in full 3-valued logic (TRUE,
+   *                                     FALSE, UNKNOWN) will be required, or whether we can accept
+   *                                     an approximation (say representing UNKNOWN as FALSE)
    * @param registerOnlyScalarSubQueries if set to true and the parse tree
    *                                     corresponds to a variation of a select
    *                                     node, only register it if it's a scalar
    *                                     sub-query
-   * @param clause A clause inside which sub-query is searched
+   * @param clause                       A clause inside which sub-query is searched
    */
   private void findSubQueries(
       Blackboard bb,
@@ -2124,6 +2106,13 @@ public class SqlToRelConverter {
       default:
         break;
       }
+      if (node instanceof SqlBasicCall && ((SqlCall) node).getOperator() instanceof SqlQuantifyOperator &&
+          ((SqlQuantifyOperator) ((SqlCall) node).getOperator())
+              .tryDeriveTypeForCollection(bb.getValidator(), bb.scope(), (SqlCall) node) != null) {
+        findSubQueries(bb, ((SqlCall) node).operand(0), logic, registerOnlyScalarSubQueries, clause);
+        findSubQueries(bb, ((SqlCall) node).operand(1), logic, registerOnlyScalarSubQueries, clause);
+        break;
+      }
       bb.registerSubQuery(node, logic, clause);
       break;
     default:
@@ -2133,7 +2122,6 @@ public class SqlToRelConverter {
 
   /**
    * Converts an expression from {@link SqlNode} to {@link RexNode} format.
-   *
    * @param node Expression to translate
    * @return Converted expression
    */
@@ -2150,7 +2138,6 @@ public class SqlToRelConverter {
   /**
    * Converts an expression from {@link SqlNode} to {@link RexNode} format,
    * mapping identifier references to predefined expressions.
-   *
    * @param node          Expression to translate
    * @param nameToNodeMap map from String to {@link RexNode}; when an
    *                      {@link SqlIdentifier} is encountered, it is used as a
@@ -2174,11 +2161,9 @@ public class SqlToRelConverter {
 
   /**
    * Converts a non-standard expression.
-   *
    * <p>This method is an extension-point that derived classes can override. If
    * this method returns a null result, the normal expression translation
    * process will proceed. The default implementation always returns null.
-   *
    * @param node Expression
    * @param bb   Blackboard
    * @return null to proceed with the usual expression translation process
@@ -2302,20 +2287,18 @@ public class SqlToRelConverter {
 
   /**
    * Converts a FROM clause into a relational expression.
-   *
-   * @param bb   Scope within which to resolve identifiers
-   * @param from FROM clause of a query. Examples include:
-   *
-   *             <ul>
-   *             <li>a single table ("SALES.EMP"),
-   *             <li>an aliased table ("EMP AS E"),
-   *             <li>a list of tables ("EMP, DEPT"),
-   *             <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
-   *             DEPT.DEPTNO"),
-   *             <li>a VALUES clause ("VALUES ('Fred', 20)"),
-   *             <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
-   *             <li>or any combination of the above.
-   *             </ul>
+   * @param bb         Scope within which to resolve identifiers
+   * @param from       FROM clause of a query. Examples include:
+   *                   <ul>
+   *                   <li>a single table ("SALES.EMP"),
+   *                   <li>an aliased table ("EMP AS E"),
+   *                   <li>a list of tables ("EMP, DEPT"),
+   *                   <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
+   *                   DEPT.DEPTNO"),
+   *                   <li>a VALUES clause ("VALUES ('Fred', 20)"),
+   *                   <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
+   *                   <li>or any combination of the above.
+   *                   </ul>
    * @param fieldNames Field aliases, usually come from AS clause, or null
    */
   protected void convertFrom(
@@ -2538,7 +2521,7 @@ public class SqlToRelConverter {
               newOperands.add(arg);
             }
             return rexBuilder.makeCall(
-              validator().getUnknownType(), call.getOperator(), newOperands);
+                validator().getUnknownType(), call.getOperator(), newOperands);
           }
 
           @Override public RexNode visit(SqlIdentifier id) {
@@ -2736,7 +2719,7 @@ public class SqlToRelConverter {
     final List<String> measureNames = unpivot.measureList.stream()
         .map(node -> ((SqlIdentifier) node).getSimple())
         .collect(Util.toImmutableList());
-    final List<String> axisNames =  unpivot.axisList.stream()
+    final List<String> axisNames = unpivot.axisList.stream()
         .map(node -> ((SqlIdentifier) node).getSimple())
         .collect(Util.toImmutableList());
     final ImmutableList.Builder<Pair<List<RexLiteral>, List<RexNode>>> axisMap =
@@ -2907,10 +2890,12 @@ public class SqlToRelConverter {
     }
   }
 
-  /** Shuttle that replace outer {@link RexInputRef} with
+  /**
+   * Shuttle that replace outer {@link RexInputRef} with
    * {@link RexFieldAccess}, and adjust {@code offset} to
    * each inner {@link RexInputRef} in the lateral join
-   * condition. */
+   * condition.
+   */
   private static class RexAccessShuttle extends RexShuttle {
     private final RexBuilder builder;
     private final RexCorrelVariable rexCorrel;
@@ -3107,7 +3092,6 @@ public class SqlToRelConverter {
    * non-correlated sub-query can contain correlated references, provided those
    * references do not reference select statements that are parents of the
    * sub-query.
-   *
    * @param subq the sub-query
    * @param bb   blackboard used while converting the sub-query, i.e., the
    *             blackboard of the parent query of this sub-query
@@ -3149,7 +3133,6 @@ public class SqlToRelConverter {
 
   /**
    * Returns a list of fields to be prefixed to each relational expression.
-   *
    * @return List of system fields
    */
   protected List<RelDataTypeField> getSystemFields() {
@@ -3239,7 +3222,6 @@ public class SqlToRelConverter {
   /**
    * This currently does not expand correlated full outer joins correctly.  Replaying on the right
    * side to correctly support left joins multiplicities.
-   *
    * <blockquote><pre>
    *   SELECT *
    *   FROM t1
@@ -3247,16 +3229,13 @@ public class SqlToRelConverter {
    *    EXIST(SELECT t3.c3 WHERE t1.c1 = t3.c1 AND t2.c2 = t3.c2)
    *    AND NOT (t2.t2 = 2)
    * </pre></blockquote>
-   *
    * <p>Given the de-correlated query produces:
-   *
    * <blockquote><pre>
    *  t1.c1 | t2.c2
    *  ------+------
    *    1   |  1
    *    1   |  2
    * </pre></blockquote>
-   *
    * <p>If correlated query was replayed on the left side, then an extra rows would be emitted for
    * every {code t1.c1 = 1}, where it failed to join to right side due to {code NOT(t2.t2 = 2)}.
    * However, if the query is joined on the right, side multiplicity is maintained.
@@ -3277,7 +3256,7 @@ public class SqlToRelConverter {
             ? rightRel
             : bb.reRegister(rightRel);
     bb.setRoot(ImmutableList.of(leftRel, newRightRel));
-    RexNode conditionExp =  bb.convertExpression(condition);
+    RexNode conditionExp = bb.convertExpression(condition);
     if (conditionExp instanceof RexInputRef && newRightRel != rightRel) {
       int leftFieldCount = leftRel.getRowType().getFieldCount();
       List<RelDataTypeField> rightFieldList = newRightRel.getRowType().getFieldList();
@@ -3294,10 +3273,9 @@ public class SqlToRelConverter {
    * Returns an expression for matching columns of a USING clause or inferred
    * from NATURAL JOIN. "a JOIN b USING (x, y)" becomes "a.x = b.x AND a.y =
    * b.y". Returns null if the column list is empty.
-   *
-   * @param leftNamespace Namespace of left input to join
+   * @param leftNamespace  Namespace of left input to join
    * @param rightNamespace Namespace of right input to join
-   * @param nameList List of column names to join on
+   * @param nameList       List of column names to join on
    * @return Expression to match columns from name list, or true if name list
    * is empty
    */
@@ -3344,12 +3322,10 @@ public class SqlToRelConverter {
 
   /**
    * Converts the SELECT, GROUP BY and HAVING clauses of an aggregate query.
-   *
    * <p>This method extracts SELECT, GROUP BY and HAVING clauses, and creates
    * an {@link AggConverter}, then delegates to {@link #createAggImpl}.
    * Derived class may override this method to change any of those clauses or
    * specify a different {@link AggConverter}.
-   *
    * @param bb            Scope within which to resolve identifiers
    * @param select        Query
    * @param orderExprList Additional expressions needed to implement ORDER BY
@@ -3557,20 +3533,17 @@ public class SqlToRelConverter {
 
   /**
    * Creates an Aggregate.
-   *
    * <p>In case the aggregate rel changes the order in which it projects
    * fields, the <code>groupExprProjection</code> parameter is provided, and
    * the implementation of this method may modify it.
-   *
    * <p>The <code>sortedCount</code> parameter is the number of expressions
    * known to be monotonic. These expressions must be on the leading edge of
    * the grouping keys. The default implementation of this method ignores this
    * parameter.
-   *
-   * @param bb       Blackboard
-   * @param groupSet Bit set of ordinals of grouping columns
+   * @param bb        Blackboard
+   * @param groupSet  Bit set of ordinals of grouping columns
    * @param groupSets Grouping sets
-   * @param aggCalls Array of calls to aggregate functions
+   * @param aggCalls  Array of calls to aggregate functions
    * @return LogicalAggregate
    */
   protected RelNode createAggregate(Blackboard bb, ImmutableBitSet groupSet,
@@ -3604,7 +3577,6 @@ public class SqlToRelConverter {
    * Creates a list of collations required to implement the ORDER BY clause,
    * if there is one. Populates <code>extraOrderExprs</code> with any sort
    * expressions which are not in the select clause.
-   *
    * @param bb              Scope within which to resolve identifiers
    * @param select          Select clause. Never null, because we invent a
    *                        dummy SELECT if ORDER BY is applied to a set
@@ -3630,8 +3602,8 @@ public class SqlToRelConverter {
     if (removeSortInSubQuery(bb.top)) {
       SqlNode offset = select.getOffset();
       if ((offset == null
-              || (offset instanceof SqlLiteral
-                  && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
+          || (offset instanceof SqlLiteral
+          && Objects.equals(((SqlLiteral) offset).bigDecimalValue(), BigDecimal.ZERO)))
           && select.getFetch() == null) {
         return;
       }
@@ -3740,7 +3712,6 @@ public class SqlToRelConverter {
 
   /**
    * Returns whether to trim unused fields as part of the conversion process.
-   *
    * @return Whether to trim unused fields
    */
   @Deprecated // to be removed before 2.0
@@ -3750,7 +3721,6 @@ public class SqlToRelConverter {
 
   /**
    * Recursively converts a query to a relational expression.
-   *
    * @param query         Query
    * @param top           Whether this query is the top-level query of the
    *                      statement
@@ -3787,7 +3757,6 @@ public class SqlToRelConverter {
   /**
    * Converts a set operation (UNION, INTERSECT, MINUS) into relational
    * expressions.
-   *
    * @param call Call to set operator
    * @return Relational expression
    */
@@ -3854,15 +3823,15 @@ public class SqlToRelConverter {
         LogicalTableModify.Operation.INSERT, null, null, false);
   }
 
-  /** Wraps a relational expression in the projects and filters implied by
+  /**
+   * Wraps a relational expression in the projects and filters implied by
    * a {@link ModifiableView}.
-   *
    * <p>The input relational expression is suitable for inserting into the view,
    * and the returned relational expression is suitable for inserting into its
    * delegate table.
-   *
    * <p>In principle, the delegate table of a view might be another modifiable
-   * view, and if so, the process can be repeated. */
+   * view, and if so, the process can be repeated.
+   */
   private RelNode createSource(RelOptTable targetTable, RelNode source,
       ModifiableView modifiableView, RelDataType delegateRowType) {
     final ImmutableIntList mapping = modifiableView.getColumnMapping();
@@ -3967,16 +3936,13 @@ public class SqlToRelConverter {
 
   /**
    * Creates a source for an INSERT statement.
-   *
    * <p>If the column list is not specified, source expressions match target
    * columns in order.
-   *
    * <p>If the column list is specified, Source expressions are mapped to
    * target columns by name via targetColumnList, and may not cover the entire
    * target table. So, we'll make up a full row, using a combination of
    * default values and the source expressions provided.
-   *
-   * @param call      Insert expression
+   * @param call   Insert expression
    * @param source Source relational expression
    * @return Converted INSERT statement
    */
@@ -4044,8 +4010,10 @@ public class SqlToRelConverter {
         .build();
   }
 
-  /** Creates a blackboard for translating the expressions of generated columns
-   * in an INSERT statement. */
+  /**
+   * Creates a blackboard for translating the expressions of generated columns
+   * in an INSERT statement.
+   */
   private Blackboard createInsertBlackboard(RelOptTable targetTable,
       RexNode sourceRef, List<String> targetColumnNames) {
     final Map<String, RexNode> nameToNodeMap = new HashMap<>();
@@ -4099,7 +4067,6 @@ public class SqlToRelConverter {
   /**
    * Given an INSERT statement, collects the list of names to be populated and
    * the expressions to put in them.
-   *
    * @param call              Insert statement
    * @param sourceRef         Expression representing a row from the source
    *                          relational expression
@@ -4366,7 +4333,6 @@ public class SqlToRelConverter {
    * Adjusts the type of a reference to an input field to account for nulls
    * introduced by outer joins; and adjusts the offset to match the physical
    * implementation.
-   *
    * @param bb       Blackboard
    * @param inputRef Input ref
    * @return Adjusted input ref
@@ -4389,7 +4355,6 @@ public class SqlToRelConverter {
 
   /**
    * Converts a row constructor into a relational expression.
-   *
    * @param bb             Blackboard
    * @param rowConstructor Row constructor expression
    * @return Relational expression which returns a single row.
@@ -4602,7 +4567,6 @@ public class SqlToRelConverter {
    * Adds extra select items. The default implementation adds nothing; derived
    * classes may add columns to exprList, nameList, aliasList and
    * columnMonotonicityList.
-   *
    * @param bb                     Blackboard
    * @param select                 Select statement being translated
    * @param exprList               List of expressions in select clause
@@ -4628,7 +4592,7 @@ public class SqlToRelConverter {
     String alias = SqlValidatorUtil.alias(node, ordinal);
     if (aliases.contains(alias)) {
       final String aliasBase = alias;
-      for (int j = 0;; j++) {
+      for (int j = 0; ; j++) {
         alias = aliasBase + j;
         if (!aliases.contains(alias)) {
           break;
@@ -4719,9 +4683,11 @@ public class SqlToRelConverter {
     bb.setRoot(relBuilder.build(), false);
   }
 
-  /** Eliminates a common sub-expression by looking for a {@link RexNode}
+  /**
+   * Eliminates a common sub-expression by looking for a {@link RexNode}
    * in the expressions of a {@link Project}; if found, returns a refIndex
-   * instead of the raw node. */
+   * instead of the raw node.
+   */
   private static final class DuplicateEliminator extends RexShuttle {
     private final List<RexNode> projects;
 
@@ -4769,7 +4735,6 @@ public class SqlToRelConverter {
   /**
    * Converts a values clause (as in "INSERT INTO T(x,y) VALUES (1,2)") into a
    * relational expression.
-   *
    * @param bb            Blackboard
    * @param values        Call to SQL VALUES operator
    * @param targetRowType Target row type
@@ -4833,11 +4798,11 @@ public class SqlToRelConverter {
     }
   }
 
-  /** Function that can convert a sort specification (expression, direction
+  /**
+   * Function that can convert a sort specification (expression, direction
    * and null direction) to a target format.
-   *
    * @param <R> Target format, such as {@link RexFieldCollation} or
-   * {@link RexNode}
+   *            {@link RexNode}
    */
   @FunctionalInterface
   interface SortExpressionConverter<R> {
@@ -4902,7 +4867,6 @@ public class SqlToRelConverter {
 
     /**
      * Creates a Blackboard.
-     *
      * @param scope         Name-resolution scope for expressions validated
      *                      within this query. Can be null if this Blackboard is
      *                      for a leaf node, say
@@ -4938,11 +4902,10 @@ public class SqlToRelConverter {
 
     /**
      * Registers a relational expression.
-     *
-     * @param rel               Relational expression
-     * @param joinType          Join type
+     * @param rel      Relational expression
+     * @param joinType Join type
      * @param leftKeys LHS of IN clause, or null for expressions
-     *                          other than IN
+     *                 other than IN
      * @return Expression with which to refer to the row (or partial row)
      * coming from this relational expression's side of the join
      */
@@ -5056,16 +5019,14 @@ public class SqlToRelConverter {
     /**
      * Re-register the {@code registered} with given root node and
      * return the new root node.
-     *
      * @param root The given root, never leaf
-     *
      * @return new root after the registration
      */
     public RelNode reRegister(RelNode root) {
       setRoot(root, false);
       List<RegisterArgs> registerCopy = registered;
       registered = new ArrayList<>();
-      for (RegisterArgs reg: registerCopy) {
+      for (RegisterArgs reg : registerCopy) {
         RelNode relNode = reg.rel;
         relBuilder.push(relNode);
         final RelMetadataQuery mq = relBuilder.getCluster().getMetadataQuery();
@@ -5084,7 +5045,6 @@ public class SqlToRelConverter {
     /**
      * Sets a new root relational expression, as the translation process
      * backs its way further up the tree.
-     *
      * @param root New root relational expression
      * @param leaf Whether the relational expression is a leaf, that is,
      *             derived from an atomic relational expression such as a table
@@ -5118,10 +5078,8 @@ public class SqlToRelConverter {
      * Notifies this Blackboard that the root just set using
      * {@link #setRoot(RelNode, boolean)} was derived using dataset
      * substitution.
-     *
      * <p>The default implementation is not interested in such
      * notifications, and does nothing.
-     *
      * @param datasetName Dataset name
      */
     public void setDataset(@Nullable String datasetName) {
@@ -5134,7 +5092,6 @@ public class SqlToRelConverter {
     /**
      * Returns an expression with which to reference a from-list item;
      * throws if not found.
-     *
      * @param qualified The alias of the FROM item
      * @return a {@link RexFieldAccess} or {@link RexRangeRef}, never null
      */
@@ -5451,7 +5408,12 @@ public class SqlToRelConverter {
       case CURSOR:
       case IN:
       case NOT_IN:
-        subQuery = requireNonNull(getSubQuery(expr, null));
+        subQuery = getSubQuery(expr, null);
+        if (subQuery == null &&
+            (kind == SqlKind.SOME || kind == SqlKind.ALL)) {
+          break;
+        }
+        assert subQuery != null;
         rex = requireNonNull(subQuery.expr);
         return StandardConvertletTable.castToValidatedType(expr, rex,
             validator(), rexBuilder);
@@ -5517,8 +5479,10 @@ public class SqlToRelConverter {
           this::sortToRexFieldCollation);
     }
 
-    /** Handles an item in an ORDER BY clause, passing using a converter
-     * function to produce the final result. */
+    /**
+     * Handles an item in an ORDER BY clause, passing using a converter
+     * function to produce the final result.
+     */
     <R> R convertSortExpression(SqlNode expr,
         RelFieldCollation.Direction direction,
         RelFieldCollation.NullDirection nullDirection,
@@ -5604,7 +5568,6 @@ public class SqlToRelConverter {
     /**
      * Determines whether a RexNode corresponds to a sub-query that's been
      * converted to a constant.
-     *
      * @param rex the expression to be examined
      * @return true if the expression is a dynamic parameter, a literal, or
      * a literal that is being cast
@@ -5765,15 +5728,11 @@ public class SqlToRelConverter {
 
   /**
    * Converts expressions to aggregates.
-   *
    * <p>Consider the expression
-   *
    * <blockquote>
    * {@code SELECT deptno, SUM(2 * sal) FROM emp GROUP BY deptno}
    * </blockquote>
-   *
    * <p>Then:
-   *
    * <ul>
    * <li>groupExprs = {SqlIdentifier(deptno)}</li>
    * <li>convertedInputExprs = {RexInputRef(deptno), 2 *
@@ -5810,9 +5769,11 @@ public class SqlToRelConverter {
     private final List<Pair<RexNode, @Nullable String>> convertedInputExprs =
         new ArrayList<>();
 
-    /** Expressions to be evaluated as rows are being placed into the
+    /**
+     * Expressions to be evaluated as rows are being placed into the
      * aggregate's hash table. This is when group functions such as TUMBLE
-     * cause rows to be expanded. */
+     * cause rows to be expanded.
+     */
 
     private final List<AggregateCall> aggCalls = new ArrayList<>();
     private final Map<SqlNode, RexNode> aggMapping = new HashMap<>();
@@ -5829,10 +5790,8 @@ public class SqlToRelConverter {
 
     /**
      * Creates an AggConverter.
-     *
      * <p>The <code>select</code> parameter provides enough context to name
      * aggregate calls which are top-level select list items.
-     *
      * @param bb     Blackboard
      * @param select Query being translated; provides context to give
      */
@@ -5894,7 +5853,6 @@ public class SqlToRelConverter {
 
     /**
      * Adds an expression, deducing an appropriate name if possible.
-     *
      * @param expr Expression
      * @param name Suggested name
      */
@@ -6298,7 +6256,6 @@ public class SqlToRelConverter {
 
     /**
      * Creates a LookupContext with multiple input relational expressions.
-     *
      * @param bb               Context for translating this sub-query
      * @param rels             Relational expressions
      * @param systemFieldCount Number of system fields
@@ -6310,12 +6267,10 @@ public class SqlToRelConverter {
     /**
      * Returns the relational expression with a given offset, and the
      * ordinal in the combined row of its first field.
-     *
      * <p>For example, in {@code Emp JOIN Dept}, findRel(1) returns the
      * relational expression for {@code Dept} and offset 6 (because
      * {@code Emp} has 6 fields, therefore the first field of {@code Dept}
      * is field 6.
-     *
      * @param offset Offset of relational expression in FROM clause
      * @return Relational expression and the ordinal of its first field
      */
@@ -6327,27 +6282,18 @@ public class SqlToRelConverter {
   /**
    * Shuttle which walks over a tree of {@link RexNode}s and applies 'over' to
    * all agg functions.
-   *
    * <p>This is necessary because the returned expression is not necessarily a
    * call to an agg function. For example,
-   *
    * <blockquote><code>AVG(x)</code></blockquote>
-   *
    * <p>becomes
-   *
    * <blockquote><code>SUM(x) / COUNT(x)</code></blockquote>
-   *
    * <p>Any aggregate functions are converted to calls to the internal <code>
    * $Histogram</code> aggregation function and accessors such as <code>
    * $HistogramMin</code>; for example,
-   *
    * <blockquote><code>MIN(x), MAX(x)</code></blockquote>
-   *
    * <p>are converted to
-   *
    * <blockquote><code>$HistogramMin($Histogram(x)),
    * $HistogramMax($Histogram(x))</code></blockquote>
-   *
    * <p>Common sub-expression elimination will ensure that only one histogram is
    * computed.
    */
@@ -6410,9 +6356,9 @@ public class SqlToRelConverter {
           exprs.set(
               0,
               reinterpretCast
-              ? rexBuilder.makeReinterpretCast(histogramType, exprs.get(0),
+                  ? rexBuilder.makeReinterpretCast(histogramType, exprs.get(0),
                   rexBuilder.makeLiteral(false))
-              : rexBuilder.makeCast(histogramType, exprs.get(0)));
+                  : rexBuilder.makeCast(histogramType, exprs.get(0)));
         }
 
         RexNode over =
@@ -6474,11 +6420,9 @@ public class SqlToRelConverter {
     /**
      * Returns the histogram operator corresponding to a given aggregate
      * function.
-     *
      * <p>For example, <code>getHistogramOp
-     *({@link SqlStdOperatorTable#MIN}}</code> returns
+     * ({@link SqlStdOperatorTable#MIN}}</code> returns
      * {@link SqlStdOperatorTable#HISTOGRAM_MIN}.
-     *
      * @param aggFunction An aggregate function
      * @return Its histogram function, or null
      */
@@ -6513,8 +6457,10 @@ public class SqlToRelConverter {
     }
   }
 
-  /** A sub-query, whether it needs to be translated using 2- or 3-valued
-   * logic. */
+  /**
+   * A sub-query, whether it needs to be translated using 2- or 3-valued
+   * logic.
+   */
   private static class SubQuery {
     final SqlNode node;
     final RelOptUtil.Logic logic;
@@ -6623,8 +6569,10 @@ public class SqlToRelConverter {
     }
   }
 
-  /** Use of a row as a correlating variable by a given relational
-   * expression. */
+  /**
+   * Use of a row as a correlating variable by a given relational
+   * expression.
+   */
   private static class CorrelationUse {
     private final CorrelationId id;
     private final ImmutableBitSet requiredColumns;
@@ -6647,14 +6595,15 @@ public class SqlToRelConverter {
   /**
    * Interface to define the configuration for a SqlToRelConverter.
    * Provides methods to set each configuration option.
-   *
    * @see SqlToRelConverter#CONFIG
    */
   @Value.Immutable(singleton = false)
   public interface Config {
-    /** Returns the {@code decorrelationEnabled} option. Controls whether to
+    /**
+     * Returns the {@code decorrelationEnabled} option. Controls whether to
      * disable sub-query decorrelation when needed. e.g. if outer joins are not
-     * supported. */
+     * supported.
+     */
     @Value.Default default boolean isDecorrelationEnabled() {
       return true;
     }
@@ -6662,8 +6611,10 @@ public class SqlToRelConverter {
     /** Sets {@link #isDecorrelationEnabled()}. */
     Config withDecorrelationEnabled(boolean decorrelationEnabled);
 
-    /** Returns the {@code trimUnusedFields} option. Controls whether to trim
-     * unused fields as part of the conversion process. */
+    /**
+     * Returns the {@code trimUnusedFields} option. Controls whether to trim
+     * unused fields as part of the conversion process.
+     */
     @Value.Default default boolean isTrimUnusedFields() {
       return false;
     }
@@ -6671,9 +6622,11 @@ public class SqlToRelConverter {
     /** Sets {@link #isTrimUnusedFields()}. */
     Config withTrimUnusedFields(boolean trimUnusedFields);
 
-    /** Returns the {@code createValuesRel} option. Controls whether instances
+    /**
+     * Returns the {@code createValuesRel} option. Controls whether instances
      * of {@link org.apache.calcite.rel.logical.LogicalValues} are generated.
-     * These may not be supported by all physical implementations. */
+     * These may not be supported by all physical implementations.
+     */
     @Value.Default default boolean isCreateValuesRel() {
       return true;
     }
@@ -6681,8 +6634,10 @@ public class SqlToRelConverter {
     /** Sets {@link #isCreateValuesRel()}. */
     Config withCreateValuesRel(boolean createValuesRel);
 
-    /** Returns the {@code explain} option. Describes whether the current
-     * statement is part of an EXPLAIN PLAN statement. */
+    /**
+     * Returns the {@code explain} option. Describes whether the current
+     * statement is part of an EXPLAIN PLAN statement.
+     */
     @Value.Default default boolean isExplain() {
       return false;
     }
@@ -6690,30 +6645,34 @@ public class SqlToRelConverter {
     /** Sets {@link #isExplain()}. */
     Config withExplain(boolean explain);
 
-    /** Returns the {@code expand} option. Controls whether to expand
+    /**
+     * Returns the {@code expand} option. Controls whether to expand
      * sub-queries. If false (the default), each sub-query becomes a
      * {@link org.apache.calcite.rex.RexSubQuery}.
-     *
      * <p>Setting {@code expand} to true is deprecated. Expansion still works,
-     * but there will be less development effort in that area. */
+     * but there will be less development effort in that area.
+     */
     @Value.Default default boolean isExpand() {
       return false;
     }
 
-    /** Sets {@link #isExpand()}.
-     *
+    /**
+     * Sets {@link #isExpand()}.
      * <p>Expansion is deprecated. We recommend that you do not call this
-     * method, and use the default value of {@link #isExpand()}, false. */
+     * method, and use the default value of {@link #isExpand()}, false.
+     */
     Config withExpand(boolean expand);
 
-    /** Returns the {@code inSubQueryThreshold} option,
+    /**
+     * Returns the {@code inSubQueryThreshold} option,
      * default {@link #DEFAULT_IN_SUB_QUERY_THRESHOLD}. Controls the list size
      * threshold under which {@link #convertInToOr} is used. Lists of this size
      * or greater will instead be converted to use a join against an inline
      * table ({@link org.apache.calcite.rel.logical.LogicalValues}) rather than
      * a predicate. A threshold of 0 forces usage of an inline table in all
      * cases; a threshold of {@link Integer#MAX_VALUE} forces usage of OR in all
-     * cases. */
+     * cases.
+     */
     @Value.Default default int getInSubQueryThreshold() {
       return DEFAULT_IN_SUB_QUERY_THRESHOLD;
     }
@@ -6721,11 +6680,13 @@ public class SqlToRelConverter {
     /** Sets {@link #getInSubQueryThreshold()}. */
     Config withInSubQueryThreshold(int threshold);
 
-    /** Returns whether to remove Sort operator for a sub-query
+    /**
+     * Returns whether to remove Sort operator for a sub-query
      * if the Sort has no offset and fetch limit attributes.
      * Because the remove does not change the semantics,
      * in many cases this is a promotion.
-     * Default is true. */
+     * Default is true.
+     */
     @Value.Default default boolean isRemoveSortInSubQuery() {
       return true;
     }
@@ -6733,20 +6694,25 @@ public class SqlToRelConverter {
     /** Sets {@link #isRemoveSortInSubQuery()}. */
     Config withRemoveSortInSubQuery(boolean removeSortInSubQuery);
 
-    /** Returns the factory to create {@link RelBuilder}, never null. Default is
-     * {@link RelFactories#LOGICAL_BUILDER}. */
+    /**
+     * Returns the factory to create {@link RelBuilder}, never null. Default is
+     * {@link RelFactories#LOGICAL_BUILDER}.
+     */
     RelBuilderFactory getRelBuilderFactory();
 
     /** Sets {@link #getRelBuilderFactory()}. */
     Config withRelBuilderFactory(RelBuilderFactory factory);
 
-    /** Returns a function that takes a {@link RelBuilder.Config} and returns
-     * another. Default is the identity function. */
+    /**
+     * Returns a function that takes a {@link RelBuilder.Config} and returns
+     * another. Default is the identity function.
+     */
     UnaryOperator<RelBuilder.Config> getRelBuilderConfigTransform();
 
-    /** Sets {@link #getRelBuilderConfigTransform()}.
-     *
-     * @see #addRelBuilderConfigTransform */
+    /**
+     * Sets {@link #getRelBuilderConfigTransform()}.
+     * @see #addRelBuilderConfigTransform
+     */
     Config withRelBuilderConfigTransform(
         UnaryOperator<RelBuilder.Config> transform);
 
@@ -6757,9 +6723,11 @@ public class SqlToRelConverter {
           getRelBuilderConfigTransform().andThen(transform)::apply);
     }
 
-    /** Returns the hint strategies used to decide how the hints are propagated to
+    /**
+     * Returns the hint strategies used to decide how the hints are propagated to
      * the relational expressions. Default is
-     * {@link HintStrategyTable#EMPTY}. */
+     * {@link HintStrategyTable#EMPTY}.
+     */
     HintStrategyTable getHintStrategyTable();
 
     /** Sets {@link #getHintStrategyTable()}. */
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 28fe7c0374..94e862382b 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -96,6 +96,7 @@ import java.util.Objects;
 import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
 
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.QUANTIFY_OPERATORS;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getComponentTypeOrThrow;
 import static org.apache.calcite.util.Util.first;
 
@@ -209,6 +210,8 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     registerOp(SqlLibraryOperators.TIMESTAMP_SUB,
         new TimestampSubConvertlet());
 
+    QUANTIFY_OPERATORS.forEach(operator -> registerOp(operator, StandardConvertletTable::convertQuantifyOperator));
+
     registerOp(SqlLibraryOperators.NVL, StandardConvertletTable::convertNvl);
     registerOp(SqlLibraryOperators.DECODE,
         StandardConvertletTable::convertDecode);
@@ -347,8 +350,31 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     }
   }
 
-  /** Converts a call to the {@code NVL} function (and also its synonym,
-   * {@code IFNULL}). */
+  /**
+   * Converts ALL or SOME operators.
+   */
+  private static RexNode convertQuantifyOperator(SqlRexContext cx, SqlCall call) {
+    final RexBuilder rexBuilder = cx.getRexBuilder();
+    final RexNode operand0 =
+        cx.convertExpression(call.getOperandList().get(0));
+    assert call.getOperandList().get(1) instanceof SqlNodeList;
+    final RexNode operand1 =
+        cx.convertExpression(((SqlNodeList) call.getOperandList().get(1)).get(0));
+    final RelDataType operand1ComponentType =
+        requireNonNull(operand1.getType().getComponentType());
+    final RelDataType returnType =
+        cx.getTypeFactory().createTypeWithNullability(cx.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN), operand1.getType().isNullable() ||
+            operand0.getType().isNullable() || operand1ComponentType.isNullable());
+    return rexBuilder.makeCall(
+        returnType,
+        call.getOperator(),
+        ImmutableList.of(operand0, operand1));
+  }
+
+  /**
+   * Converts a call to the {@code NVL} function (and also its synonym,
+   * {@code IFNULL}).
+   */
   private static RexNode convertNvl(SqlRexContext cx, SqlCall call) {
     final RexBuilder rexBuilder = cx.getRexBuilder();
     final RexNode operand0 =
@@ -394,9 +420,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, exprs);
   }
 
-  /** Converts a call to the IF function.
-   *
-   * <p>{@code IF(b, x, y)} &rarr; {@code CASE WHEN b THEN x ELSE y END}. */
+  /**
+   * Converts a call to the IF function.
+   * <p>{@code IF(b, x, y)} &rarr; {@code CASE WHEN b THEN x ELSE y END}.
+   */
   private static RexNode convertIf(SqlRexContext cx, SqlCall call) {
     final RexBuilder rexBuilder = cx.getRexBuilder();
     final List<RexNode> operands =
@@ -406,8 +433,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     return rexBuilder.makeCall(type, SqlStdOperatorTable.CASE, operands);
   }
 
-  /** Converts an interval expression to a numeric multiplied by an interval
-   * literal. */
+  /**
+   * Converts an interval expression to a numeric multiplied by an interval
+   * literal.
+   */
   private static RexNode convertInterval(SqlRexContext cx, SqlCall call) {
     // "INTERVAL n HOUR" becomes "n * INTERVAL '1' HOUR"
     final SqlNode n = call.operand(0);
@@ -711,7 +740,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
 
   /**
    * Converts a call to the {@code EXTRACT} function.
-   *
    * <p>Called automatically via reflection.
    */
   public RexNode convertExtract(
@@ -937,9 +965,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
   /**
    * Converts a call to an operator into a {@link RexCall} to the same
    * operator.
-   *
    * <p>Called automatically via reflection.
-   *
    * @param cx   Context
    * @param call Call
    * @return Rex call
@@ -979,7 +1005,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     // If list is odd, e.g. [0, 1, 2, 3, 4] we get [1, 3, 4]
     // If list is even, e.g. [0, 1, 2, 3, 4, 5] we get [2, 4, 5]
     final List<Integer> list = new ArrayList<>();
-    for (int i = count % 2;;) {
+    for (int i = count % 2; ; ) {
       list.add(i);
       i += 2;
       if (i >= count) {
@@ -997,7 +1023,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
       // skip set semantic table node of table function
       operandList =
           call.getOperandList().stream().filter(
-              operand -> operand.getKind() != SqlKind.SET_SEMANTICS_TABLE)
+                  operand -> operand.getKind() != SqlKind.SET_SEMANTICS_TABLE)
               .collect(Collectors.toList());
     } else {
       operandList = call.getOperandList();
@@ -1131,7 +1157,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
 
   /**
    * Converts a BETWEEN expression.
-   *
    * <p>Called automatically via reflection.
    */
   public RexNode convertBetween(
@@ -1180,7 +1205,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
 
   /**
    * Converts a SUBSTRING expression.
-   *
    * <p>Called automatically via reflection.
    */
   public RexNode convertSubstring(
@@ -1213,7 +1237,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
   /**
    * Converts a LiteralChain expression: that is, concatenates the operands
    * immediately, to produce a single literal string.
-   *
    * <p>Called automatically via reflection.
    */
   public RexNode convertLiteralChain(
@@ -1228,7 +1251,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
 
   /**
    * Converts a ROW.
-   *
    * <p>Called automatically via reflection.
    */
   public RexNode convertRow(
@@ -1251,7 +1273,6 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
 
   /**
    * Converts a call to OVERLAPS.
-   *
    * <p>Called automatically via reflection.
    */
   public RexNode convertOverlaps(
@@ -1360,7 +1381,8 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     return rexBuilder.makeCast(type, e);
   }
 
-  /** Convertlet that handles {@code COVAR_POP}, {@code COVAR_SAMP},
+  /**
+   * Convertlet that handles {@code COVAR_POP}, {@code COVAR_SAMP},
    * {@code REGR_SXX}, {@code REGR_SYY} windowed aggregate functions.
    */
   private static class RegrCovarianceConvertlet implements SqlRexConvertlet {
@@ -1490,8 +1512,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     }
   }
 
-  /** Convertlet that handles {@code AVG} and {@code VARIANCE}
-   * windowed aggregate functions. */
+  /**
+   * Convertlet that handles {@code AVG} and {@code VARIANCE}
+   * windowed aggregate functions.
+   */
   private static class AvgVarianceConvertlet implements SqlRexConvertlet {
     private final SqlKind kind;
 
@@ -1641,8 +1665,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     }
   }
 
-  /** Convertlet that converts {@code LTRIM} and {@code RTRIM} to
-   * {@code TRIM}. */
+  /**
+   * Convertlet that converts {@code LTRIM} and {@code RTRIM} to
+   * {@code TRIM}.
+   */
   private static class TrimConvertlet implements SqlRexConvertlet {
     private final SqlTrimFunction.Flag flag;
 
@@ -1721,10 +1747,12 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     }
   }
 
-  /** Convertlet that handles the {@code SUBSTR} function; various dialects
+  /**
+   * Convertlet that handles the {@code SUBSTR} function; various dialects
    * have slightly different specifications. PostgreSQL seems to comply with
    * the ISO standard for the {@code SUBSTRING} function, and therefore
-   * Calcite's default behavior matches PostgreSQL. */
+   * Calcite's default behavior matches PostgreSQL.
+   */
   private static class SubstrConvertlet implements SqlRexConvertlet {
     private final SqlLibrary library;
 
@@ -1878,8 +1906,10 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
     }
   }
 
-  /** Convertlet that handles the 3-argument {@code TIMESTAMPADD} function
-   * and the 2-argument BigQuery-style {@code TIMESTAMP_ADD} function. */
+  /**
+   * Convertlet that handles the 3-argument {@code TIMESTAMPADD} function
+   * and the 2-argument BigQuery-style {@code TIMESTAMP_ADD} function.
+   */
   private static class TimestampAddConvertlet implements SqlRexConvertlet {
     @Override public RexNode convertCall(SqlRexContext cx, SqlCall call) {
       // TIMESTAMPADD(unit, count, timestamp)
@@ -1895,7 +1925,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
       case 2:
         // BigQuery-style 'TIMESTAMP_ADD(timestamp, interval)'
         final SqlBasicCall operandCall = call.operand(1);
-        qualifier  = operandCall.operand(1);
+        qualifier = operandCall.operand(1);
         op1 = cx.convertExpression(operandCall.operand(0));
         op2 = cx.convertExpression(call.operand(0));
         break;
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index 2b3eaaf085..412092a9f8 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -308,6 +308,11 @@ public enum BuiltInMethod {
   COLLECTIONS_EMPTY_LIST(Collections.class, "emptyList"),
   COLLECTIONS_SINGLETON_LIST(Collections.class, "singletonList", Object.class),
   COLLECTION_SIZE(Collection.class, "size"),
+  COLLECTION_EXISTS(Functions.class, "exists", List.class, Predicate1.class),
+  COLLECTION_ALL(Functions.class, "all", List.class, Predicate1.class),
+  COLLECTION_NULLABLE_EXISTS(SqlFunctions.class, "nullableExists",
+      List.class, Function1.class),
+  COLLECTION_NULLABLE_ALL(SqlFunctions.class, "nullableAll", List.class, Function1.class),
   MAP_CLEAR(Map.class, "clear"),
   MAP_GET(Map.class, "get", Object.class),
   MAP_GET_OR_DEFAULT(Map.class, "getOrDefault", Object.class, Object.class),
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index f0cfa5c75f..11a682a2fb 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -1277,9 +1277,9 @@ completeness.
 | value NOT IN (value [, value]*)                   | Whether *value* is not equal to every value in a list
 | value IN (sub-query)                              | Whether *value* is equal to a row returned by *sub-query*
 | value NOT IN (sub-query)                          | Whether *value* is not equal to every row returned by *sub-query*
-| value comparison SOME (sub-query)                 | Whether *value* *comparison* at least one row returned by *sub-query*
-| value comparison ANY (sub-query)                  | Synonym for `SOME`
-| value comparison ALL (sub-query)                  | Whether *value* *comparison* every row returned by *sub-query*
+| value comparison SOME (sub-query or collection)   | Whether *value* *comparison* at least one row returned by *sub-query* or *collection*
+| value comparison ANY (sub-query or collection)    | Synonym for `SOME`
+| value comparison ALL (sub-query or collection)    | Whether *value* *comparison* every row returned by *sub-query* or *collection*
 | EXISTS (sub-query)                                | Whether *sub-query* returns at least one row
 | UNIQUE (sub-query)                                | Whether the rows returned by *sub-query* are unique (ignoring null values)
 
@@ -1644,7 +1644,7 @@ Implicit type coercion of following cases are ignored:
 | multiset NOT SUBMULTISET OF multiset2 | Whether *multiset* is not a submultiset of *multiset2*.
 | multiset MULTISET UNION [ ALL &#124; DISTINCT ] multiset2 | Returns the union *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
 | multiset MULTISET INTERSECT [ ALL &#124; DISTINCT ] multiset2 | Returns the intersection of *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
-| multiset MULTISET EXCEPT [ ALL &#124; DISTINCT ] multiset2 | Returns the difference of *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default).
+| multiset MULTISET EXCEPT [ ALL &#124; DISTINCT ] multiset2 | Returns the difference of *multiset* and *multiset2*, eliminating duplicates if DISTINCT is specified (ALL is the default). 
 
 See also: the UNNEST relational operator converts a collection to a relation.
 
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 4bbb6f1d69..ad74baabfc 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -19,6 +19,8 @@ package org.apache.calcite.test;
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.config.CalciteConnectionProperty;
 import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.linq4j.function.Function1;
+import org.apache.calcite.linq4j.function.Function2;
 import org.apache.calcite.plan.Strong;
 import org.apache.calcite.rel.type.DelegatingTypeSystem;
 import org.apache.calcite.rel.type.RelDataType;
@@ -104,6 +106,7 @@ import java.util.regex.Pattern;
 import static org.apache.calcite.linq4j.tree.Expressions.list;
 import static org.apache.calcite.rel.type.RelDataTypeImpl.NON_NULLABLE_SUFFIX;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PI;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.QUANTIFY_OPERATORS;
 import static org.apache.calcite.sql.test.ResultCheckers.isExactly;
 import static org.apache.calcite.sql.test.ResultCheckers.isNullValue;
 import static org.apache.calcite.sql.test.ResultCheckers.isSet;
@@ -130,27 +133,22 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
 /**
  * Contains unit tests for all operators. Each of the methods is named after an
  * operator.
- *
  * <p>To run, you also need an execution mechanism: parse, validate, and execute
  * expressions on the operators. This is left to a {@link SqlTester} object
  * which is obtained via the {@link #fixture()} method. The default tester
  * merely validates calls to operators, but {@code CalciteSqlOperatorTest}
  * uses a tester that executes calls and checks that results are valid.
- *
  * <p>Different implementations of {@link SqlTester} are possible, such as:
- *
  * <ul>
  * <li>Execute against a JDBC database;
  * <li>Parse and validate but do not evaluate expressions;
  * <li>Generate a SQL script;
  * <li>Analyze which operators are adequately tested.
  * </ul>
- *
  * <p>A typical method will be named after the operator it is testing (say
  * <code>testSubstringFunc</code>). It first calls
  * {@link SqlOperatorFixture#setFor(SqlOperator, VmName...)}
  * to declare which operator it is testing.
- *
  * <blockquote>
  * <pre><code>
  * public void testSubstringFunc() {
@@ -159,15 +157,12 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
  *     tester.checkScalar("sin(1.5707)", "1");
  * }</code></pre>
  * </blockquote>
- *
  * <p>The rest of the method contains calls to the various {@code checkXxx}
  * methods in the {@link SqlTester} interface. For an operator
  * to be adequately tested, there need to be tests for:
- *
  * <ul>
  * <li>Parsing all of its the syntactic variants.
  * <li>Deriving the type of in all combinations of arguments.
- *
  * <ul>
  * <li>Pay particular attention to nullability. For example, the result of the
  * "+" operator is NOT NULL if and only if both of its arguments are NOT
@@ -235,8 +230,10 @@ public class SqlOperatorTest {
   public static final List<String> YEAR_VARIANTS =
       Arrays.asList("YEAR", "SQL_TSI_YEAR");
 
-  /** Minimum and maximum values for each exact and approximate numeric
-   * type. */
+  /**
+   * Minimum and maximum values for each exact and approximate numeric
+   * type.
+   */
   enum Numeric {
     TINYINT("TINYINT", Long.toString(Byte.MIN_VALUE),
         Long.toString(Byte.MIN_VALUE - 1),
@@ -268,16 +265,20 @@ public class SqlOperatorTest {
 
     private final String typeName;
 
-    /** For Float and Double Java types, MIN_VALUE
+    /**
+     * For Float and Double Java types, MIN_VALUE
      * is the smallest positive value, not the smallest negative value.
      * For REAL, FLOAT, DOUBLE, Win32 takes smaller values from
-     * win32_values.h. */
+     * win32_values.h.
+     */
     private final String minNumericString;
     private final String minOverflowNumericString;
 
-    /** For REAL, FLOAT and DOUBLE SQL types (Flaot and Double Java types), we
+    /**
+     * For REAL, FLOAT and DOUBLE SQL types (Flaot and Double Java types), we
      * use something slightly less than MAX_VALUE because round-tripping string
-     * to approx to string doesn't preserve MAX_VALUE on win32. */
+     * to approx to string doesn't preserve MAX_VALUE on win32.
+     */
     private final String maxNumericString;
     private final String maxOverflowNumericString;
 
@@ -291,8 +292,10 @@ public class SqlOperatorTest {
       this.maxOverflowNumericString = maxOverflowNumericString;
     }
 
-    /** Calls a consumer for each value. Similar effect to a {@code for}
-     * loop, but the calling line number will show up in the call stack. */
+    /**
+     * Calls a consumer for each value. Similar effect to a {@code for}
+     * loop, but the calling line number will show up in the call stack.
+     */
     static void forEach(Consumer<Numeric> consumer) {
       consumer.accept(TINYINT);
       consumer.accept(SMALLINT);
@@ -335,8 +338,10 @@ public class SqlOperatorTest {
    */
   public static final boolean DECIMAL = false;
 
-  /** Function object that returns a string with 2 copies of each character.
-   * For example, {@code DOUBLER.apply("xy")} returns {@code "xxyy"}. */
+  /**
+   * Function object that returns a string with 2 copies of each character.
+   * For example, {@code DOUBLER.apply("xy")} returns {@code "xxyy"}.
+   */
   private static final UnaryOperator<String> DOUBLER =
       new UnaryOperator<String>() {
         final Pattern pattern = Pattern.compile("(.)");
@@ -1015,9 +1020,11 @@ public class SqlOperatorTest {
     f.checkNull("cast(null as boolean)");
   }
 
-  /** Test case for
+  /**
+   * Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-1439">[CALCITE-1439]
-   * Handling errors during constant reduction</a>. */
+   * Handling errors during constant reduction</a>.
+   */
   @Test void testCastInvalid() {
     // Before CALCITE-1439 was fixed, constant reduction would kick in and
     // generate Java constants that throw when the class is loaded, thus
@@ -1212,7 +1219,6 @@ public class SqlOperatorTest {
   /**
    * Returns a Calendar that is the current time, pausing if we are within 2
    * minutes of midnight or the top of the hour.
-   *
    * @param timeUnit Time unit
    * @return calendar
    */
@@ -1268,7 +1274,8 @@ public class SqlOperatorTest {
         INVALID_CHAR_MESSAGE, true);
   }
 
-  /** Test case for
+  /**
+   * Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-4861">[CALCITE-4861]
    * Optimisation of chained cast calls can lead to unexpected behaviour.</a>.
    */
@@ -1321,8 +1328,8 @@ public class SqlOperatorTest {
     // so nulls do not match.
     // (Unlike Oracle's 'decode(null, null, ...)', by the way.)
     f.checkString("case cast(null as int)\n"
-        + "when cast(null as int) then 'nulls match'\n"
-        + "else 'nulls do not match' end",
+            + "when cast(null as int) then 'nulls match'\n"
+            + "else 'nulls do not match' end",
         "nulls do not match",
         "CHAR(18) NOT NULL");
 
@@ -1460,7 +1467,6 @@ public class SqlOperatorTest {
 
   /**
    * Tests support for JDBC functions.
-   *
    * <p>See FRG-97 "Support for JDBC escape syntax is incomplete".
    */
   @Test void testJdbcFn() {
@@ -2232,14 +2238,15 @@ public class SqlOperatorTest {
         + " interval '1 2:3:4.5' day to second)");
   }
 
-  /** Test case for
+  /**
+   * Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-715">[CALCITE-715]
    * Add PERIOD type constructor and period operators (CONTAINS, PRECEDES,
    * etc.)</a>.
-   *
    * <p>Tests OVERLAP and similar period operators CONTAINS, EQUALS, PRECEDES,
    * SUCCEEDS, IMMEDIATELY PRECEDES, IMMEDIATELY SUCCEEDS for DATE, TIME and
-   * TIMESTAMP values. */
+   * TIMESTAMP values.
+   */
   @Test void testPeriodOperators() {
     String[] times = {
         "TIME '01:00:00'",
@@ -2669,9 +2676,11 @@ public class SqlOperatorTest {
         "2014-04-12", "DATE NOT NULL");
   }
 
-  /** Test case for
+  /**
+   * Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-1864">[CALCITE-1864]
-   * Allow NULL literal as argument</a>. */
+   * Allow NULL literal as argument</a>.
+   */
   @Test void testNullOperand() {
     final SqlOperatorFixture f = fixture();
     checkNullOperand(f, "=");
@@ -3262,9 +3271,11 @@ public class SqlOperatorTest {
     f1.checkBoolean("'ab\ncd\nef' ilike '%cde%'", false);
   }
 
-  /** Test case for
+  /**
+   * Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-1898">[CALCITE-1898]
-   * LIKE must match '.' (period) literally</a>. */
+   * LIKE must match '.' (period) literally</a>.
+   */
   @Test void testLikeDot() {
     final SqlOperatorFixture f = fixture();
     f.checkBoolean("'abc' like 'a.c'", false);
@@ -3439,8 +3450,8 @@ public class SqlOperatorTest {
     final String expectedError =
         TestUtil.getJavaMajorVersion() >= 13
             ? "Illegal repetition near index 22\n"
-              + "\\[\\:LOWER\\:\\]\\{2\\}\\[\\:DIGIT\\:\\]\\{,5\\}\n"
-              + "                      \\^"
+            + "\\[\\:LOWER\\:\\]\\{2\\}\\[\\:DIGIT\\:\\]\\{,5\\}\n"
+            + "                      \\^"
             : "Illegal repetition near index 20\n"
                 + "\\[\\:LOWER\\:\\]\\{2\\}\\[\\:DIGIT\\:\\]\\{,5\\}\n"
                 + "                    \\^";
@@ -4889,7 +4900,7 @@ public class SqlOperatorTest {
             "Cannot apply 'INITCAP' to arguments of type "
                 + "'INITCAP\\(<DATE>\\)'\\. Supported form\\(s\\): "
                 + "'INITCAP\\(<CHARACTER>\\)'",
-        false);
+            false);
     f.checkType("initcap(cast(null as date))", "VARCHAR");
   }
 
@@ -5150,7 +5161,7 @@ public class SqlOperatorTest {
             "Cannot apply 'ACOS' to arguments of type "
                 + "'ACOS\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
                 + "'ACOS\\(<NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("acos('abc')", "DOUBLE NOT NULL");
     f.checkScalarApprox("acos(0.5)", "DOUBLE NOT NULL",
         isWithin(1.0472d, 0.0001d));
@@ -5171,7 +5182,7 @@ public class SqlOperatorTest {
             "Cannot apply 'ASIN' to arguments of type "
                 + "'ASIN\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
                 + "'ASIN\\(<NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("asin('abc')", "DOUBLE NOT NULL");
     f.checkScalarApprox("asin(0.5)", "DOUBLE NOT NULL",
         isWithin(0.5236d, 0.0001d));
@@ -5192,7 +5203,7 @@ public class SqlOperatorTest {
             "Cannot apply 'ATAN' to arguments of type "
                 + "'ATAN\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
                 + "'ATAN\\(<NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("atan('abc')", "DOUBLE NOT NULL");
     f.checkScalarApprox("atan(2)", "DOUBLE NOT NULL",
         isWithin(1.1071d, 0.0001d));
@@ -5215,7 +5226,7 @@ public class SqlOperatorTest {
             "Cannot apply 'ATAN2' to arguments of type "
                 + "'ATAN2\\(<CHAR\\(3\\)>, <CHAR\\(3\\)>\\)'\\. "
                 + "Supported form\\(s\\): 'ATAN2\\(<NUMERIC>, <NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("atan2('abc', 'def')", "DOUBLE NOT NULL");
     f.checkScalarApprox("atan2(0.5, -0.5)", "DOUBLE NOT NULL",
         isWithin(2.3562d, 0.0001d));
@@ -5237,7 +5248,7 @@ public class SqlOperatorTest {
             "Cannot apply 'CBRT' to arguments of type "
                 + "'CBRT\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
                 + "'CBRT\\(<NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("cbrt('abc')", "DOUBLE NOT NULL");
     f.checkScalar("cbrt(8)", "2.0", "DOUBLE NOT NULL");
     f.checkScalar("cbrt(-8)", "-2.0", "DOUBLE NOT NULL");
@@ -5258,7 +5269,7 @@ public class SqlOperatorTest {
             "Cannot apply 'COS' to arguments of type "
                 + "'COS\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
                 + "'COS\\(<NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("cos('abc')", "DOUBLE NOT NULL");
     f.checkScalarApprox("cos(1)", "DOUBLE NOT NULL",
         isWithin(0.5403d, 0.0001d));
@@ -5319,7 +5330,7 @@ public class SqlOperatorTest {
             "Cannot apply 'DEGREES' to arguments of type "
                 + "'DEGREES\\(<CHAR\\(3\\)>\\)'\\. Supported form\\(s\\): "
                 + "'DEGREES\\(<NUMERIC>\\)'",
-        false);
+            false);
     f.checkType("degrees('abc')", "DOUBLE NOT NULL");
     f.checkScalarApprox("degrees(1)", "DOUBLE NOT NULL",
         isWithin(57.2958d, 0.0001d));
@@ -5801,17 +5812,16 @@ public class SqlOperatorTest {
 
   /**
    * Returns a time string, in GMT, that will be valid for at least 2 minutes.
-   *
    * <p>For example, at "2005-01-01 12:34:56 PST", returns "2005-01-01 20:".
    * At "2005-01-01 12:34:59 PST", waits a minute, then returns "2005-01-01
    * 21:".
-   *
    * @param tz Time zone
    * @return Time string
    */
   protected static Pair<String, Hook.Closeable> currentTimeString(TimeZone tz) {
     final Calendar calendar = getCalendarNotTooNear(Calendar.HOUR_OF_DAY);
-    final Hook.Closeable closeable = () -> { };
+    final Hook.Closeable closeable = () -> {
+    };
     return Pair.of(toTimeString(tz, calendar), closeable);
   }
 
@@ -6066,9 +6076,11 @@ public class SqlOperatorTest {
     f.checkBoolean("ends_with(x'', x'')", true);
   }
 
-  /** Tests the {@code SUBSTRING} operator. Many test cases that used to be
+  /**
+   * Tests the {@code SUBSTRING} operator. Many test cases that used to be
    * have been moved to {@link SubFunChecker#assertSubFunReturns}, and are
-   * called for both {@code SUBSTRING} and {@code SUBSTR}. */
+   * called for both {@code SUBSTRING} and {@code SUBSTR}.
+   */
   @Test void testSubstringFunction() {
     final SqlOperatorFixture f = fixture();
     checkSubstringFunction(f);
@@ -6110,43 +6122,55 @@ public class SqlOperatorTest {
     f.checkNull("substring('abc' FROM 2 FOR cast(null as integer))");
   }
 
-  /** Tests the non-standard SUBSTR function, that has syntax
-   * "SUBSTR(value, start [, length ])", as used in BigQuery. */
+  /**
+   * Tests the non-standard SUBSTR function, that has syntax
+   * "SUBSTR(value, start [, length ])", as used in BigQuery.
+   */
   @Test void testBigQuerySubstrFunction() {
     substrChecker(SqlLibrary.BIG_QUERY, SqlLibraryOperators.SUBSTR_BIG_QUERY)
         .check();
   }
 
-  /** Tests the non-standard SUBSTR function, that has syntax
-   * "SUBSTR(value, start [, length ])", as used in Oracle. */
+  /**
+   * Tests the non-standard SUBSTR function, that has syntax
+   * "SUBSTR(value, start [, length ])", as used in Oracle.
+   */
   @Test void testMysqlSubstrFunction() {
     substrChecker(SqlLibrary.MYSQL, SqlLibraryOperators.SUBSTR_MYSQL)
         .check();
   }
 
-  /** Tests the non-standard SUBSTR function, that has syntax
-   * "SUBSTR(value, start [, length ])", as used in Oracle. */
+  /**
+   * Tests the non-standard SUBSTR function, that has syntax
+   * "SUBSTR(value, start [, length ])", as used in Oracle.
+   */
   @Test void testOracleSubstrFunction() {
     substrChecker(SqlLibrary.ORACLE, SqlLibraryOperators.SUBSTR_ORACLE)
         .check();
   }
 
-  /** Tests the non-standard SUBSTR function, that has syntax
-   * "SUBSTR(value, start [, length ])", as used in PostgreSQL. */
+  /**
+   * Tests the non-standard SUBSTR function, that has syntax
+   * "SUBSTR(value, start [, length ])", as used in PostgreSQL.
+   */
   @Test void testPostgresqlSubstrFunction() {
     substrChecker(SqlLibrary.POSTGRESQL, SqlLibraryOperators.SUBSTR_POSTGRESQL)
         .check();
   }
 
-  /** Tests the standard {@code SUBSTRING} function in the mode that has
-   * BigQuery's non-standard semantics. */
+  /**
+   * Tests the standard {@code SUBSTRING} function in the mode that has
+   * BigQuery's non-standard semantics.
+   */
   @Test void testBigQuerySubstringFunction() {
     substringChecker(SqlConformanceEnum.BIG_QUERY, SqlLibrary.BIG_QUERY)
         .check();
   }
 
-  /** Tests the standard {@code SUBSTRING} function in ISO standard
-   * semantics. */
+  /**
+   * Tests the standard {@code SUBSTRING} function in ISO standard
+   * semantics.
+   */
   @Test void testStandardSubstringFunction() {
     substringChecker(SqlConformanceEnum.STRICT_2003, SqlLibrary.POSTGRESQL)
         .check();
@@ -6167,8 +6191,10 @@ public class SqlOperatorTest {
     return new SubFunChecker(fixture().withLibrary(library), library, function);
   }
 
-  /** Tests various configurations of {@code SUBSTR} and {@code SUBSTRING}
-   * functions. */
+  /**
+   * Tests various configurations of {@code SUBSTR} and {@code SUBSTRING}
+   * functions.
+   */
   static class SubFunChecker {
     final SqlOperatorFixture f;
     final SqlLibrary library;
@@ -6486,8 +6512,10 @@ public class SqlOperatorTest {
     f12.checkNull("nvl(CAST(NULL AS VARCHAR(6)), cast(NULL AS VARCHAR(4)))");
   }
 
-  /** Tests {@code IFNULL}, which is a synonym for {@code NVL}, and is related to
-   * {@code COALESCE} but requires precisely two arguments. */
+  /**
+   * Tests {@code IFNULL}, which is a synonym for {@code NVL}, and is related to
+   * {@code COALESCE} but requires precisely two arguments.
+   */
   @Test void testIfnullFunc() {
     final SqlOperatorFixture f = fixture()
         .withLibrary(SqlLibrary.BIG_QUERY)
@@ -6532,7 +6560,7 @@ public class SqlOperatorTest {
         "CHAR(1) NOT NULL");
     // nulls match
     f.checkScalar("decode(cast(null as integer), 0, 'a',\n"
-        + " cast(null as integer), 'b', 2, 'c', 'd')", "b",
+            + " cast(null as integer), 'b', 2, 'c', 'd')", "b",
         "CHAR(1) NOT NULL");
   }
 
@@ -6573,7 +6601,7 @@ public class SqlOperatorTest {
     f.checkBoolean("1 member of multiset[1]", true);
     f.checkBoolean("'2' member of multiset['1']", false);
     f.checkBoolean("cast(null as double) member of"
-            + " multiset[cast(null as double)]", true);
+        + " multiset[cast(null as double)]", true);
     f.checkBoolean("cast(null as double) member of multiset[1.1]", false);
     f.checkBoolean("1.1 member of multiset[cast(null as double)]", false);
   }
@@ -6583,7 +6611,7 @@ public class SqlOperatorTest {
     f.setFor(SqlStdOperatorTable.MULTISET_UNION_DISTINCT,
         VM_FENNEL, VM_JAVA);
     f.checkBoolean("multiset[1,2] submultiset of "
-            + "(multiset[2] multiset union multiset[1])", true);
+        + "(multiset[2] multiset union multiset[1])", true);
     f.checkScalar("cardinality(multiset[1, 2, 3, 4, 2] "
             + "multiset union distinct multiset[1, 4, 5, 7, 8])",
         "7",
@@ -6690,7 +6718,7 @@ public class SqlOperatorTest {
     f.checkBoolean("multiset['a', 'b'] not submultiset of "
         + "multiset['c', 'd', 's', 'a']", true);
     f.checkBoolean("multiset['a', 'd'] not submultiset of "
-            + "multiset['c', 's', 'a', 'w', 'd']", false);
+        + "multiset['c', 's', 'a', 'w', 'd']", false);
     f.checkBoolean("multiset['q', 'a'] not submultiset of "
         + "multiset['a', 'q']", false);
   }
@@ -6729,11 +6757,11 @@ public class SqlOperatorTest {
     f.checkAggType("listagg(12)", "VARCHAR NOT NULL");
     f.enableTypeCoercion(false)
         .checkFails("^listagg(12)^",
-        "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
+            "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
     f.checkAggType("listagg(cast(12 as double))", "VARCHAR NOT NULL");
     f.enableTypeCoercion(false)
         .checkFails("^listagg(cast(12 as double))^",
-        "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
+            "Cannot apply 'LISTAGG' to arguments of type .*'\n.*'", false);
     f.checkFails("^listagg()^",
         "Invalid number of arguments to function 'LISTAGG'. Was expecting 1 arguments",
         false);
@@ -6923,8 +6951,10 @@ public class SqlOperatorTest {
         "INTEGER NOT NULL MULTISET NOT NULL");
     f.enableTypeCoercion(false).checkFails("^intersection(12)^",
         "Cannot apply 'INTERSECTION' to arguments of type .*", false);
-    final String[] values1 = {"MULTISET[0]", "MULTISET[1]", "MULTISET[2]",
-        "MULTISET[3]"};
+    final String[] values1 = {
+        "MULTISET[0]", "MULTISET[1]", "MULTISET[2]",
+        "MULTISET[3]"
+    };
     f.checkAgg("intersection(x)", values1, isSingle("[]"));
     final String[] values2 = {"MULTISET[0, 1]", "MULTISET[1, 2]"};
     f.checkAgg("intersection(x)", values2, isSingle("[1]"));
@@ -6955,7 +6985,7 @@ public class SqlOperatorTest {
     f.checkAggType("mode(DISTINCT 1.5)", "DECIMAL(2, 1) NOT NULL");
     f.checkType("mode(cast(null as varchar(2)))", "VARCHAR(2)");
 
-    final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2", "3", "3", "3" };
+    final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2", "3", "3", "3"};
     f.checkAgg("mode(x)", values, isSingle("3"));
     final String[] values2 = {"0", null, null, null, "2", "2"};
     f.checkAgg("mode(x)", values2, isSingle("2"));
@@ -7097,13 +7127,13 @@ public class SqlOperatorTest {
           "0", "BIGINT NOT NULL");
 
       f.checkScalar("extract(millisecond from "
-              + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
+          + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
 
       f.checkScalar("extract(microsecond "
-              + "from interval '4-2' year to month)", "0", "BIGINT NOT NULL");
+          + "from interval '4-2' year to month)", "0", "BIGINT NOT NULL");
 
       f.checkScalar("extract(nanosecond from "
-              + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
+          + "interval '4-2' year to month)", "0", "BIGINT NOT NULL");
 
       f.checkScalar("extract(minute from interval '4-2' year to month)",
           "0", "BIGINT NOT NULL");
@@ -7558,7 +7588,7 @@ public class SqlOperatorTest {
             + "from (VALUES (ROW(ROW(3, CAST(NULL AS INTEGER)), ROW(4, 8)))) as T(x, y)",
         SqlTests.ANY_TYPE_CHECKER, isNullValue());
     f.checkFails("select \"T\".\"X\"[1 + CAST(NULL AS INTEGER)] "
-        + "from (VALUES (ROW(ROW(3, CAST(NULL AS INTEGER)), ROW(4, 8)))) as T(x, y)",
+            + "from (VALUES (ROW(ROW(3, CAST(NULL AS INTEGER)), ROW(4, 8)))) as T(x, y)",
         "Cannot infer type of field at position null within ROW type: "
             + "RecordType\\(INTEGER EXPR\\$0, INTEGER EXPR\\$1\\)", false);
   }
@@ -7679,7 +7709,7 @@ public class SqlOperatorTest {
                 + "'CEIL\\(<DATE> TO <TIME_UNIT>\\)'\n"
                 + "'CEIL\\(<TIME> TO <TIME_UNIT>\\)'\n"
                 + "'CEIL\\(<TIMESTAMP> TO <TIME_UNIT>\\)'",
-        false);
+            false);
     f.checkType("ceil('12:34:56')", "DECIMAL(19, 0) NOT NULL");
     f.checkFails("^ceil(time '12:34:56')^",
         "(?s)Cannot apply 'CEIL' to arguments .*", false);
@@ -7722,8 +7752,10 @@ public class SqlOperatorTest {
     f.checkNull("ceiling(cast(null as timestamp) to month)");
   }
 
-  /** Tests {@code FLOOR}, {@code CEIL}, {@code TIMESTAMPADD},
-   * {@code TIMESTAMPDIFF} functions with custom time frames. */
+  /**
+   * Tests {@code FLOOR}, {@code CEIL}, {@code TIMESTAMPADD},
+   * {@code TIMESTAMPDIFF} functions with custom time frames.
+   */
   @Test void testCustomTimeFrame() {
     final SqlOperatorFixture f = fixture()
         .withFactory(tf ->
@@ -7793,7 +7825,7 @@ public class SqlOperatorTest {
     f.withLibrary(SqlLibrary.BIG_QUERY)
         .setFor(SqlLibraryOperators.TIMESTAMP_DIFF3)
         .checkScalar("timestamp_diff(timestamp '2008-12-25 15:30:00', "
-            + "timestamp '2008-12-25 16:30:00', \"minute15\")",
+                + "timestamp '2008-12-25 16:30:00', \"minute15\")",
             "-4", "INTEGER NOT NULL");
   }
 
@@ -7986,8 +8018,10 @@ public class SqlOperatorTest {
         "TIMESTAMP(3) NOT NULL");
   }
 
-  /** Tests {@code TIMESTAMP_ADD}, BigQuery's 2-argument variant of the
-   * 3-argument {@code TIMESTAMPADD} function. */
+  /**
+   * Tests {@code TIMESTAMP_ADD}, BigQuery's 2-argument variant of the
+   * 3-argument {@code TIMESTAMPADD} function.
+   */
   @Test void testTimestampAdd2() {
     final SqlOperatorFixture f0 = fixture()
         .setFor(SqlLibraryOperators.TIMESTAMP_ADD2);
@@ -8029,12 +8063,14 @@ public class SqlOperatorTest {
     f.checkNull("timestamp_add(CAST(NULL AS TIMESTAMP), interval 5 minute)");
   }
 
-  /** Tests BigQuery's {@code DATETIME_ADD(timestamp, interval)} function.
+  /**
+   * Tests BigQuery's {@code DATETIME_ADD(timestamp, interval)} function.
    * When Calcite runs in BigQuery mode, {@code DATETIME} is a type alias for
    * {@code TIMESTAMP} and this function follows the same behavior as
    * {@code TIMESTAMP_ADD(timestamp, interval)}. The tests below use
    * {@code TIMESTAMP} values rather than the {@code DATETIME} alias because the
-   * operator fixture does not currently support type aliases. */
+   * operator fixture does not currently support type aliases.
+   */
   @Test void testDatetimeAdd() {
     final SqlOperatorFixture f0 = fixture()
         .setFor(SqlLibraryOperators.DATETIME_ADD);
@@ -8076,11 +8112,13 @@ public class SqlOperatorTest {
     f.checkNull("datetime_add(CAST(NULL AS TIMESTAMP), interval 5 minute)");
   }
 
-  /** Tests {@code TIMESTAMP_DIFF}, BigQuery's variant of the
+  /**
+   * Tests {@code TIMESTAMP_DIFF}, BigQuery's variant of the
    * {@code TIMESTAMPDIFF} function, which differs in the ordering
    * of the parameters and the ordering of the subtraction between
    * the two timestamps. In {@code TIMESTAMPDIFF} it is (t2 - t1)
-   * while for {@code TIMESTAMP_DIFF} is is (t1 - t2). */
+   * while for {@code TIMESTAMP_DIFF} is is (t1 - t2).
+   */
   @Test void testTimestampDiff3() {
     final SqlOperatorFixture f0 = fixture()
         .setFor(SqlLibraryOperators.TIMESTAMP_DIFF3);
@@ -8191,12 +8229,14 @@ public class SqlOperatorTest {
             isNullValue(), "INTEGER"));
   }
 
-  /** Tests BigQuery's {@code DATETIME_DIFF(timestamp, timestamp2, timeUnit)}
+  /**
+   * Tests BigQuery's {@code DATETIME_DIFF(timestamp, timestamp2, timeUnit)}
    * function. When Calcite runs in BigQuery mode, {@code DATETIME} is a type
    * alias for {@code TIMESTAMP} and this function follows the same behavior as
    * {@code TIMESTAMP_DIFF(timestamp, timestamp2, timeUnit)}. The tests below
    * use {@code TIMESTAMP} values rather than the {@code DATETIME} alias because
-   * the operator fixture does not currently support type aliases. */
+   * the operator fixture does not currently support type aliases.
+   */
   @Test void testDatetimeDiff() {
     final SqlOperatorFixture f0 = fixture()
         .setFor(SqlLibraryOperators.DATETIME_DIFF);
@@ -8557,10 +8597,12 @@ public class SqlOperatorTest {
     f.checkNull("date_sub(CAST(NULL AS DATE), interval 5 day)");
   }
 
-  /** Tests for BigQuery's DATETIME_SUB() function. Because the operator
+  /**
+   * Tests for BigQuery's DATETIME_SUB() function. Because the operator
    * fixture does not currently support type aliases, TIMESTAMPs are used
    * in place of DATETIMEs (a Calcite alias of TIMESTAMP) for the function's
-   * first argument. */
+   * first argument.
+   */
   @Test void testDatetimeSub() {
     final SqlOperatorFixture f0 = fixture()
         .setFor(SqlLibraryOperators.DATETIME_SUB);
@@ -8602,8 +8644,10 @@ public class SqlOperatorTest {
     f.checkNull("datetime_sub(CAST(NULL AS TIMESTAMP), interval 5 minute)");
   }
 
-  /** The {@code DATEDIFF} function is implemented in the Babel parser but not
-   * the Core parser, and therefore gives validation errors. */
+  /**
+   * The {@code DATEDIFF} function is implemented in the Babel parser but not
+   * the Core parser, and therefore gives validation errors.
+   */
   @Test void testDateDiff() {
     final SqlOperatorFixture f = fixture()
         .setFor(SqlLibraryOperators.DATEDIFF);
@@ -8612,8 +8656,10 @@ public class SqlOperatorTest {
         false);
   }
 
-  /** Tests BigQuery's {@code TIME_ADD}, which adds an interval to a time
-   * expression. */
+  /**
+   * Tests BigQuery's {@code TIME_ADD}, which adds an interval to a time
+   * expression.
+   */
   @Test void testTimeAdd() {
     final SqlOperatorFixture f0 = fixture()
         .setFor(SqlLibraryOperators.TIME_ADD);
@@ -9035,7 +9081,7 @@ public class SqlOperatorTest {
             "(?s)Cannot apply 'SUM' to arguments of type "
                 + "'SUM\\(<CHAR\\(4\\)>\\)'\\. Supported form\\(s\\): "
                 + "'SUM\\(<NUMERIC>\\)'.*",
-        false);
+            false);
     f.checkType("sum('name')", "DECIMAL(19, 9)");
     f.checkAggType("sum(1)", "INTEGER NOT NULL");
     f.checkAggType("sum(1.2)", "DECIMAL(19, 1) NOT NULL");
@@ -9051,7 +9097,7 @@ public class SqlOperatorTest {
             "(?s)Cannot apply 'SUM' to arguments of type "
                 + "'SUM\\(<VARCHAR\\(2\\)>\\)'\\. Supported form\\(s\\): "
                 + "'SUM\\(<NUMERIC>\\)'.*",
-        false);
+            false);
     f.checkType("sum(cast(null as varchar(2)))", "DECIMAL(19, 9)");
     final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2"};
     f.checkAgg("sum(x)", values, isSingle(4));
@@ -9261,7 +9307,7 @@ public class SqlOperatorTest {
             "(?s)Cannot apply 'STDDEV' to arguments of type "
                 + "'STDDEV\\(<VARCHAR\\(2\\)>\\)'\\. "
                 + "Supported form\\(s\\): 'STDDEV\\(<NUMERIC>\\)'.*",
-        false);
+            false);
     f.checkType("stddev(cast(null as varchar(2)))", "DECIMAL(19, 9)");
     f.checkType("stddev(CAST(NULL AS INTEGER))", "INTEGER");
     f.checkAggType("stddev(DISTINCT 1.5)", "DECIMAL(2, 1) NOT NULL");
@@ -9471,7 +9517,99 @@ public class SqlOperatorTest {
     f.checkAgg("some(x = 2)", values, isSingle("true"));
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-5160">[CALCITE-5160]
+   * ANY/SOME, ALL operators should support collection expressions</a>. */
+  @Test void testQuantifyCollectionOperators() {
+    final SqlOperatorFixture f = fixture();
+    QUANTIFY_OPERATORS.forEach(operator -> f.setFor(operator, SqlOperatorFixture.VmName.EXPAND));
+
+    Function2<String, Boolean, Void> checkBoolean = (sql, result) -> {
+      f.checkBoolean(sql.replace("COLLECTION", "ARRAY"), result);
+      f.checkBoolean(sql.replace("COLLECTION", "MULTISET"), result);
+      return null;
+    };
+
+    Function1<String, Void> checkNull = sql -> {
+      f.checkNull(sql.replace("COLLECTION", "ARRAY"));
+      f.checkNull(sql.replace("COLLECTION", "MULTISET"));
+      return null;
+    };
+
+    checkNull.apply("1 = some (COLLECTION[2,3,null])");
+    checkNull.apply("null = some (COLLECTION[1,2,3])");
+    checkNull.apply("null = some (COLLECTION[1,2,null])");
+    checkNull.apply("1 = some (COLLECTION[null,null,null])");
+    checkNull.apply("null = some (COLLECTION[null,null,null])");
+
+    checkBoolean.apply("1 = some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("3 = some (COLLECTION[1,2])", false);
+
+    checkBoolean.apply("1 <> some (COLLECTION[1])", false);
+    checkBoolean.apply("2 <> some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("3 <> some (COLLECTION[1,2,null])", true);
+
+    checkBoolean.apply("1 < some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("0 < some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("2 < some (COLLECTION[1,2])", false);
+
+    checkBoolean.apply("2 <= some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("0 <= some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("3 <= some (COLLECTION[1,2])", false);
+
+    checkBoolean.apply("2 > some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("3 > some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("1 > some (COLLECTION[1,2])", false);
+
+    checkBoolean.apply("2 >= some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("3 >= some (COLLECTION[1,2,null])", true);
+    checkBoolean.apply("0 >= some (COLLECTION[1,2])", false);
+
+    f.check("SELECT 3 = some(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+        "BOOLEAN", true);
+    f.check("SELECT 4 = some(x.t) FROM (SELECT ARRAY[1,2,3] as t) as x",
+        "BOOLEAN NOT NULL", false);
+    f.check("SELECT 4 = some(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+        "BOOLEAN", isNullValue());
+    f.check("SELECT (SELECT * FROM UNNEST(ARRAY[3]) LIMIT 1) = "
+            + "some(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+        "BOOLEAN", true);
 
+
+    checkNull.apply("1 = all (COLLECTION[1,1,null])");
+    checkNull.apply("null = all (COLLECTION[1,2,3])");
+    checkNull.apply("null = all (COLLECTION[1,2,null])");
+    checkNull.apply("1 = all (COLLECTION[null,null,null])");
+    checkNull.apply("null = all (COLLECTION[null,null,null])");
+
+    checkBoolean.apply("1 = all (COLLECTION[1,1])", true);
+    checkBoolean.apply("3 = all (COLLECTION[1,3,null])", false);
+
+    checkBoolean.apply("1 <> all (COLLECTION[2,3,4])", true);
+    checkBoolean.apply("2 <> all (COLLECTION[2,null])", false);
+
+    checkBoolean.apply("1 < all (COLLECTION[2,3,4])", true);
+    checkBoolean.apply("2 < all (COLLECTION[1,2,null])", false);
+
+    checkBoolean.apply("2 <= all (COLLECTION[2,3,4])", true);
+    checkBoolean.apply("1 <= all (COLLECTION[0,1,null])", false);
+
+    checkBoolean.apply("2 > all (COLLECTION[0,1])", true);
+    checkBoolean.apply("3 > all (COLLECTION[1,3,null])", false);
+
+    checkBoolean.apply("2 >= all (COLLECTION[0,1,2])", true);
+    checkBoolean.apply("3 >= all (COLLECTION[3,4,null])", false);
+
+    f.check("SELECT 3 >= all(x.t) FROM (SELECT ARRAY[1,2,3] as t) as x",
+        "BOOLEAN NOT NULL", true);
+    f.check("SELECT 4 = all(x.t) FROM (SELECT ARRAY[1,2,3,null] as t) as x",
+        "BOOLEAN", false);
+    f.check("SELECT 4 = all(x.t) FROM (SELECT ARRAY[4,4,null] as t) as x",
+        "BOOLEAN", isNullValue());
+    f.check("SELECT (SELECT * FROM UNNEST(ARRAY[3]) LIMIT 1) = "
+            + "all(x.t) FROM (SELECT ARRAY[3,3] as t) as x",
+        "BOOLEAN", true);
+  }
   @Test void testAnyValueFunc() {
     final SqlOperatorFixture f = fixture();
     f.setFor(SqlStdOperatorTable.ANY_VALUE, VM_EXPAND);
@@ -9664,15 +9802,16 @@ public class SqlOperatorTest {
         "CAST(x'03' AS BINARY)",
         "cast(x'02' as BINARY)",
         "cast(x'02' AS BINARY)",
-        "cast(null AS BINARY)"};
+        "cast(null AS BINARY)"
+    };
     f.checkAgg("bit_and(x)", binaryValues, isSingle("02"));
     f.checkAgg("bit_and(x)", new String[]{"CAST(x'02' AS BINARY)"}, isSingle("02"));
 
     f.checkAggFails("bit_and(x)",
         new String[]{"CAST(x'0201' AS VARBINARY)", "CAST(x'02' AS VARBINARY)"},
         "Error while executing SQL"
-            +  " \"SELECT bit_and\\(x\\)"
-            +  " FROM \\(SELECT CAST\\(x'0201' AS VARBINARY\\) AS x FROM \\(VALUES \\(1\\)\\)"
+            + " \"SELECT bit_and\\(x\\)"
+            + " FROM \\(SELECT CAST\\(x'0201' AS VARBINARY\\) AS x FROM \\(VALUES \\(1\\)\\)"
             + " UNION ALL SELECT CAST\\(x'02' AS VARBINARY\\) AS x FROM \\(VALUES \\(1\\)\\)\\)\":"
             + " Different length for bitwise operands: the first: 2, the second: 1",
         true);
@@ -9705,7 +9844,8 @@ public class SqlOperatorTest {
         "CAST(x'01' AS BINARY)",
         "cast(x'02' as BINARY)",
         "cast(x'02' AS BINARY)",
-        "cast(null AS BINARY)"};
+        "cast(null AS BINARY)"
+    };
     f.checkAgg("bit_or(x)", binaryValues, isSingle("03"));
     f.checkAgg("bit_or(x)", new String[]{"CAST(x'02' AS BINARY)"},
         isSingle("02"));
@@ -9738,7 +9878,8 @@ public class SqlOperatorTest {
         "CAST(x'01' AS BINARY)",
         "cast(x'02' as BINARY)",
         "cast(x'01' AS BINARY)",
-        "cast(null AS BINARY)"};
+        "cast(null AS BINARY)"
+    };
     f.checkAgg("bit_xor(x)", binaryValues, isSingle("02"));
     f.checkAgg("bit_xor(x)", new String[]{"CAST(x'02' AS BINARY)"},
         isSingle("02"));
@@ -9768,7 +9909,6 @@ public class SqlOperatorTest {
   /**
    * Tests that CAST fails when given a value just outside the valid range for
    * that type. For example,
-   *
    * <ul>
    * <li>CAST(-200 AS TINYINT) fails because the value is less than -128;
    * <li>CAST(1E-999 AS FLOAT) fails because the value underflows;
@@ -9812,7 +9952,6 @@ public class SqlOperatorTest {
   /**
    * Tests that CAST fails when given a value just outside the valid range for
    * that type. For example,
-   *
    * <ul>
    * <li>CAST(-200 AS TINYINT) fails because the value is less than -128;
    * <li>CAST(1E-999 AS FLOAT) fails because the value underflows;
@@ -9887,16 +10026,16 @@ public class SqlOperatorTest {
     f.checkBoolean("CAST(X'' AS BINARY(3)) = X''", false);
   }
 
-  /** Test that calls all operators with all possible argument types, and for
+  /**
+   * Test that calls all operators with all possible argument types, and for
    * each type, with a set of tricky values.
-   *
    * <p>This is not really a unit test since there are no assertions;
    * it either succeeds or fails in the preparation of the operator case
    * and not when actually testing (validating/executing) the call.
-   *
    * <p>Nevertheless the log messages conceal many problems which potentially
    * need to be fixed especially cases where the query passes from the
-   * validation stage and fails at runtime. */
+   * validation stage and fails at runtime.
+   */
   @Disabled("Too slow and not really a unit test")
   @Tag("slow")
   @Test void testArgumentBounds() {
@@ -9990,7 +10129,8 @@ public class SqlOperatorTest {
                 query = AbstractSqlTester.buildQuery(s);
               }
               f.check(query, SqlTests.ANY_TYPE_CHECKER,
-                  SqlTests.ANY_PARAMETER_CHECKER, result -> { });
+                  SqlTests.ANY_PARAMETER_CHECKER, result -> {
+                  });
             }
           } catch (Throwable e) {
             // Logging the top-level throwable directly makes the message
@@ -10037,7 +10177,6 @@ public class SqlOperatorTest {
    * Result checker that considers a test to have succeeded if it returns a
    * particular value or throws an exception that matches one of a list of
    * patterns.
-   *
    * <p>Sounds peculiar, but is necessary when eager and lazy behaviors are
    * both valid.
    */
@@ -10096,9 +10235,9 @@ public class SqlOperatorTest {
               .with(CalciteConnectionProperty.TYPE_SYSTEM,
                   CustomTimeFrameTypeSystem.class.getName());
       try (TryThreadLocal.Memo ignore =
-               CustomTimeFrameTypeSystem.DELEGATE.push(typeSystem);
-           Connection connection = connectionFactory.createConnection();
-           Statement statement = connection.createStatement()) {
+          CustomTimeFrameTypeSystem.DELEGATE.push(typeSystem);
+          Connection connection = connectionFactory.createConnection();
+          Statement statement = connection.createStatement()) {
         final ResultSet resultSet =
             statement.executeQuery(query);
         resultChecker.checkResult(resultSet);
@@ -10202,10 +10341,10 @@ public class SqlOperatorTest {
     }
   }
 
-  /** Type system whose constructor reads from a thread-local. You must invoke
+  /**
+   * Type system whose constructor reads from a thread-local. You must invoke
    * the constructor in the same thread, but once constructed you can use from
    * other threads.
-   *
    * <p>It's a bit strange, but the best we can do to pass objects via Avatica's
    * plugin system until
    * <a href="https://issues.apache.org/jira/browse/CALCITE-5295">[CALCITE-5295]
@@ -10213,14 +10352,18 @@ public class SqlOperatorTest {
    * ThreadLocal fields</a> is fixed.
    */
   public static class CustomTimeFrameTypeSystem extends DelegatingTypeSystem {
-    /** Assign to this thread-local before you instantiate a FooTypeSystem
+    /**
+     * Assign to this thread-local before you instantiate a FooTypeSystem
      * (in the same thread) and your FooTypeSystem will behave in the same
-     * way. */
+     * way.
+     */
     public static final TryThreadLocal<RelDataTypeSystem> DELEGATE =
         TryThreadLocal.of(DEFAULT);
 
-    /** Creates a CustomTimeFrameTypeSystem, taking a snapshot of
-     * {@link #DELEGATE}. */
+    /**
+     * Creates a CustomTimeFrameTypeSystem, taking a snapshot of
+     * {@link #DELEGATE}.
+     */
     public CustomTimeFrameTypeSystem() {
       super(DELEGATE.get());
     }