diff --git a/core/src/main/java/io/questdb/griffin/ExpressionParser.java b/core/src/main/java/io/questdb/griffin/ExpressionParser.java index a78d2202b3830c2d9c103c4298278a30109d7e94..db63737eab95b48a4f73e1bfb32bbf559200a15d 100644 --- a/core/src/main/java/io/questdb/griffin/ExpressionParser.java +++ b/core/src/main/java/io/questdb/griffin/ExpressionParser.java @@ -679,7 +679,7 @@ class ExpressionParser { int operatorType = op.type; - if (thisChar == '-') { + if (thisChar == '-' || thisChar == '~') { switch (prevBranch) { case BRANCH_OPERATOR: case BRANCH_LEFT_BRACE: diff --git a/core/src/main/java/io/questdb/griffin/OperatorExpression.java b/core/src/main/java/io/questdb/griffin/OperatorExpression.java index 8c1a9f1d4c1f45cb1bfa37bcc43dc87ae4d939cf..84484ac50c9c9cf34348b64d4c4f5f08b19a9955 100644 --- a/core/src/main/java/io/questdb/griffin/OperatorExpression.java +++ b/core/src/main/java/io/questdb/griffin/OperatorExpression.java @@ -37,7 +37,6 @@ public final class OperatorExpression { static final ObjList operators = new ObjList() {{ add(new OperatorExpression(".", DOT_PRECEDENCE, false, BINARY)); add(new OperatorExpression("::", DOT_PRECEDENCE, false, BINARY)); - add(new OperatorExpression("^", 2, false, BINARY)); add(new OperatorExpression("*", 3, true, BINARY)); add(new OperatorExpression("/", 3, true, BINARY)); add(new OperatorExpression("%", 3, true, BINARY)); @@ -55,6 +54,9 @@ public final class OperatorExpression { add(new OperatorExpression("!~", 7, true, BINARY)); add(new OperatorExpression("in", 7, true, SET, false)); add(new OperatorExpression("between", 7, true, SET, false)); + add(new OperatorExpression("&", 8, true, BINARY)); + add(new OperatorExpression("^", 9, false, BINARY)); + add(new OperatorExpression("|", 10, true, BINARY)); add(new OperatorExpression("and", 11, true, BINARY, false)); add(new OperatorExpression("or", 11, true, BINARY, false)); add(new OperatorExpression("not", 11, true, UNARY, false)); diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseAndIntFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseAndIntFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..f60df57e4db07dcea21bb7ea3549430ca9dc6f71 --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseAndIntFunctionFactory.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.BinaryFunction; +import io.questdb.griffin.engine.functions.IntFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseAndIntFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "&(II)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitAndIntFunction(position, args.getQuick(0), args.getQuick(1)); + } + + public static final class BitAndIntFunction extends IntFunction implements BinaryFunction { + private final Function left; + private final Function right; + + public BitAndIntFunction(int position, Function left, Function right) { + super(position); + this.left = left; + this.right = right; + } + + @Override + public Function getLeft() { + return left; + } + + @Override + public Function getRight() { + return right; + } + + @Override + public int getInt(Record rec) { + final int l = left.getInt(rec); + final int r = right.getInt(rec); + return l != Numbers.INT_NaN && r != Numbers.INT_NaN ? l & r : Numbers.INT_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseAndLongFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseAndLongFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0d1db721dcf91df8892d1a423658d0fa825041e8 --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseAndLongFunctionFactory.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.BinaryFunction; +import io.questdb.griffin.engine.functions.LongFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseAndLongFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "&(LL)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitAndLongFunction(position, args.getQuick(0), args.getQuick(1)); + } + + public static final class BitAndLongFunction extends LongFunction implements BinaryFunction { + private final Function left; + private final Function right; + + public BitAndLongFunction(int position, Function left, Function right) { + super(position); + this.left = left; + this.right = right; + } + + @Override + public Function getLeft() { + return left; + } + + @Override + public Function getRight() { + return right; + } + + @Override + public long getLong(Record rec) { + final long l = left.getLong(rec); + final long r = right.getLong(rec); + return l != Numbers.LONG_NaN && r != Numbers.LONG_NaN ? l & r : Numbers.LONG_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseNotIntFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseNotIntFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..fc7845efa5fe91242929b08586e395194a6eb011 --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseNotIntFunctionFactory.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.IntFunction; +import io.questdb.griffin.engine.functions.UnaryFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseNotIntFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "~(I)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitNotIntFunction(position, args.getQuick(0)); + } + + public static final class BitNotIntFunction extends IntFunction implements UnaryFunction { + private final Function value; + + public BitNotIntFunction(int position, Function value) { + super(position); + this.value = value; + } + + @Override + public Function getArg() { + return value; + } + + @Override + public int getInt(Record rec) { + final int val = value.getInt(rec); + return val != Numbers.INT_NaN ? ~val : Numbers.INT_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseNotLongFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseNotLongFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..2092daacbd66c0d7a4b1021d2c15cffae0c5fc59 --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseNotLongFunctionFactory.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.LongFunction; +import io.questdb.griffin.engine.functions.UnaryFunction; +import io.questdb.griffin.engine.functions.constants.LongConstant; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseNotLongFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "~(L)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitNotLongFunction(position, args.getQuick(0)); + } + + public static final class BitNotLongFunction extends LongFunction implements UnaryFunction { + private final Function value; + + public BitNotLongFunction(int position, Function value) { + super(position); + this.value = value; + } + + @Override + public Function getArg() { + return value; + } + + @Override + public long getLong(Record rec) { + final long val = value.getLong(rec); + return val != Numbers.LONG_NaN ? ~val : Numbers.LONG_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseOrIntFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseOrIntFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..8c87c3a354860bef31792086b9f94da1799e107b --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseOrIntFunctionFactory.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.BinaryFunction; +import io.questdb.griffin.engine.functions.IntFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseOrIntFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "|(II)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitOrIntFunction(position, args.getQuick(0), args.getQuick(1)); + } + + public static final class BitOrIntFunction extends IntFunction implements BinaryFunction { + private final Function left; + private final Function right; + + public BitOrIntFunction(int position, Function left, Function right) { + super(position); + this.left = left; + this.right = right; + } + + @Override + public Function getLeft() { + return left; + } + + @Override + public Function getRight() { + return right; + } + + @Override + public int getInt(Record rec) { + final int l = left.getInt(rec); + final int r = right.getInt(rec); + return l != Numbers.INT_NaN && r != Numbers.INT_NaN ? l | r : Numbers.INT_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseOrLongFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseOrLongFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..1420969476cb9c98eebb946eee7e109b49918b2c --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseOrLongFunctionFactory.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.BinaryFunction; +import io.questdb.griffin.engine.functions.LongFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseOrLongFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "|(LL)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitOrLongFunction(position, args.getQuick(0), args.getQuick(1)); + } + + public static final class BitOrLongFunction extends LongFunction implements BinaryFunction { + private final Function left; + private final Function right; + + public BitOrLongFunction(int position, Function left, Function right) { + super(position); + this.left = left; + this.right = right; + } + + @Override + public Function getLeft() { + return left; + } + + @Override + public Function getRight() { + return right; + } + + @Override + public long getLong(Record rec) { + final long l = left.getLong(rec); + final long r = right.getLong(rec); + return l != Numbers.LONG_NaN && r != Numbers.LONG_NaN ? l | r : Numbers.LONG_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseXorIntFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseXorIntFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..6ebf2bd1297bc1743da9fa6104b1d2108778e437 --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseXorIntFunctionFactory.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.BinaryFunction; +import io.questdb.griffin.engine.functions.IntFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseXorIntFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "^(II)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitXorIntFunction(position, args.getQuick(0), args.getQuick(1)); + } + + public static final class BitXorIntFunction extends IntFunction implements BinaryFunction { + private final Function left; + private final Function right; + + public BitXorIntFunction(int position, Function left, Function right) { + super(position); + this.left = left; + this.right = right; + } + + @Override + public Function getLeft() { + return left; + } + + @Override + public Function getRight() { + return right; + } + + @Override + public int getInt(Record rec) { + final int l = left.getInt(rec); + final int r = right.getInt(rec); + return l != Numbers.INT_NaN && r != Numbers.INT_NaN ? l ^ r : Numbers.INT_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseXorLongFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseXorLongFunctionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..ad03a5c1749f242b63f4bf6d69c4f3895b936fb3 --- /dev/null +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/BitwiseXorLongFunctionFactory.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin.engine.functions.math; + +import io.questdb.cairo.CairoConfiguration; +import io.questdb.cairo.sql.Function; +import io.questdb.cairo.sql.Record; +import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.SqlException; +import io.questdb.griffin.SqlExecutionContext; +import io.questdb.griffin.engine.functions.BinaryFunction; +import io.questdb.griffin.engine.functions.LongFunction; +import io.questdb.std.Numbers; +import io.questdb.std.ObjList; + +public class BitwiseXorLongFunctionFactory implements FunctionFactory { + @Override + public String getSignature() { + return "^(LL)"; + } + + @Override + public Function newInstance(ObjList args, int position, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) throws SqlException { + return new BitXorLongFunction(position, args.getQuick(0), args.getQuick(1)); + } + + public static final class BitXorLongFunction extends LongFunction implements BinaryFunction { + private final Function left; + private final Function right; + + public BitXorLongFunction(int position, Function left, Function right) { + super(position); + this.left = left; + this.right = right; + } + + @Override + public Function getLeft() { + return left; + } + + @Override + public Function getRight() { + return right; + } + + @Override + public long getLong(Record rec) { + final long l = left.getLong(rec); + final long r = right.getLong(rec); + return l != Numbers.LONG_NaN && r != Numbers.LONG_NaN ? l ^ r : Numbers.LONG_NaN; + } + } +} diff --git a/core/src/main/java/io/questdb/griffin/engine/functions/math/PowDoubleFunctionFactory.java b/core/src/main/java/io/questdb/griffin/engine/functions/math/PowDoubleFunctionFactory.java index 45fb814fb4fd5499f1be79a80a582cd2e79241b5..495e5662719a0e40a06e6c3ebedd5f638420283e 100644 --- a/core/src/main/java/io/questdb/griffin/engine/functions/math/PowDoubleFunctionFactory.java +++ b/core/src/main/java/io/questdb/griffin/engine/functions/math/PowDoubleFunctionFactory.java @@ -36,7 +36,7 @@ import io.questdb.std.ObjList; public class PowDoubleFunctionFactory implements FunctionFactory { @Override public String getSignature() { - return "^(DD)"; + return "power(DD)"; } @Override diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java index 8a3cd7337169f3b32ff486dc1653c0043b30a41c..ef0dcf2f55b215da15e2569b47da8fe24042b901 100644 --- a/core/src/main/java/module-info.java +++ b/core/src/main/java/module-info.java @@ -23,6 +23,7 @@ ******************************************************************************/ import io.questdb.griffin.FunctionFactory; +import io.questdb.griffin.engine.functions.math.*; open module io.questdb { requires transitive jdk.unsupported; @@ -530,6 +531,16 @@ open module io.questdb { io.questdb.griffin.engine.functions.analytic.RowNumberFunctionFactory, // metadata functions - io.questdb.griffin.engine.functions.metadata.BuildFunctionFactory + io.questdb.griffin.engine.functions.metadata.BuildFunctionFactory, + + // bit operations + BitwiseAndLongFunctionFactory, + BitwiseOrLongFunctionFactory, + BitwiseNotLongFunctionFactory, + BitwiseXorLongFunctionFactory, + BitwiseAndIntFunctionFactory, + BitwiseOrIntFunctionFactory, + BitwiseNotIntFunctionFactory, + BitwiseXorIntFunctionFactory ; } diff --git a/core/src/main/resources/META-INF/services/io.questdb.griffin.FunctionFactory b/core/src/main/resources/META-INF/services/io.questdb.griffin.FunctionFactory index 9ff3eba02ce738d2bd4d1c1f9629162e7b42f559..11c15746061758e6d205560a064c87747cde97af 100644 --- a/core/src/main/resources/META-INF/services/io.questdb.griffin.FunctionFactory +++ b/core/src/main/resources/META-INF/services/io.questdb.griffin.FunctionFactory @@ -492,3 +492,13 @@ io.questdb.griffin.engine.functions.analytic.RowNumberFunctionFactory # metadata functions io.questdb.griffin.engine.functions.metadata.BuildFunctionFactory + +# Bitwise operators +io.questdb.griffin.engine.functions.math.BitwiseAndLongFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseOrLongFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseXorLongFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseNotLongFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseAndIntFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseOrIntFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseXorIntFunctionFactory +io.questdb.griffin.engine.functions.math.BitwiseNotIntFunctionFactory \ No newline at end of file diff --git a/core/src/test/java/io/questdb/griffin/BitwiseTest.java b/core/src/test/java/io/questdb/griffin/BitwiseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..773eba1cbb68b1354a385af0614aecad663b4cf8 --- /dev/null +++ b/core/src/test/java/io/questdb/griffin/BitwiseTest.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin; + +import io.questdb.test.tools.TestUtils; +import org.junit.Test; + +public class BitwiseTest extends AbstractGriffinTest { + + @Test + public void testIntNot() throws Exception { + assertBitwiseOp("select ~1024", "-1025\n"); + } + + @Test + public void testIntNotNull() throws Exception { + assertBitwiseOp("select ~cast(NaN as int)", "NaN\n"); + } + + @Test + public void testIntOr() throws Exception { + assertBitwiseOp("select 2 | 4", "6\n"); + } + + @Test + public void testIntOrLeftNull() throws Exception { + assertBitwiseOp("select NaN | 4", "NaN\n"); + } + + @Test + public void testIntOrRightNull() throws Exception { + assertBitwiseOp("select 2 | NaN", "NaN\n"); + } + + @Test + public void testLongOr() throws Exception { + assertBitwiseOp("select 2L | 4", "6\n"); + } + + @Test + public void testLongOrLeftNull() throws Exception { + assertBitwiseOp("select NaN | 4L", "NaN\n"); + } + + @Test + public void testLongOrRightNull() throws Exception { + assertBitwiseOp("select 2L | NaN", "NaN\n"); + } + + @Test + public void testLongAnd() throws Exception { + assertBitwiseOp("select 6L & 4", "4\n"); + } + + @Test + public void testLongAndLeftNull() throws Exception { + assertBitwiseOp("select NaN & 4L", "NaN\n"); + } + + @Test + public void testLongAndRightNull() throws Exception { + assertBitwiseOp("select 2L & NaN", "NaN\n"); + } + + @Test + public void testIntAnd() throws Exception { + assertBitwiseOp("select 6 & 4", "4\n"); + } + + @Test + public void testIntAndLeftNull() throws Exception { + assertBitwiseOp("select NaN & 4", "NaN\n"); + } + + @Test + public void testIntAndRightNull() throws Exception { + assertBitwiseOp("select 2 & NaN", "NaN\n"); + } + + @Test + public void testIntXor() throws Exception { + assertBitwiseOp("select 6 ^ 4", "2\n"); + } + + @Test + public void testIntXorLeftNull() throws Exception { + assertBitwiseOp("select NaN ^ 4", "NaN\n"); + } + + @Test + public void testIntXorRightNull() throws Exception { + assertBitwiseOp("select 2 ^ NaN", "NaN\n"); + } + + @Test + public void testLongXor() throws Exception { + assertBitwiseOp("select 6L ^ 4", "2\n"); + } + + @Test + public void testLongXorLeftNull() throws Exception { + assertBitwiseOp("select NaN ^ 4L", "NaN\n"); + } + + @Test + public void testLongXorRightNull() throws Exception { + assertBitwiseOp("select 2L ^ NaN", "NaN\n"); + } + + @Test + public void testLongNot() throws Exception { + assertBitwiseOp("select ~255L", "-256\n"); + } + + @Test + public void testLongNotNull() throws Exception { + assertBitwiseOp("select ~cast(NaN as long)", "NaN\n"); + } + + private void assertBitwiseOp(String sql, String expected) throws Exception { + assertMemoryLeak(() -> TestUtils.assertSql( + compiler, + sqlExecutionContext, + sql, + sink, + "column\n" + + expected + )); + } +} diff --git a/core/src/test/java/io/questdb/griffin/ExpressionParserTest.java b/core/src/test/java/io/questdb/griffin/ExpressionParserTest.java index c4c811675e9fbc51bf0ac7552b62a7b97c91ab01..553f449676ac41e534bc911ef55148afca09517b 100644 --- a/core/src/test/java/io/questdb/griffin/ExpressionParserTest.java +++ b/core/src/test/java/io/questdb/griffin/ExpressionParserTest.java @@ -508,7 +508,7 @@ public class ExpressionParserTest extends AbstractCairoTest { @Test public void testComplexUnary2() throws Exception { - x("ab^-", "-a^b"); + x("a-b^", "-a^b"); } @Test diff --git a/core/src/test/java/io/questdb/griffin/PowerTest.java b/core/src/test/java/io/questdb/griffin/PowerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..dedfdc2dbc6094466203345eb009e6ea5f27b979 --- /dev/null +++ b/core/src/test/java/io/questdb/griffin/PowerTest.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (c) 2014-2019 Appsicle + * Copyright (c) 2019-2020 QuestDB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package io.questdb.griffin; + +import io.questdb.test.tools.TestUtils; +import org.junit.Test; + +public class PowerTest extends AbstractGriffinTest { + @Test + public void testPowerDouble() throws Exception { + assertMemoryLeak(() -> TestUtils.assertSql( + compiler, + sqlExecutionContext, + "select power(10.2, 3)", + sink, + "power\n" + + "1061.2080000000003\n" + )); + } + + @Test + public void testPowerDoubleLeftNull() throws Exception { + assertMemoryLeak(() -> TestUtils.assertSql( + compiler, + sqlExecutionContext, + "select power(NaN, 3)", + sink, + "power\n" + + "NaN\n" + )); + } + + @Test + public void testPowerDoubleRightNull() throws Exception { + assertMemoryLeak(() -> TestUtils.assertSql( + compiler, + sqlExecutionContext, + "select power(1.5, NaN)", + sink, + "power\n" + + "NaN\n" + )); + } +}