| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you 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. |
| |
| #include "exprs/arithmetic_expr.h" |
| |
| namespace doris { |
| |
| std::set<std::string> ArithmeticExpr::_s_valid_fn_names = { |
| "add", "subtract", "multiply", "divide", "int_divide", |
| "mod", "bitand", "bitor", "bitxor", "bitnot"}; |
| |
| Expr* ArithmeticExpr::from_thrift(const TExprNode& node) { |
| switch (node.opcode) { |
| case TExprOpcode::ADD: |
| return new AddExpr(node); |
| case TExprOpcode::SUBTRACT: |
| return new SubExpr(node); |
| case TExprOpcode::MULTIPLY: |
| return new MulExpr(node); |
| case TExprOpcode::DIVIDE: |
| case TExprOpcode::INT_DIVIDE: |
| return new DivExpr(node); |
| case TExprOpcode::MOD: |
| return new ModExpr(node); |
| case TExprOpcode::BITAND: |
| return new BitAndExpr(node); |
| case TExprOpcode::BITOR: |
| return new BitOrExpr(node); |
| case TExprOpcode::BITXOR: |
| return new BitXorExpr(node); |
| case TExprOpcode::BITNOT: |
| return new BitNotExpr(node); |
| default: |
| return nullptr; |
| } |
| return nullptr; |
| } |
| |
| Expr* ArithmeticExpr::from_fn_name(const TExprNode& node) { |
| std::string fn_name = node.fn.name.function_name; |
| if (fn_name == "add") { |
| return new AddExpr(node); |
| } else if (fn_name == "subtract") { |
| return new SubExpr(node); |
| } else if (fn_name == "multiply") { |
| return new MulExpr(node); |
| } else if (fn_name == "divide" || fn_name == "int_divide") { |
| return new DivExpr(node); |
| } else if (fn_name == "mod") { |
| return new ModExpr(node); |
| } else if (fn_name == "bitand") { |
| return new BitAndExpr(node); |
| } else if (fn_name == "bitor") { |
| return new BitOrExpr(node); |
| } else if (fn_name == "bitxor") { |
| return new BitXorExpr(node); |
| } else if (fn_name == "bitnot") { |
| return new BitNotExpr(node); |
| } |
| |
| return nullptr; |
| } |
| |
| #define BINARY_OP_CHECK_ZERO_FN(TYPE, CLASS, FN, OP) \ |
| TYPE CLASS::FN(ExprContext* context, TupleRow* row) { \ |
| TYPE v1 = _children[0]->FN(context, row); \ |
| if (v1.is_null) { \ |
| return TYPE::null(); \ |
| } \ |
| TYPE v2 = _children[1]->FN(context, row); \ |
| if (v2.is_null || v2.val == 0) { \ |
| return TYPE::null(); \ |
| } \ |
| return TYPE(v1.val OP v2.val); \ |
| } |
| |
| #define BINARY_OP_FN(TYPE, CLASS, FN, OP) \ |
| TYPE CLASS::FN(ExprContext* context, TupleRow* row) { \ |
| TYPE v1 = _children[0]->FN(context, row); \ |
| if (v1.is_null) { \ |
| return TYPE::null(); \ |
| } \ |
| TYPE v2 = _children[1]->FN(context, row); \ |
| if (v2.is_null) { \ |
| return TYPE::null(); \ |
| } \ |
| return TYPE(v1.val OP v2.val); \ |
| } |
| |
| #define BINARY_ARITH_FNS(CLASS, OP) \ |
| BINARY_OP_FN(TinyIntVal, CLASS, get_tiny_int_val, OP) \ |
| BINARY_OP_FN(SmallIntVal, CLASS, get_small_int_val, OP) \ |
| BINARY_OP_FN(IntVal, CLASS, get_int_val, OP) \ |
| BINARY_OP_FN(BigIntVal, CLASS, get_big_int_val, OP) \ |
| BINARY_OP_FN(LargeIntVal, CLASS, get_large_int_val, OP) \ |
| BINARY_OP_FN(FloatVal, CLASS, get_float_val, OP) \ |
| BINARY_OP_FN(DoubleVal, CLASS, get_double_val, OP) |
| |
| BINARY_ARITH_FNS(AddExpr, +) |
| BINARY_ARITH_FNS(SubExpr, -) |
| BINARY_ARITH_FNS(MulExpr, *) |
| |
| #define BINARY_DIV_FNS() \ |
| BINARY_OP_CHECK_ZERO_FN(TinyIntVal, DivExpr, get_tiny_int_val, /) \ |
| BINARY_OP_CHECK_ZERO_FN(SmallIntVal, DivExpr, get_small_int_val, /) \ |
| BINARY_OP_CHECK_ZERO_FN(IntVal, DivExpr, get_int_val, /) \ |
| BINARY_OP_CHECK_ZERO_FN(BigIntVal, DivExpr, get_big_int_val, /) \ |
| BINARY_OP_CHECK_ZERO_FN(LargeIntVal, DivExpr, get_large_int_val, /) \ |
| BINARY_OP_CHECK_ZERO_FN(FloatVal, DivExpr, get_float_val, /) \ |
| BINARY_OP_CHECK_ZERO_FN(DoubleVal, DivExpr, get_double_val, /) |
| |
| BINARY_DIV_FNS() |
| |
| #define BINARY_MOD_FNS() \ |
| BINARY_OP_CHECK_ZERO_FN(TinyIntVal, ModExpr, get_tiny_int_val, %) \ |
| BINARY_OP_CHECK_ZERO_FN(SmallIntVal, ModExpr, get_small_int_val, %) \ |
| BINARY_OP_CHECK_ZERO_FN(IntVal, ModExpr, get_int_val, %) \ |
| BINARY_OP_CHECK_ZERO_FN(BigIntVal, ModExpr, get_big_int_val, %) \ |
| BINARY_OP_CHECK_ZERO_FN(LargeIntVal, ModExpr, get_large_int_val, %) |
| |
| BINARY_MOD_FNS() |
| |
| FloatVal ModExpr::get_float_val(ExprContext* context, TupleRow* row) { |
| FloatVal v1 = _children[0]->get_float_val(context, row); |
| if (v1.is_null) { |
| return FloatVal::null(); |
| } |
| FloatVal v2 = _children[1]->get_float_val(context, row); |
| if (v2.is_null || v2.val == 0) { |
| return FloatVal::null(); |
| } |
| return FloatVal(fmod(v1.val, v2.val)); |
| } |
| |
| DoubleVal ModExpr::get_double_val(ExprContext* context, TupleRow* row) { |
| DoubleVal v1 = _children[0]->get_double_val(context, row); |
| if (v1.is_null) { |
| return DoubleVal::null(); |
| } |
| DoubleVal v2 = _children[1]->get_double_val(context, row); |
| if (v2.is_null || v2.val == 0) { |
| return DoubleVal::null(); |
| } |
| return DoubleVal(fmod(v1.val, v2.val)); |
| } |
| |
| #define BINARY_BIT_FNS(CLASS, OP) \ |
| BINARY_OP_FN(TinyIntVal, CLASS, get_tiny_int_val, OP) \ |
| BINARY_OP_FN(SmallIntVal, CLASS, get_small_int_val, OP) \ |
| BINARY_OP_FN(IntVal, CLASS, get_int_val, OP) \ |
| BINARY_OP_FN(BigIntVal, CLASS, get_big_int_val, OP) \ |
| BINARY_OP_FN(LargeIntVal, CLASS, get_large_int_val, OP) |
| |
| BINARY_BIT_FNS(BitAndExpr, &) |
| BINARY_BIT_FNS(BitOrExpr, |) |
| BINARY_BIT_FNS(BitXorExpr, ^) |
| |
| #define BITNOT_OP_FN(TYPE, FN) \ |
| TYPE BitNotExpr::FN(ExprContext* context, TupleRow* row) { \ |
| TYPE v = _children[0]->FN(context, row); \ |
| if (v.is_null) { \ |
| return TYPE::null(); \ |
| } \ |
| return TYPE(~v.val); \ |
| } |
| |
| #define BITNOT_FNS() \ |
| BITNOT_OP_FN(TinyIntVal, get_tiny_int_val) \ |
| BITNOT_OP_FN(SmallIntVal, get_small_int_val) \ |
| BITNOT_OP_FN(IntVal, get_int_val) \ |
| BITNOT_OP_FN(BigIntVal, get_big_int_val) \ |
| BITNOT_OP_FN(LargeIntVal, get_large_int_val) |
| |
| BITNOT_FNS() |
| |
| #define DECIMAL_ARITHMETIC_OP(EXPR_NAME, OP) \ |
| DecimalV2Val EXPR_NAME::get_decimalv2_val(ExprContext* context, TupleRow* row) { \ |
| DecimalV2Val v1 = _children[0]->get_decimalv2_val(context, row); \ |
| DecimalV2Val v2 = _children[1]->get_decimalv2_val(context, row); \ |
| if (v1.is_null || v2.is_null) { \ |
| return DecimalV2Val::null(); \ |
| } \ |
| DecimalV2Value iv1 = DecimalV2Value::from_decimal_val(v1); \ |
| DecimalV2Value iv2 = DecimalV2Value::from_decimal_val(v2); \ |
| DecimalV2Value ir = iv1 OP iv2; \ |
| DecimalV2Val result; \ |
| ir.to_decimal_val(&result); \ |
| return result; \ |
| } |
| |
| #define DECIMAL_ARITHMETIC_OP_DIVIDE(EXPR_NAME, OP) \ |
| DecimalV2Val EXPR_NAME::get_decimalv2_val(ExprContext* context, TupleRow* row) { \ |
| DecimalV2Val v1 = _children[0]->get_decimalv2_val(context, row); \ |
| DecimalV2Val v2 = _children[1]->get_decimalv2_val(context, row); \ |
| if (v1.is_null || v2.is_null || v2.value() == 0) { \ |
| return DecimalV2Val::null(); \ |
| } \ |
| DecimalV2Value iv1 = DecimalV2Value::from_decimal_val(v1); \ |
| DecimalV2Value iv2 = DecimalV2Value::from_decimal_val(v2); \ |
| DecimalV2Value ir = iv1 OP iv2; \ |
| DecimalV2Val result; \ |
| ir.to_decimal_val(&result); \ |
| return result; \ |
| } |
| |
| DECIMAL_ARITHMETIC_OP(AddExpr, +); |
| DECIMAL_ARITHMETIC_OP(SubExpr, -); |
| DECIMAL_ARITHMETIC_OP(MulExpr, *); |
| DECIMAL_ARITHMETIC_OP_DIVIDE(DivExpr, /); |
| DECIMAL_ARITHMETIC_OP_DIVIDE(ModExpr, %); |
| |
| } // namespace doris |