From 38ffaa69bbfe14213ba99ea16d33f9ea497e625c Mon Sep 17 00:00:00 2001 From: XuQianJin-Stars Date: Thu, 9 Jan 2020 23:25:03 +0800 Subject: [PATCH 1/4] [CALCITE-3686] Implement bit_not function --- .../adapter/enumerable/RexImpTable.java | 2 ++ .../apache/calcite/runtime/SqlFunctions.java | 6 ++++++ .../org/apache/calcite/sql/SqlDialect.java | 1 + .../calcite/sql/fun/SqlStdOperatorTable.java | 9 +++++++++ .../apache/calcite/util/BuiltInMethod.java | 1 + .../calcite/sql/test/SqlOperatorBaseTest.java | 20 +++++++++++++++++++ core/src/test/resources/sql/functions.iq | 11 ++++++++++ site/_docs/reference.md | 1 + 8 files changed, 51 insertions(+) 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 7ce7c48fa277..c1e156308e28 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 @@ -130,6 +130,7 @@ 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_NOT; 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; @@ -393,6 +394,7 @@ public Expression implement(RexToLixTranslator translator, defineMethod(ASIN, "asin", NullPolicy.STRICT); defineMethod(ATAN, "atan", NullPolicy.STRICT); defineMethod(ATAN2, "atan2", NullPolicy.STRICT); + defineMethod(BIT_NOT, BuiltInMethod.BIT_NOT.method, NullPolicy.STRICT); defineMethod(CBRT, "cbrt", NullPolicy.STRICT); defineMethod(COS, "cos", NullPolicy.STRICT); defineMethod(COT, "cot", NullPolicy.STRICT); 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 6e02ccb96c88..a0e6aa4ce3d9 100644 --- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java +++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java @@ -1072,6 +1072,12 @@ public static long bitAnd(long b0, long b1) { return b0 & b1; } + // ~ + /** Helper function for implementing BIT_NOT */ + public static long bitNot(long b) { + return ~b; + } + // | /** Helper function for implementing BIT_OR */ public static long bitOr(long b0, long b1) { diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java index 590cbba854a3..6bc1abcc2de5 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java @@ -100,6 +100,7 @@ public class SqlDialect { .add(SqlStdOperatorTable.AND) .add(SqlStdOperatorTable.ASIN) .add(SqlStdOperatorTable.BETWEEN) + .add(SqlStdOperatorTable.BIT_NOT) .add(SqlStdOperatorTable.CASE) .add(SqlStdOperatorTable.CAST) .add(SqlStdOperatorTable.CEIL) 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 d586e90261bb..1344a35a69b0 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 @@ -1633,6 +1633,15 @@ public SqlOperandCountRange getOperandCountRange() { OperandTypes.NUMERIC_NUMERIC, SqlFunctionCategory.NUMERIC); + public static final SqlFunction BIT_NOT = + new SqlFunction( + "BIT_NOT", + SqlKind.OTHER_FUNCTION, + ReturnTypes.ARG0, + null, + OperandTypes.INTEGER, + SqlFunctionCategory.NUMERIC); + public static final SqlFunction CBRT = new SqlFunction( "CBRT", 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 92ce6d44f702..15fee7641a6f 100644 --- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java +++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java @@ -408,6 +408,7 @@ public enum BuiltInMethod { LESSER(SqlFunctions.class, "lesser", Comparable.class, Comparable.class), GREATER(SqlFunctions.class, "greater", Comparable.class, Comparable.class), BIT_AND(SqlFunctions.class, "bitAnd", long.class, long.class), + BIT_NOT(SqlFunctions.class, "bitNot", long.class), BIT_OR(SqlFunctions.class, "bitOr", long.class, long.class), BIT_XOR(SqlFunctions.class, "bitXor", long.class, long.class), MODIFIABLE_TABLE_GET_MODIFIABLE_COLLECTION(ModifiableTable.class, 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 6a5bdc0b20c4..fb90287e230e 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 @@ -8810,6 +8810,26 @@ protected void checkAggType(SqlTester tester, String expr, String type) { tester.checkAgg("bit_and(x)", values, 2, 0); } + @Test public void testBitNotFunc() { + tester.setFor(SqlStdOperatorTable.BIT_NOT); + tester.checkFails("bit_not(^*^)", "Unknown identifier '\\*'", false); + tester.checkType("bit_not(1)", "INTEGER NOT NULL"); + tester.checkType("bit_not(CAST(2 AS TINYINT))", "TINYINT NOT NULL"); + tester.checkType("bit_not(CAST(2 AS SMALLINT))", "SMALLINT NOT NULL"); + tester.checkFails("^bit_not(1.2)^", + "Cannot apply 'BIT_NOT' to arguments of type 'BIT_NOT\\(\\)'\\. Supported form\\(s\\): 'BIT_NOT\\(\\)'", + false); + tester.checkFails( + "^bit_not()^", + "Invalid number of arguments to function 'BIT_NOT'. Was expecting 1 arguments", + false); + tester.checkFails( + "^bit_not(1, 2)^", + "Invalid number of arguments to function 'BIT_NOT'. Was expecting 1 arguments", + false); + tester.checkScalar("bit_not(3)", "-4", "INTEGER NOT NULL"); + } + @Test public void testBitOrFunc() { tester.setFor(SqlStdOperatorTable.BIT_OR, VM_FENNEL, VM_JAVA); tester.checkFails("bit_or(^*^)", "Unknown identifier '\\*'", false); diff --git a/core/src/test/resources/sql/functions.iq b/core/src/test/resources/sql/functions.iq index 0ec8646aaf20..047ba50f2115 100644 --- a/core/src/test/resources/sql/functions.iq +++ b/core/src/test/resources/sql/functions.iq @@ -18,6 +18,17 @@ !use mysqlfunc !set outputformat mysql +# BIT_NOT +select bit_not(3); ++--------+ +| EXPR$0 | ++--------+ +| -4 | ++--------+ +(1 row) + +!ok + # MATH Functions # CBRT diff --git a/site/_docs/reference.md b/site/_docs/reference.md index 488056526dc0..b2f02f8bc364 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -1772,6 +1772,7 @@ and `LISTAGG`). | MIN( [ ALL | DISTINCT ] value) | Returns the minimum value of *value* across all input values | ANY_VALUE( [ ALL | DISTINCT ] value) | Returns one of the values of *value* across all input values; this is NOT specified in the SQL standard | BIT_AND( [ ALL | DISTINCT ] value) | Returns the bitwise AND of all non-null input values, or null if none +| BIT_NOT( [ ALL | DISTINCT ] value) | Returns the bitwise NOT of all non-null input values, or null if none | BIT_OR( [ ALL | DISTINCT ] value) | Returns the bitwise OR of all non-null input values, or null if none | BIT_XOR( [ ALL | DISTINCT ] value) | Returns the bitwise XOR of all non-null input values, or null if none | STDDEV_POP( [ ALL | DISTINCT ] numeric) | Returns the population standard deviation of *numeric* across all input values From cadc94aa8bbd61702b2eebbc46a856e7743c1e9a Mon Sep 17 00:00:00 2001 From: XuQianJin-Stars Date: Fri, 10 Jan 2020 21:46:25 +0800 Subject: [PATCH 2/4] [CALCITE-3686] Implement bit_not function --- site/_docs/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/_docs/reference.md b/site/_docs/reference.md index b2f02f8bc364..63c54833b328 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -1222,6 +1222,7 @@ comp: | numeric1 % numeric2 | As *MOD(numeric1, numeric2)* (only in certain [conformance levels]({{ site.apiRoot }}/org/apache/calcite/sql/validate/SqlConformance.html#isPercentRemainderAllowed--)) | POWER(numeric1, numeric2) | Returns *numeric1* raised to the power of *numeric2* | ABS(numeric) | Returns the absolute value of *numeric* +| BIT_NOT(value) | Returns the bitwise NOT of non-null *numeric* | MOD(numeric1, numeric2) | Returns the remainder (modulus) of *numeric1* divided by *numeric2*. The result is negative only if *numeric1* is negative | SQRT(numeric) | Returns the square root of *numeric* | LN(numeric) | Returns the natural logarithm (base *e*) of *numeric* @@ -1772,7 +1773,6 @@ and `LISTAGG`). | MIN( [ ALL | DISTINCT ] value) | Returns the minimum value of *value* across all input values | ANY_VALUE( [ ALL | DISTINCT ] value) | Returns one of the values of *value* across all input values; this is NOT specified in the SQL standard | BIT_AND( [ ALL | DISTINCT ] value) | Returns the bitwise AND of all non-null input values, or null if none -| BIT_NOT( [ ALL | DISTINCT ] value) | Returns the bitwise NOT of all non-null input values, or null if none | BIT_OR( [ ALL | DISTINCT ] value) | Returns the bitwise OR of all non-null input values, or null if none | BIT_XOR( [ ALL | DISTINCT ] value) | Returns the bitwise XOR of all non-null input values, or null if none | STDDEV_POP( [ ALL | DISTINCT ] numeric) | Returns the population standard deviation of *numeric* across all input values From fc6545f8104206ac9c14a06f3caa39d676849884 Mon Sep 17 00:00:00 2001 From: XuQianJin-Stars Date: Fri, 10 Jan 2020 21:55:46 +0800 Subject: [PATCH 3/4] [CALCITE-3686] Implement bit_not function --- core/src/test/resources/sql/functions.iq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/resources/sql/functions.iq b/core/src/test/resources/sql/functions.iq index 047ba50f2115..c684de373ac9 100644 --- a/core/src/test/resources/sql/functions.iq +++ b/core/src/test/resources/sql/functions.iq @@ -23,7 +23,7 @@ select bit_not(3); +--------+ | EXPR$0 | +--------+ -| -4 | +| -4 | +--------+ (1 row) From 8245cf75222cfcd4cd62140336f23ac5ca538c40 Mon Sep 17 00:00:00 2001 From: XuQianJin-Stars Date: Sat, 11 Jan 2020 11:39:56 +0800 Subject: [PATCH 4/4] [CALCITE-3686] Implement bit_not function --- .../apache/calcite/adapter/enumerable/RexImpTable.java | 6 ++++-- .../main/java/org/apache/calcite/sql/SqlDialect.java | 1 - .../apache/calcite/sql/fun/SqlLibraryOperators.java | 10 ++++++++++ .../apache/calcite/sql/fun/SqlStdOperatorTable.java | 9 --------- .../apache/calcite/sql/test/SqlOperatorBaseTest.java | 2 +- site/_docs/reference.md | 2 +- 6 files changed, 16 insertions(+), 14 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 c1e156308e28..64886596e252 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 @@ -94,6 +94,7 @@ import static org.apache.calcite.linq4j.tree.ExpressionType.OrElse; import static org.apache.calcite.linq4j.tree.ExpressionType.Subtract; import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus; +import static org.apache.calcite.sql.fun.SqlLibraryOperators.BIT_NOT; import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHR; import static org.apache.calcite.sql.fun.SqlLibraryOperators.DAYNAME; import static org.apache.calcite.sql.fun.SqlLibraryOperators.DIFFERENCE; @@ -130,7 +131,6 @@ 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_NOT; 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; @@ -394,7 +394,6 @@ public Expression implement(RexToLixTranslator translator, defineMethod(ASIN, "asin", NullPolicy.STRICT); defineMethod(ATAN, "atan", NullPolicy.STRICT); defineMethod(ATAN2, "atan2", NullPolicy.STRICT); - defineMethod(BIT_NOT, BuiltInMethod.BIT_NOT.method, NullPolicy.STRICT); defineMethod(CBRT, "cbrt", NullPolicy.STRICT); defineMethod(COS, "cos", NullPolicy.STRICT); defineMethod(COT, "cot", NullPolicy.STRICT); @@ -408,6 +407,9 @@ public Expression implement(RexToLixTranslator translator, map.put(PI, (translator, call, nullAs) -> Expressions.constant(Math.PI)); + // bitwise + defineMethod(BIT_NOT, BuiltInMethod.BIT_NOT.method, NullPolicy.STRICT); + // datetime defineImplementor(DATETIME_PLUS, NullPolicy.STRICT, new DatetimeArithmeticImplementor(), false); diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java index 6bc1abcc2de5..590cbba854a3 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java @@ -100,7 +100,6 @@ public class SqlDialect { .add(SqlStdOperatorTable.AND) .add(SqlStdOperatorTable.ASIN) .add(SqlStdOperatorTable.BETWEEN) - .add(SqlStdOperatorTable.BIT_NOT) .add(SqlStdOperatorTable.CASE) .add(SqlStdOperatorTable.CAST) .add(SqlStdOperatorTable.CEIL) 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 5ff3cc226363..6a83fc1791e8 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 @@ -255,6 +255,16 @@ private SqlLibraryOperators() { OperandTypes.STRING_STRING, SqlFunctionCategory.STRING); + @LibraryOperator(libraries = {MYSQL}) + public static final SqlFunction BIT_NOT = + new SqlFunction( + "BIT_NOT", + SqlKind.OTHER_FUNCTION, + ReturnTypes.ARG0, + null, + OperandTypes.INTEGER, + SqlFunctionCategory.NUMERIC); + /** The "CONCAT(arg, ...)" function that concatenates strings. * For example, "CONCAT('a', 'bc', 'd')" returns "abcd". */ @LibraryOperator(libraries = {MYSQL, POSTGRESQL, ORACLE}) 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 1344a35a69b0..d586e90261bb 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 @@ -1633,15 +1633,6 @@ public SqlOperandCountRange getOperandCountRange() { OperandTypes.NUMERIC_NUMERIC, SqlFunctionCategory.NUMERIC); - public static final SqlFunction BIT_NOT = - new SqlFunction( - "BIT_NOT", - SqlKind.OTHER_FUNCTION, - ReturnTypes.ARG0, - null, - OperandTypes.INTEGER, - SqlFunctionCategory.NUMERIC); - public static final SqlFunction CBRT = new SqlFunction( "CBRT", 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 fb90287e230e..d8b406157201 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 @@ -8811,7 +8811,7 @@ protected void checkAggType(SqlTester tester, String expr, String type) { } @Test public void testBitNotFunc() { - tester.setFor(SqlStdOperatorTable.BIT_NOT); + SqlTester tester = tester(SqlLibrary.MYSQL); tester.checkFails("bit_not(^*^)", "Unknown identifier '\\*'", false); tester.checkType("bit_not(1)", "INTEGER NOT NULL"); tester.checkType("bit_not(CAST(2 AS TINYINT))", "TINYINT NOT NULL"); diff --git a/site/_docs/reference.md b/site/_docs/reference.md index 63c54833b328..127308d9b296 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -1222,7 +1222,6 @@ comp: | numeric1 % numeric2 | As *MOD(numeric1, numeric2)* (only in certain [conformance levels]({{ site.apiRoot }}/org/apache/calcite/sql/validate/SqlConformance.html#isPercentRemainderAllowed--)) | POWER(numeric1, numeric2) | Returns *numeric1* raised to the power of *numeric2* | ABS(numeric) | Returns the absolute value of *numeric* -| BIT_NOT(value) | Returns the bitwise NOT of non-null *numeric* | MOD(numeric1, numeric2) | Returns the remainder (modulus) of *numeric1* divided by *numeric2*. The result is negative only if *numeric1* is negative | SQRT(numeric) | Returns the square root of *numeric* | LN(numeric) | Returns the natural logarithm (base *e*) of *numeric* @@ -2295,6 +2294,7 @@ semantics. | C | Operator syntax | Description |:- |:-----------------------------------------------|:----------- | p | expr :: type | Casts *expr* to *type* +| m | BIT_NOT(value) | Returns the bitwise NOT of non-null *numeric* | o | CHR(integer) | Returns the character having the binary equivalent to *integer* as a CHAR value | m o p | CONCAT(string [, string ]*) | Concatenates two or more strings | p | CONVERT_TIMEZONE(tz1, tz2, datetime) | Converts the timezone of *datetime* from *tz1* to *tz2*