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

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


The following commit(s) were added to refs/heads/master by this push:
     new f11115a  [CALCITE-3815] Add missing SQL standard aggregate functions: 
EVERY, SOME, INTERSECTION
f11115a is described below

commit f11115a2fe9e360f38910f112288581040e0ced5
Author: Hanumath Maduri <[email protected]>
AuthorDate: Sat Mar 7 21:35:38 2020 -0800

    [CALCITE-3815] Add missing SQL standard aggregate functions: EVERY, SOME, 
INTERSECTION
---
 core/src/main/codegen/templates/Parser.jj          |  3 +
 .../calcite/adapter/enumerable/RexImpTable.java    | 41 +++++++++++
 .../main/java/org/apache/calcite/sql/SqlKind.java  |  6 +-
 .../calcite/sql/fun/SqlMinMaxAggFunction.java      | 11 ++-
 .../calcite/sql/fun/SqlStdOperatorTable.java       | 24 +++++++
 .../org/apache/calcite/util/BuiltInMethod.java     |  1 +
 .../apache/calcite/sql/parser/SqlParserTest.java   | 16 ++++-
 .../apache/calcite/sql/test/SqlAdvisorTest.java    |  6 ++
 .../calcite/sql/test/SqlOperatorBaseTest.java      | 79 ++++++++++++++++++++++
 .../apache/calcite/test/SqlToRelConverterTest.java |  7 ++
 .../org/apache/calcite/test/SqlValidatorTest.java  | 10 +++
 .../apache/calcite/test/SqlToRelConverterTest.xml  | 13 ++++
 core/src/test/resources/sql/agg.iq                 | 22 ++++++
 site/_docs/reference.md                            |  3 +
 14 files changed, 236 insertions(+), 6 deletions(-)

diff --git a/core/src/main/codegen/templates/Parser.jj 
b/core/src/main/codegen/templates/Parser.jj
index 1946c63..eebd80c 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -6401,10 +6401,12 @@ SqlIdentifier ReservedFunctionName() :
     |   <CURRENT_TIMESTAMP>
     |   <DENSE_RANK>
     |   <ELEMENT>
+    |   <EVERY>
     |   <EXP>
     |   <FIRST_VALUE>
     |   <FLOOR>
     |   <FUSION>
+    |   <INTERSECTION>
     |   <GROUPING>
     |   <HOUR>
     |   <LAG>
@@ -6433,6 +6435,7 @@ SqlIdentifier ReservedFunctionName() :
     |   <RIGHT>
     |   <ROW_NUMBER>
     |   <SECOND>
+    |   <SOME>
     |   <SQRT>
     |   <STDDEV_POP>
     |   <STDDEV_SAMP>
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 795048f..629e2bd 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
@@ -167,6 +167,7 @@ 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;
@@ -177,6 +178,7 @@ import static 
org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN_OR_EQU
 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.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;
@@ -263,6 +265,7 @@ 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;
@@ -623,6 +626,8 @@ public class RexImpTable {
     aggMap.put(MIN, minMax);
     aggMap.put(MAX, minMax);
     aggMap.put(ANY_VALUE, minMax);
+    aggMap.put(SOME, minMax);
+    aggMap.put(EVERY, minMax);
     final Supplier<BitOpImplementor> bitop = 
constructorSupplier(BitOpImplementor.class);
     aggMap.put(BIT_AND, bitop);
     aggMap.put(BIT_OR, bitop);
@@ -631,6 +636,7 @@ public class RexImpTable {
     aggMap.put(COLLECT, constructorSupplier(CollectImplementor.class));
     aggMap.put(LISTAGG, constructorSupplier(ListaggImplementor.class));
     aggMap.put(FUSION, constructorSupplier(FusionImplementor.class));
+    aggMap.put(INTERSECTION, 
constructorSupplier(IntersectionImplementor.class));
     final Supplier<GroupingImplementor> grouping =
         constructorSupplier(GroupingImplementor.class);
     aggMap.put(GROUPING, grouping);
@@ -1542,6 +1548,41 @@ public class RexImpTable {
     }
   }
 
+  /** Implementor for the {@code INTERSECTION} aggregate function. */
+  static class IntersectionImplementor extends StrictAggImplementor {
+    @Override protected void implementNotNullReset(AggContext info, 
AggResetContext reset) {
+      reset.currentBlock().add(
+          Expressions.statement(
+              Expressions.assign(reset.accumulator().get(0), 
Expressions.constant(null))));
+    }
+
+    @Override public void implementNotNullAdd(AggContext info, AggAddContext 
add) {
+      BlockBuilder accumulatorIsNull = new BlockBuilder();
+      accumulatorIsNull.add(
+          Expressions.statement(
+              Expressions.assign(add.accumulator().get(0), 
Expressions.new_(ArrayList.class))));
+      accumulatorIsNull.add(
+          Expressions.statement(
+              Expressions.call(add.accumulator().get(0),
+                  BuiltInMethod.COLLECTION_ADDALL.method, 
add.arguments().get(0))));
+
+      BlockBuilder accumulatorNotNull = new BlockBuilder();
+      accumulatorNotNull.add(
+          Expressions.statement(
+              Expressions.call(add.accumulator().get(0),
+                  BuiltInMethod.COLLECTION_RETAIN_ALL.method,
+                  add.arguments().get(0))
+          )
+      );
+
+      add.currentBlock().add(
+          Expressions.ifThenElse(
+              Expressions.equal(add.accumulator().get(0), 
Expressions.constant(null)),
+              accumulatorIsNull.toBlock(),
+              accumulatorNotNull.toBlock()));
+    }
+  }
+
   /** Implementor for the {@code FUSION} aggregate function. */
   static class FusionImplementor extends StrictAggImplementor {
     @Override protected void implementNotNullReset(AggContext info,
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlKind.java 
b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
index d5ac533..b3e42a8 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -966,6 +966,9 @@ public enum SqlKind {
   /** The {@code FUSION} aggregate function. */
   FUSION,
 
+  /** The {@code INTERSECTION} aggregate function. */
+  INTERSECTION,
+
   /** The {@code SINGLE_VALUE} aggregate function. */
   SINGLE_VALUE,
 
@@ -1161,7 +1164,8 @@ public enum SqlKind {
           LAST_VALUE, COVAR_POP, COVAR_SAMP, REGR_COUNT, REGR_SXX, REGR_SYY,
           AVG, STDDEV_POP, STDDEV_SAMP, VAR_POP, VAR_SAMP, NTILE, COLLECT,
           FUSION, SINGLE_VALUE, ROW_NUMBER, RANK, PERCENT_RANK, DENSE_RANK,
-          CUME_DIST, JSON_ARRAYAGG, JSON_OBJECTAGG, BIT_AND, BIT_OR, BIT_XOR, 
LISTAGG);
+          CUME_DIST, JSON_ARRAYAGG, JSON_OBJECTAGG, BIT_AND, BIT_OR, BIT_XOR,
+          LISTAGG, INTERSECTION, ANY_VALUE);
 
   /**
    * Category consisting of all DML operators.
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java
index e71d990..f6c3b22 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java
@@ -24,6 +24,7 @@ import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlSplittableAggFunction;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlOperandTypeChecker;
 import org.apache.calcite.util.Optionality;
 
 import com.google.common.base.Preconditions;
@@ -68,12 +69,18 @@ public class SqlMinMaxAggFunction extends SqlAggFunction {
 
   /** Creates a SqlMinMaxAggFunction. */
   public SqlMinMaxAggFunction(SqlKind kind) {
-    super(kind.name(),
+    this(kind.name(), kind, OperandTypes.COMPARABLE_ORDERED);
+  }
+
+  /** Creates a SqlMinMaxAggFunction. */
+  public SqlMinMaxAggFunction(String funcName, SqlKind kind,
+      SqlOperandTypeChecker inputTypeChecker) {
+    super(funcName,
         null,
         kind,
         ReturnTypes.ARG0_NULLABLE_IF_EMPTY,
         null,
-        OperandTypes.COMPARABLE_ORDERED,
+        inputTypeChecker,
         SqlFunctionCategory.SYSTEM,
         false,
         false,
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 91dc944..e0ec497 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
@@ -943,6 +943,18 @@ public class SqlStdOperatorTable extends 
ReflectiveSqlOperatorTable {
       new SqlMinMaxAggFunction(SqlKind.MAX);
 
   /**
+   * <code>EVERY</code> aggregate function.
+   */
+  public static final SqlAggFunction EVERY =
+      new SqlMinMaxAggFunction("EVERY", SqlKind.MIN, OperandTypes.BOOLEAN);
+
+  /**
+   * <code>SOME</code> aggregate function.
+   */
+  public static final SqlAggFunction SOME =
+      new SqlMinMaxAggFunction("SOME", SqlKind.MAX, OperandTypes.BOOLEAN);
+
+  /**
    * <code>LAST_VALUE</code> aggregate function.
    */
   public static final SqlAggFunction LAST_VALUE =
@@ -2219,6 +2231,18 @@ public class SqlStdOperatorTable extends 
ReflectiveSqlOperatorTable {
       };
 
   /**
+   * The INTERSECTION operator. Multiset aggregator function.
+   */
+  public static final SqlAggFunction INTERSECTION =
+      new SqlAggFunction("INTERSECTION", null,
+          SqlKind.INTERSECTION,
+          ReturnTypes.ARG0,
+          null,
+          OperandTypes.MULTISET,
+          SqlFunctionCategory.SYSTEM, false, false,
+          Optionality.FORBIDDEN) {
+      };
+  /**
    * The sequence next value function: <code>NEXT VALUE FOR sequence</code>
    */
   public static final SqlOperator NEXT_VALUE =
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 7d30ac5..bb226a0 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -287,6 +287,7 @@ public enum BuiltInMethod {
   MAP_PUT(Map.class, "put", Object.class, Object.class),
   COLLECTION_ADD(Collection.class, "add", Object.class),
   COLLECTION_ADDALL(Collection.class, "addAll", Collection.class),
+  COLLECTION_RETAIN_ALL(Collection.class, "retainAll", Collection.class),
   LIST_GET(List.class, "get", int.class),
   ITERATOR_HAS_NEXT(Iterator.class, "hasNext"),
   ITERATOR_NEXT(Iterator.class, "next"),
diff --git 
a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java 
b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 83ff169..e96bf6b 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -2139,6 +2139,12 @@ public class SqlParserTest {
             + "FROM `DEPT`))");
   }
 
+  @Test public void testSomeEveryAndIntersectionAggQuery() {
+    sql("select some(deptno = 10), every(deptno > 0), 
intersection(multiset[1,2]) from dept")
+        .ok("SELECT SOME((`DEPTNO` = 10)), EVERY((`DEPTNO` > 0)), 
INTERSECTION((MULTISET[1, 2]))\n"
+            + "FROM `DEPT`");
+  }
+
   /**
    * Tricky for the parser - looks like "IN (scalar, scalar)" but isn't.
    */
@@ -2184,11 +2190,15 @@ public class SqlParserTest {
 
     final String sql3 = "select * from emp\n"
         + "where name like (select ^some^ name from emp)";
-    sql(sql3).fails("(?s).*Encountered \"some\" at .*");
+    sql(sql3).fails("(?s).*Encountered \"some name\" at .*");
 
     final String sql4 = "select * from emp\n"
-        + "where name ^like^ some (select name from emp)";
-    sql(sql4).fails("(?s).*Encountered \"like some\" at .*");
+        + "where name like some (select name from emp)";
+    final String expected4 = "SELECT *\n"
+        + "FROM `EMP`\n"
+        + "WHERE (`NAME` LIKE SOME((SELECT `NAME`\n"
+        +  "FROM `EMP`)))";
+    sql(sql4).ok(expected4);
 
     final String sql5 = "select * from emp where empno = any (10,20)";
     final String expected5 = "SELECT *\n"
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java 
b/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java
index 09fc285..b0e5761 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java
@@ -152,6 +152,7 @@ public class SqlAdvisorTest extends SqlValidatorTestCase {
           "KEYWORD(DATE)",
           "KEYWORD(DENSE_RANK)",
           "KEYWORD(ELEMENT)",
+          "KEYWORD(EVERY)",
           "KEYWORD(EXISTS)",
           "KEYWORD(EXP)",
           "KEYWORD(EXTRACT)",
@@ -161,6 +162,7 @@ public class SqlAdvisorTest extends SqlValidatorTestCase {
           "KEYWORD(FUSION)",
           "KEYWORD(GROUPING)",
           "KEYWORD(HOUR)",
+          "KEYWORD(INTERSECTION)",
           "KEYWORD(INTERVAL)",
           "KEYWORD(JSON_ARRAY)",
           "KEYWORD(JSON_ARRAYAGG)",
@@ -208,6 +210,7 @@ public class SqlAdvisorTest extends SqlValidatorTestCase {
           "KEYWORD(RUNNING)",
           "KEYWORD(SECOND)",
           "KEYWORD(SESSION_USER)",
+          "KEYWORD(SOME)",
           "KEYWORD(SPECIFIC)",
           "KEYWORD(SQRT)",
           "KEYWORD(SUBSTRING)",
@@ -1295,6 +1298,7 @@ public class SqlAdvisorTest extends SqlValidatorTestCase {
         "COLUMN(EMPNO)\n"
             + "COLUMN(ENAME)\n"
             + "KEYWORD(ELEMENT)\n"
+            + "KEYWORD(EVERY)\n"
             + "KEYWORD(EXISTS)\n"
             + "KEYWORD(EXP)\n"
             + "KEYWORD(EXTRACT)\n"
@@ -1308,6 +1312,7 @@ public class SqlAdvisorTest extends SqlValidatorTestCase {
         "COLUMN(EMPNO)\n"
             + "COLUMN(ENAME)\n"
             + "KEYWORD(ELEMENT)\n"
+            + "KEYWORD(EVERY)\n"
             + "KEYWORD(EXISTS)\n"
             + "KEYWORD(EXP)\n"
             + "KEYWORD(EXTRACT)\n"
@@ -1321,6 +1326,7 @@ public class SqlAdvisorTest extends SqlValidatorTestCase {
         "COLUMN(EMPNO)\n"
             + "COLUMN(ENAME)\n"
             + "KEYWORD(ELEMENT)\n"
+            + "KEYWORD(EVERY)\n"
             + "KEYWORD(EXISTS)\n"
             + "KEYWORD(EXP)\n"
             + "KEYWORD(EXTRACT)\n"
diff --git 
a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java 
b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index ca67272..8ad9f30 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -6944,6 +6944,28 @@ public abstract class SqlOperatorBaseTest {
 
   @Test public void testFusionFunc() {
     tester.setFor(SqlStdOperatorTable.FUSION, VM_FENNEL, VM_JAVA);
+    tester.checkFails("fusion(^*^)", "Unknown identifier '\\*'", false);
+    checkAggType(tester, "fusion(MULTISET[1,2,3])", "INTEGER NOT NULL MULTISET 
NOT NULL");
+    strictTester.checkFails("^fusion(12)^",
+        "Cannot apply 'FUSION' to arguments of type .*", false);
+    final String[] values1 = {"MULTISET[0]", "MULTISET[1]", "MULTISET[2]", 
"MULTISET[3]"};
+    tester.checkAgg("fusion(x)", values1, "[0, 1, 2, 3]", 0);
+    final String[] values2 = {"MULTISET[0,1]", "MULTISET[1, 2]"};
+    tester.checkAgg("fusion(x)", values2, "[0, 1, 1, 2]", 0);
+  }
+
+  @Test public void testIntersectionFunc() {
+    tester.setFor(SqlStdOperatorTable.INTERSECTION, VM_FENNEL, VM_JAVA);
+    tester.checkFails("intersection(^*^)", "Unknown identifier '\\*'", false);
+    checkAggType(tester, "intersection(MULTISET[1,2,3])", "INTEGER NOT NULL 
MULTISET NOT NULL");
+    strictTester.checkFails("^intersection(12)^",
+        "Cannot apply 'INTERSECTION' to arguments of type .*", false);
+    final String[] values1 = {"MULTISET[0]", "MULTISET[1]", "MULTISET[2]", 
"MULTISET[3]"};
+    tester.checkAgg("intersection(x)", values1, "[]", 0);
+    final String[] values2 = {"MULTISET[0, 1]", "MULTISET[1, 2]"};
+    tester.checkAgg("intersection(x)", values2, "[1]", 0);
+    final String[] values3 = {"MULTISET[0, 1, 1]", "MULTISET[0, 1, 2]"};
+    tester.checkAgg("intersection(x)", values3, "[0, 1, 1]", 0);
   }
 
   @Test public void testYear() {
@@ -8868,6 +8890,63 @@ public abstract class SqlOperatorBaseTest {
         0d);
   }
 
+  @Test public void testEveryFunc() {
+    tester.setFor(SqlStdOperatorTable.EVERY, VM_EXPAND);
+    tester.checkFails(
+        "every(^*^)",
+        "Unknown identifier '\\*'",
+        false);
+    tester.checkType("every(1 = 1)", "BOOLEAN");
+    tester.checkType("every(1.2 = 1.2)", "BOOLEAN");
+    tester.checkType("every(1.5 = 1.4)", "BOOLEAN");
+    tester.checkFails(
+        "^every()^",
+        "Invalid number of arguments to function 'EVERY'. Was expecting 1 
arguments",
+        false);
+    tester.checkFails(
+        "^every(1, 2)^",
+        "Invalid number of arguments to function 'EVERY'. Was expecting 1 
arguments",
+        false);
+    final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2"};
+    if (!enable) {
+      return;
+    }
+    tester.checkAgg(
+        "every(x = 2)",
+        values,
+        "false",
+        0d);
+  }
+
+  @Test public void testSomeAggFunc() {
+    tester.setFor(SqlStdOperatorTable.SOME, VM_EXPAND);
+    tester.checkFails(
+        "some(^*^)",
+        "Unknown identifier '\\*'",
+        false);
+    tester.checkType("some(1 = 1)", "BOOLEAN");
+    tester.checkType("some(1.2 = 1.2)", "BOOLEAN");
+    tester.checkType("some(1.5 = 1.4)", "BOOLEAN");
+    tester.checkFails(
+        "^some()^",
+        "Invalid number of arguments to function 'SOME'. Was expecting 1 
arguments",
+        false);
+    tester.checkFails(
+        "^some(1, 2)^",
+        "Invalid number of arguments to function 'SOME'. Was expecting 1 
arguments",
+        false);
+    final String[] values = {"0", "CAST(null AS INTEGER)", "2", "2"};
+    if (!enable) {
+      return;
+    }
+    tester.checkAgg(
+        "some(x = 2)",
+        values,
+        "true",
+        0d);
+  }
+
+
   @Test public void testAnyValueFunc() {
     tester.setFor(SqlStdOperatorTable.ANY_VALUE, VM_EXPAND);
     tester.checkFails(
diff --git 
a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index 993a5e2..698c748 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -3205,6 +3205,13 @@ public class SqlToRelConverterTest extends 
SqlToRelTestBase {
     sql(sql).ok();
   }
 
+  @Test public void testSomeAndEveryAggregateFunctions() throws Exception {
+    final String sql = "SELECT some(empno = 130) as someempnoexists,\n"
+        + " every(empno > 0) as everyempnogtzero\n"
+        + " FROM emp AS e group by e.sal";
+    sql(sql).ok();
+  }
+
   private Tester getExtendedTester() {
     return tester.withCatalogReaderFactory(MockCatalogReaderExtended::new);
   }
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index dc9a50d..0be6a60 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -7831,6 +7831,16 @@ public class SqlValidatorTest extends 
SqlValidatorTestCase {
     sql("SELECT MAX(5) FROM emp").ok();
   }
 
+  @Test public void testSomeEveryAndIntersectionFunctions() {
+    sql("select some(sal = 100), every(sal > 0), intersection(multiset[1,2]) 
from emp").ok();
+    sql("select some(sal = 100), ^empno^ from emp")
+        .fails("Expression 'EMPNO' is not being grouped");
+    sql("select every(sal > 0), ^empno^ from emp")
+        .fails("Expression 'EMPNO' is not being grouped");
+    sql("select intersection(multiset[1]), ^empno^ from emp")
+        .fails("Expression 'EMPNO' is not being grouped");
+  }
+
   @Test public void testAnyValueFunction() {
     sql("SELECT any_value(ename) from emp").ok();
   }
diff --git 
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml 
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 2f00acf..7e4ad68 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -6052,6 +6052,19 @@ LogicalProject(C1=[$1])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testSomeAndEveryAggregateFunctions">
+        <Resource name="sql">
+            <![CDATA[]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(SOMEEMPNOEXISTS=[$1], EVERYEMPNOGTZERO=[$2])
+  LogicalAggregate(group=[{0}], SOMEEMPNOEXISTS=[SOME($1)], 
EVERYEMPNOGTZERO=[EVERY($2)])
+    LogicalProject(SAL=[$5], $f1=[=($0, 130)], $f2=[>($0, 0)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testAnyValueAggregateFunctionNoGroupBy">
         <Resource name="sql">
             <![CDATA[SELECT any_value(empno) as anyempno FROM emp AS e]]>
diff --git a/core/src/test/resources/sql/agg.iq 
b/core/src/test/resources/sql/agg.iq
index 8b3fd9c..398ebea 100644
--- a/core/src/test/resources/sql/agg.iq
+++ b/core/src/test/resources/sql/agg.iq
@@ -159,6 +159,28 @@ select stddev_samp(deptno) as s from emp;
 
 !ok
 
+# [CALCITE-3815] Add missing SQL standard aggregate
+# functions: EVERY, SOME, INTERSECTION
+select some(deptno = 100), every(deptno > 0), intersection(multiset[1, 2]) 
from emp;
++--------+--------+--------+
+| EXPR$0 | EXPR$1 | EXPR$2 |
++--------+--------+--------+
+| false  | true   | [1, 2] |
++--------+--------+--------+
+(1 row)
+
+!ok
+
+select some(deptno > 100), every(deptno > 0) from emp where deptno > 1000;
++--------+--------+
+| EXPR$0 | EXPR$1 |
++--------+--------+
+|        |        |
++--------+--------+
+(1 row)
+
+!ok
+
 # stddev_pop
 select stddev_pop(deptno) as s from emp;
 +----+
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 6e6402d..b0dbace 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -1766,12 +1766,15 @@ and `LISTAGG`).
 | COUNT( [ ALL &#124; DISTINCT ] value [, value ]*) | Returns the number of 
input rows for which *value* is not null (wholly not null if *value* is 
composite)
 | COUNT(*)                           | Returns the number of input rows
 | FUSION(multiset)                   | Returns the multiset union of 
*multiset* across all input values
+| INTERSECTION(multiset)             | Returns the multiset intersection of 
*multiset* across all input values
 | APPROX_COUNT_DISTINCT(value [, value ]*)      | Returns the approximate 
number of distinct values of *value*; the database is allowed to use an 
approximation but is not required to
 | AVG( [ ALL &#124; DISTINCT ] numeric)         | Returns the average 
(arithmetic mean) of *numeric* across all input values
 | SUM( [ ALL &#124; DISTINCT ] numeric)         | Returns the sum of *numeric* 
across all input values
 | MAX( [ ALL &#124; DISTINCT ] value)           | Returns the maximum value of 
*value* across all input values
 | MIN( [ ALL &#124; DISTINCT ] value)           | Returns the minimum value of 
*value* across all input values
 | ANY_VALUE( [ ALL &#124; DISTINCT ] value)     | Returns one of the values of 
*value* across all input values; this is NOT specified in the SQL standard
+| SOME(condition)                               | Returns true if any 
condition is true.
+| EVERY(condition)                              | Returns true if all 
conditions are true.
 | BIT_AND( [ ALL &#124; DISTINCT ] value)       | Returns the bitwise AND of 
all non-null input values, or null if none
 | BIT_OR( [ ALL &#124; DISTINCT ] value)        | Returns the bitwise OR of 
all non-null input values, or null if none
 | BIT_XOR( [ ALL &#124; DISTINCT ] value)       | Returns the bitwise XOR of 
all non-null input values, or null if none

Reply via email to