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 c1288c730da0..dd8860a5c541 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 @@ -115,174 +115,7 @@ import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus; import static org.apache.calcite.sql.fun.SqlInternalOperators.LITERAL_AGG; import static org.apache.calcite.sql.fun.SqlInternalOperators.THROW_UNLESS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ACOSH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAYS_OVERLAP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAYS_ZIP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_AGG; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_APPEND; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_COMPACT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_CONCAT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_CONCAT_AGG; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_CONTAINS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_DISTINCT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_EXCEPT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_INSERT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_INTERSECT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_JOIN; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_LENGTH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_MAX; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_MIN; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_POSITION; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_PREPEND; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REMOVE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REPEAT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REVERSE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_SIZE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_TO_STRING; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_UNION; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ASINH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ATANH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.BIT_GET; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.BIT_LENGTH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.BOOL_AND; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.BOOL_OR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CEIL_BIG_QUERY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHAR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CODE_POINTS_TO_BYTES; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CODE_POINTS_TO_STRING; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.COMPRESS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT2; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT_FUNCTION; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT_FUNCTION_WITH_NULL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT_WS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT_WS_MSSQL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONTAINS_SUBSTR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.COSH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.COTH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CSC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CSCH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.CURRENT_DATETIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATEADD; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATETIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATETIME_TRUNC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATE_FROM_UNIX_DATE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATE_PART; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATE_TRUNC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DAYNAME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.DIFFERENCE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ENDS_WITH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXISTS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXISTS_NODE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXTRACT_VALUE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXTRACT_XML; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FACTORIAL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FIND_IN_SET; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FLOOR_BIG_QUERY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_DATE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_DATETIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_NUMBER; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_TIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_TIMESTAMP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_BASE32; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_BASE64; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_HEX; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.GETBIT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ILIKE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.IS_INF; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.IS_NAN; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_DEPTH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_INSERT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_KEYS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_LENGTH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_PRETTY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_REMOVE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_REPLACE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_SET; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_STORAGE_SIZE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_TYPE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.LEFT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.LEVENSHTEIN; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOG; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOGICAL_AND; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOGICAL_OR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.LPAD; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP_CONCAT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP_ENTRIES; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP_FROM_ARRAYS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP_FROM_ENTRIES; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP_KEYS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAP_VALUES; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MAX_BY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MD5; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MIN_BY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.MONTHNAME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.OFFSET; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.ORDINAL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_DATE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_DATETIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_TIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_TIMESTAMP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_URL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.POW; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_CONTAINS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_EXTRACT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_EXTRACT_ALL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_INSTR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_REPLACE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REPEAT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.REVERSE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.RIGHT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.RLIKE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.RPAD; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_ADD; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_CAST; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_DIVIDE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_MULTIPLY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_NEGATE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_OFFSET; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_ORDINAL; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SAFE_SUBTRACT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SEC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SECH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SHA1; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SHA256; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SHA512; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SINH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SORT_ARRAY; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SOUNDEX; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SOUNDEX_SPARK; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SPACE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.SPLIT; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.STARTS_WITH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.STRCMP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.STR_TO_MAP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TANH; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIME; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIMESTAMP; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIMESTAMP_MICROS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIMESTAMP_MILLIS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIMESTAMP_SECONDS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIMESTAMP_TRUNC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TIME_TRUNC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TO_BASE32; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TO_BASE64; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TO_CHAR; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TO_CODE_POINTS; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TO_HEX; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TRANSLATE3; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TRUNC; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.TRY_CAST; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.UNIX_DATE; -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.URL_DECODE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.URL_ENCODE; -import static org.apache.calcite.sql.fun.SqlLibraryOperators.XML_TRANSFORM; +import static org.apache.calcite.sql.fun.SqlLibraryOperators.*; 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.ALL_EQ; @@ -1041,6 +874,8 @@ Builder populate3() { aggMap.put(LOGICAL_OR, minMax); final Supplier bitop = constructorSupplier(BitOpImplementor.class); + aggMap.put(BITAND_AGG, bitop); + aggMap.put(BITOR_AGG, bitop); aggMap.put(BIT_AND, bitop); aggMap.put(BIT_OR, bitop); aggMap.put(BIT_XOR, bitop); @@ -1793,7 +1628,7 @@ static class BitOpImplementor extends StrictAggImplementor { if (SqlTypeUtil.isBinary(info.returnRelType())) { start = Expressions.field(null, ByteString.class, "EMPTY"); } else { - Object initValue = info.aggregation() == BIT_AND ? -1L : 0; + Object initValue = info.aggregation().kind == SqlKind.BIT_AND ? -1L : 0; start = Expressions.constant(initValue, info.returnType()); } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java index f7d8741491f3..9b38821202c0 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java @@ -43,6 +43,16 @@ public SnowflakeSqlDialect(Context context) { @Override public void unparseCall(final SqlWriter writer, final SqlCall call, final int leftPrec, final int rightPrec) { switch (call.getKind()) { + case BIT_AND: + SqlCall bitAndCall = SqlLibraryOperators.BITAND_AGG + .createCall(SqlParserPos.ZERO, call.getOperandList()); + super.unparseCall(writer, bitAndCall, leftPrec, rightPrec); + break; + case BIT_OR: + SqlCall bitOrCall = SqlLibraryOperators.BITOR_AGG + .createCall(SqlParserPos.ZERO, call.getOperandList()); + super.unparseCall(writer, bitOrCall, leftPrec, rightPrec); + break; case CHAR_LENGTH: SqlCall lengthCall = SqlLibraryOperators.LENGTH .createCall(SqlParserPos.ZERO, call.getOperandList()); diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java index 17eacae87ffb..808724d02d11 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java @@ -39,7 +39,7 @@ public class SqlBitOpAggFunction extends SqlAggFunction { //~ Constructors ----------------------------------------------------------- - /** Creates a SqlBitOpAggFunction. */ + /** Creates a SqlBitOpAggFunction from a SqlKind. */ public SqlBitOpAggFunction(SqlKind kind) { super(kind.name(), null, @@ -56,6 +56,23 @@ public SqlBitOpAggFunction(SqlKind kind) { || kind == SqlKind.BIT_XOR); } + /** Creates a SqlBitOpAggFunction from a name and SqlKind. */ + public SqlBitOpAggFunction(String name, SqlKind kind) { + super(name, + null, + kind, + ReturnTypes.ARG0_NULLABLE_IF_EMPTY, + null, + OperandTypes.INTEGER.or(OperandTypes.BINARY), + SqlFunctionCategory.NUMERIC, + false, + false, + Optionality.FORBIDDEN); + Preconditions.checkArgument(kind == SqlKind.BIT_AND + || kind == SqlKind.BIT_OR + || kind == SqlKind.BIT_XOR); + } + @Override public @Nullable T unwrap(Class clazz) { if (clazz.isInstance(SqlSplittableAggFunction.SelfSplitter.INSTANCE)) { return clazz.cast(SqlSplittableAggFunction.SelfSplitter.INSTANCE); diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java index d4c8b9d1ea96..265084c4f693 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java @@ -2203,6 +2203,18 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding InferTypes.FIRST_KNOWN, OperandTypes.COMPARABLE_UNORDERED_COMPARABLE_UNORDERED); + /** The "BITAND_AGG(expression)" function. Equivalent to + * the standard "BIT_AND(expression)". */ + @LibraryOperator(libraries = {SNOWFLAKE}) + public static final SqlAggFunction BITAND_AGG = + new SqlBitOpAggFunction("BITAND_AGG", SqlKind.BIT_AND); + + /** The "BITOR_AGG(expression)" function. Equivalent to + * the standard "BIT_OR(expression)". */ + @LibraryOperator(libraries = {SNOWFLAKE}) + public static final SqlAggFunction BITOR_AGG = + new SqlBitOpAggFunction("BITOR_AGG", SqlKind.BIT_OR); + /** The "BIT_LENGTH(string or binary)" function. */ @LibraryOperator(libraries = {SPARK}) public static final SqlFunction BIT_LENGTH = 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 d9bc1d27d5c0..ccd946c437f8 100644 --- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java +++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java @@ -137,6 +137,8 @@ private StandardConvertletTable() { addAlias(SqlLibraryOperators.REGEXP_SUBSTR, SqlLibraryOperators.REGEXP_EXTRACT); addAlias(SqlLibraryOperators.ENDSWITH, SqlLibraryOperators.ENDS_WITH); addAlias(SqlLibraryOperators.STARTSWITH, SqlLibraryOperators.STARTS_WITH); + addAlias(SqlLibraryOperators.BITAND_AGG, SqlStdOperatorTable.BIT_AND); + addAlias(SqlLibraryOperators.BITOR_AGG, SqlStdOperatorTable.BIT_OR); // Register convertlets for specific objects. registerOp(SqlStdOperatorTable.CAST, this::convertCast); diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index 7a5bc0c49930..4a17a29cc69b 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -6661,6 +6661,28 @@ private void checkLiteral2(String expression, String expected) { + "CROSS JOIN `foodmart`.`department`"; sql(sql).withMysql().ok(expectedMysql); } + + /** Test case for + * [CALCITE-6205] + * Add BITAND_AGG, BITOR_AGG functions (enabled in Snowflake library). */ + @Test void testBitAndAgg() { + final String query = "select bit_and(\"product_id\")\n" + + "from \"product\""; + final String expectedSnowflake = "SELECT BITAND_AGG(\"product_id\")\n" + + "FROM \"foodmart\".\"product\""; + sql(query).withLibrary(SqlLibrary.SNOWFLAKE).withSnowflake().ok(expectedSnowflake); + } + + /** Test case for + * [CALCITE-6205] + * Add BITAND_AGG, BITOR_AGG functions (enabled in Snowflake library). */ + @Test void testBitOrAgg() { + final String query = "select bit_or(\"product_id\")\n" + + "from \"product\""; + final String expectedSnowflake = "SELECT BITOR_AGG(\"product_id\")\n" + + "FROM \"foodmart\".\"product\""; + sql(query).withLibrary(SqlLibrary.SNOWFLAKE).withSnowflake().ok(expectedSnowflake); + } /** Test case for * [CALCITE-6156] diff --git a/site/_docs/reference.md b/site/_docs/reference.md index 3f9744854398..1ba228d312c9 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -2685,6 +2685,8 @@ In the following: | s | SORT_ARRAY(array [, ascendingOrder]) | Sorts the *array* in ascending or descending order according to the natural ordering of the array elements. The default order is ascending if *ascendingOrder* is not specified. Null elements will be placed at the beginning of the returned array in ascending order or at the end of the returned array in descending order | * | ASINH(numeric) | Returns the inverse hyperbolic sine of *numeric* | * | ATANH(numeric) | Returns the inverse hyperbolic tangent of *numeric* +| f | BITAND_AGG(value) | Equivalent to `BIT_AND(value)` +| f | BITOR_AGG(value) | Equivalent to `BIT_OR(value)` | s | BIT_LENGTH(binary) | Returns the bit length of *binary* | s | BIT_LENGTH(string) | Returns the bit length of *string* | s | BIT_GET(value, position) | Returns the bit (0 or 1) value at the specified *position* of numeric *value*. The positions are numbered from right to left, starting at zero. The *position* argument cannot be negative 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 2eb931d85aad..dad7e878a826 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -13476,76 +13476,106 @@ private static void checkLogicalOrFunc(SqlOperatorFixture f) { f.checkAgg("logical_or(x)", values4, isNullValue()); } + @Test void testBitAndAggFunc() { + final SqlOperatorFixture f = fixture(); + f.setFor(SqlLibraryOperators.BITAND_AGG, VmName.EXPAND); + checkBitAnd(f, FunctionAlias.of(SqlLibraryOperators.BITAND_AGG)); + } + @Test void testBitAndFunc() { final SqlOperatorFixture f = fixture(); - f.setFor(SqlStdOperatorTable.BIT_AND, VM_FENNEL, VM_JAVA); - f.checkFails("bit_and(^*^)", "Unknown identifier '\\*'", false); - f.checkType("bit_and(1)", "INTEGER"); - f.checkType("bit_and(CAST(2 AS TINYINT))", "TINYINT"); - f.checkType("bit_and(CAST(2 AS SMALLINT))", "SMALLINT"); - f.checkType("bit_and(distinct CAST(2 AS BIGINT))", "BIGINT"); - f.checkType("bit_and(CAST(x'02' AS BINARY(1)))", "BINARY(1)"); - f.checkFails("^bit_and(1.2)^", - "Cannot apply 'BIT_AND' to arguments of type 'BIT_AND\\(\\)'\\. Supported form\\(s\\): 'BIT_AND\\(\\)'\n" - + "'BIT_AND\\(\\)'", - false); - f.checkFails("^bit_and()^", - "Invalid number of arguments to function 'BIT_AND'. Was expecting 1 arguments", - false); - f.checkFails("^bit_and(1, 2)^", - "Invalid number of arguments to function 'BIT_AND'. Was expecting 1 arguments", - false); - final String[] values = {"3", "2", "2"}; - f.checkAgg("bit_and(x)", values, isSingle("2")); - final String[] binaryValues = { - "CAST(x'03' AS BINARY)", - "cast(x'02' as BINARY)", - "cast(x'02' 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.setFor(SqlStdOperatorTable.BIT_AND, VmName.EXPAND); + checkBitAnd(f, FunctionAlias.of(SqlStdOperatorTable.BIT_AND)); + } + + /** Tests the {@code BIT_AND} and {@code BITAND_AGG} operators. */ + void checkBitAnd(SqlOperatorFixture f0, FunctionAlias functionAlias) { + final SqlFunction function = functionAlias.function; + final String fn = function.getName(); + final Consumer consumer = f -> { + f.checkFails(fn + "(^*^)", "Unknown identifier '\\*'", false); + f.checkType(fn + "(1)", "INTEGER"); + f.checkType(fn + "(CAST(2 AS TINYINT))", "TINYINT"); + f.checkType(fn + "(CAST(2 AS SMALLINT))", "SMALLINT"); + f.checkType(fn + "(distinct CAST(2 AS BIGINT))", "BIGINT"); + f.checkType(fn + "(CAST(x'02' AS BINARY(1)))", "BINARY(1)"); + f.checkFails("^" + fn + "(1.2)^", + "Cannot apply '" + fn + "' to arguments of type '" + + fn + "\\(\\)'\\. Supported form\\(s\\): '" + + fn + "\\(\\)'\n" + + "'" + fn + "\\(\\)'", + false); + f.checkFails("^" + fn + "()^", + "Invalid number of arguments to function '" + fn + "'. Was expecting 1 arguments", + false); + f.checkFails("^" + fn + "(1, 2)^", + "Invalid number of arguments to function '" + fn + "'. Was expecting 1 arguments", + false); + final String[] values = {"3", "2", "2"}; + f.checkAgg(fn + "(x)", values, isSingle("2")); + final String[] binaryValues = { + "CAST(x'03' AS BINARY)", + "cast(x'02' as BINARY)", + "cast(x'02' AS BINARY)", + "cast(null AS BINARY)"}; + f.checkAgg(fn + "(x)", binaryValues, isSingle("02")); + f.checkAgg(fn + "(x)", new String[]{"CAST(x'02' AS BINARY)"}, isSingle("02")); + f.checkAggFails(fn + "(x)", + new String[]{"CAST(x'0201' AS VARBINARY)", "CAST(x'02' AS VARBINARY)"}, + "Error while executing SQL .*" + + " Different length for bitwise operands: the first: 2, the second: 1", + true); + }; + f0.forEachLibrary(list(functionAlias.libraries), consumer); } - @Test void testBitAndFuncRuntimeFails() { + @Test void testBitOrAggFunc() { final SqlOperatorFixture f = fixture(); - f.checkAggFails("bit_and(x)", - new String[]{"CAST(x'0201' AS VARBINARY)", "CAST(x'02' AS VARBINARY)"}, - "Error while executing SQL .*" - + " Different length for bitwise operands: the first: 2, the second: 1", - true); + f.setFor(SqlLibraryOperators.BITOR_AGG, VmName.EXPAND); + checkBitOr(f, FunctionAlias.of(SqlLibraryOperators.BITOR_AGG)); } @Test void testBitOrFunc() { final SqlOperatorFixture f = fixture(); - f.setFor(SqlStdOperatorTable.BIT_OR, VM_FENNEL, VM_JAVA); - f.checkFails("bit_or(^*^)", "Unknown identifier '\\*'", false); - f.checkType("bit_or(1)", "INTEGER"); - f.checkType("bit_or(CAST(2 AS TINYINT))", "TINYINT"); - f.checkType("bit_or(CAST(2 AS SMALLINT))", "SMALLINT"); - f.checkType("bit_or(distinct CAST(2 AS BIGINT))", "BIGINT"); - f.checkType("bit_or(CAST(x'02' AS BINARY(1)))", "BINARY(1)"); - f.checkFails("^bit_or(1.2)^", - "Cannot apply 'BIT_OR' to arguments of type " - + "'BIT_OR\\(\\)'\\. Supported form\\(s\\): " - + "'BIT_OR\\(\\)'\n" - + "'BIT_OR\\(\\)'", - false); - f.checkFails("^bit_or()^", - "Invalid number of arguments to function 'BIT_OR'. Was expecting 1 arguments", - false); - f.checkFails("^bit_or(1, 2)^", - "Invalid number of arguments to function 'BIT_OR'. Was expecting 1 arguments", - false); - final String[] values = {"1", "2", "2"}; - f.checkAgg("bit_or(x)", values, isSingle(3)); - final String[] binaryValues = { - "CAST(x'01' AS BINARY)", - "cast(x'02' as BINARY)", - "cast(x'02' 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")); + f.setFor(SqlStdOperatorTable.BIT_OR, VmName.EXPAND); + checkBitOr(f, FunctionAlias.of(SqlStdOperatorTable.BIT_OR)); + } + + /** Tests the {@code BIT_OR} and {@code BITOR_AGG} operators. */ + void checkBitOr(SqlOperatorFixture f0, FunctionAlias functionAlias) { + final SqlFunction function = functionAlias.function; + final String fn = function.getName(); + final Consumer consumer = f -> { + f.checkFails(fn + "(^*^)", "Unknown identifier '\\*'", false); + f.checkType(fn + "(1)", "INTEGER"); + f.checkType(fn + "(CAST(2 AS TINYINT))", "TINYINT"); + f.checkType(fn + "(CAST(2 AS SMALLINT))", "SMALLINT"); + f.checkType(fn + "(distinct CAST(2 AS BIGINT))", "BIGINT"); + f.checkType(fn + "(CAST(x'02' AS BINARY(1)))", "BINARY(1)"); + f.checkFails("^" + fn + "(1.2)^", + "Cannot apply '" + fn + "' to arguments of type " + + "'" + fn + "\\(\\)'\\. Supported form\\(s\\): " + + "'" + fn + "\\(\\)'\n" + + "'" + fn + "\\(\\)'", + false); + f.checkFails("^" + fn + "()^", + "Invalid number of arguments to function '" + fn + "'. Was expecting 1 arguments", + false); + f.checkFails("^" + fn + "(1, 2)^", + "Invalid number of arguments to function '" + fn + "'. Was expecting 1 arguments", + false); + final String[] values = {"1", "2", "2"}; + f.checkAgg("bit_or(x)", values, isSingle(3)); + final String[] binaryValues = { + "CAST(x'01' AS BINARY)", + "cast(x'02' as BINARY)", + "cast(x'02' AS BINARY)", + "cast(null AS BINARY)"}; + f.checkAgg(fn + "(x)", binaryValues, isSingle("03")); + f.checkAgg(fn + "(x)", new String[]{"CAST(x'02' AS BINARY)"}, + isSingle("02")); + }; + f0.forEachLibrary(list(functionAlias.libraries), consumer); } @Test void testBitXorFunc() {