This is an automated email from the ASF dual-hosted git repository. ravindra pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push: new 49ed11b ARROW-5867: [C++][Gandiva] add support for cast int to decimal 49ed11b is described below commit 49ed11b7d161666952bddb6aace76f0c06c26f98 Author: Pindikura Ravindra <ravin...@dremio.com> AuthorDate: Mon Jul 8 15:28:55 2019 +0530 ARROW-5867: [C++][Gandiva] add support for cast int to decimal - cleanup and remove indirection for decimal fns - add fn for casting int/float to decimal Author: Pindikura Ravindra <ravin...@dremio.com> Closes #4817 from pravindra/int2dec and squashes the following commits: c80ee0044 <Pindikura Ravindra> fix format 3a5e7530d <Pindikura Ravindra> add fns for casting int/float to decimal 768dcd106 <Pindikura Ravindra> ARROW-5867: add support for cast int to decimal --- cpp/src/gandiva/decimal_ir.cc | 466 +++--------------------- cpp/src/gandiva/decimal_ir.h | 4 + cpp/src/gandiva/function_registry_arithmetic.cc | 2 + cpp/src/gandiva/gdv_function_stubs.cc | 4 +- cpp/src/gandiva/llvm_generator.cc | 15 +- cpp/src/gandiva/precompiled/decimal_wrapper.cc | 221 +++++------ cpp/src/gandiva/tests/decimal_test.cc | 34 +- 7 files changed, 208 insertions(+), 538 deletions(-) diff --git a/cpp/src/gandiva/decimal_ir.cc b/cpp/src/gandiva/decimal_ir.cc index 463e448..d9ea4e0 100644 --- a/cpp/src/gandiva/decimal_ir.cc +++ b/cpp/src/gandiva/decimal_ir.cc @@ -16,6 +16,7 @@ // under the License. #include <sstream> +#include <unordered_set> #include <utility> #include "arrow/status.h" @@ -35,6 +36,21 @@ namespace gandiva { AddTrace128(msg, value); \ } +// These are the functions defined in this file. The rest are in precompiled folder, +// and the i128 needs to be dis-assembled for those. +static const char* kAddFunction = "add_decimal128_decimal128"; +static const char* kSubtractFunction = "subtract_decimal128_decimal128"; +static const char* kEQFunction = "equal_decimal128_decimal128"; +static const char* kNEFunction = "not_equal_decimal128_decimal128"; +static const char* kLTFunction = "less_than_decimal128_decimal128"; +static const char* kLEFunction = "less_than_or_equal_to_decimal128_decimal128"; +static const char* kGTFunction = "greater_than_decimal128_decimal128"; +static const char* kGEFunction = "greater_than_or_equal_to_decimal128_decimal128"; + +static const std::unordered_set<std::string> kDecimalIRBuilderFunctions{ + kAddFunction, kSubtractFunction, kEQFunction, kNEFunction, + kLTFunction, kLEFunction, kGTFunction, kGEFunction}; + const char* DecimalIR::kScaleMultipliersName = "gandivaScaleMultipliers"; /// Populate globals required by decimal IR. @@ -250,7 +266,7 @@ Status DecimalIR::BuildAdd() { // int32_t out_precision, int32_t out_scale) auto i32 = types()->i32_type(); auto i128 = types()->i128_type(); - auto function = BuildFunction("add_decimal128_decimal128", i128, + auto function = BuildFunction(kAddFunction, i128, { {"x_value", i128}, {"x_precision", i32}, @@ -316,7 +332,7 @@ Status DecimalIR::BuildSubtract() { // int32_t out_precision, int32_t out_scale) auto i32 = types()->i32_type(); auto i128 = types()->i128_type(); - auto function = BuildFunction("subtract_decimal128_decimal128", i128, + auto function = BuildFunction(kSubtractFunction, i128, { {"x_value", i128}, {"x_precision", i32}, @@ -345,121 +361,13 @@ Status DecimalIR::BuildSubtract() { } ++i; } - auto value = - ir_builder()->CreateCall(module()->getFunction("add_decimal128_decimal128"), args); + auto value = ir_builder()->CreateCall(module()->getFunction(kAddFunction), args); // store result to out ir_builder()->CreateRet(value); return Status::OK(); } -Status DecimalIR::BuildMultiply() { - // Create fn prototype : - // int128_t - // multiply_decimal128_decimal128(int128_t x_value, int32_t x_precision, int32_t - // x_scale, - // int128_t y_value, int32_t y_precision, int32_t y_scale - // int32_t out_precision, int32_t out_scale) - auto i32 = types()->i32_type(); - auto i128 = types()->i128_type(); - auto function = BuildFunction("multiply_decimal128_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"y_value", i128}, - {"y_precision", i32}, - {"y_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - }); - - auto arg_iter = function->arg_begin(); - ValueFull x(&arg_iter[0], &arg_iter[1], &arg_iter[2]); - ValueFull y(&arg_iter[3], &arg_iter[4], &arg_iter[5]); - ValueFull out(nullptr, &arg_iter[6], &arg_iter[7]); - - auto entry = llvm::BasicBlock::Create(*context(), "entry", function); - ir_builder()->SetInsertPoint(entry); - - // Make call to pre-compiled IR function. - auto block = ir_builder()->GetInsertBlock(); - auto out_high_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_hi", block); - auto out_low_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_low", block); - auto x_split = ValueSplit::MakeFromInt128(this, x.value()); - auto y_split = ValueSplit::MakeFromInt128(this, y.value()); - - std::vector<llvm::Value*> args = { - x_split.high(), x_split.low(), x.precision(), x.scale(), - y_split.high(), y_split.low(), y.precision(), y.scale(), - out.precision(), out.scale(), out_high_ptr, out_low_ptr, - }; - ir_builder()->CreateCall( - module()->getFunction("multiply_internal_decimal128_decimal128"), args); - - auto out_high = ir_builder()->CreateLoad(out_high_ptr); - auto out_low = ir_builder()->CreateLoad(out_low_ptr); - auto result = ValueSplit(out_high, out_low).AsInt128(this); - ADD_TRACE_128("Multiply : result", result); - - ir_builder()->CreateRet(result); - return Status::OK(); -} - -Status DecimalIR::BuildDivideOrMod(const std::string& function_name, - const std::string& internal_fname) { - // Create fn prototype : - // int128_t - // divide_decimal128_decimal128(int64_t execution_context, - // int128_t x_value, int32_t x_precision, int32_t x_scale, - // int128_t y_value, int32_t y_precision, int32_t y_scale - // int32_t out_precision, int32_t out_scale) - auto i32 = types()->i32_type(); - auto i128 = types()->i128_type(); - auto function = BuildFunction(function_name, i128, - { - {"execution_context", types()->i64_type()}, - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"y_value", i128}, - {"y_precision", i32}, - {"y_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - }); - - auto arg_iter = function->arg_begin(); - auto execution_context = &arg_iter[0]; - ValueFull x(&arg_iter[1], &arg_iter[2], &arg_iter[3]); - ValueFull y(&arg_iter[4], &arg_iter[5], &arg_iter[6]); - ValueFull out(nullptr, &arg_iter[7], &arg_iter[8]); - - auto entry = llvm::BasicBlock::Create(*context(), "entry", function); - ir_builder()->SetInsertPoint(entry); - - // Make call to pre-compiled IR function. - auto block = ir_builder()->GetInsertBlock(); - auto out_high_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_hi", block); - auto out_low_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_low", block); - auto x_split = ValueSplit::MakeFromInt128(this, x.value()); - auto y_split = ValueSplit::MakeFromInt128(this, y.value()); - - std::vector<llvm::Value*> args = { - execution_context, x_split.high(), x_split.low(), x.precision(), x.scale(), - y_split.high(), y_split.low(), y.precision(), y.scale(), out.precision(), - out.scale(), out_high_ptr, out_low_ptr, - }; - ir_builder()->CreateCall(module()->getFunction(internal_fname), args); - - auto out_high = ir_builder()->CreateLoad(out_high_ptr); - auto out_low = ir_builder()->CreateLoad(out_low_ptr); - auto result = ValueSplit(out_high, out_low).AsInt128(this); - - ir_builder()->CreateRet(result); - return Status::OK(); -} - Status DecimalIR::BuildCompare(const std::string& function_name, llvm::ICmpInst::Predicate cmp_instruction) { // Create fn prototype : @@ -495,50 +403,47 @@ Status DecimalIR::BuildCompare(const std::string& function_name, y_split.high(), y_split.low(), y.precision(), y.scale(), }; auto cmp_value = ir_builder()->CreateCall( - module()->getFunction("compare_internal_decimal128_decimal128"), args); + module()->getFunction("compare_decimal128_decimal128_internal"), args); auto result = ir_builder()->CreateICmp(cmp_instruction, cmp_value, types()->i32_constant(0)); ir_builder()->CreateRet(result); return Status::OK(); } -Status DecimalIR::BuildDecimalFunction(const std::string& function_name, - llvm::Type* return_type, - std::vector<NamedArg> in_types) { - auto i64 = types()->i64_type(); - auto i128 = types()->i128_type(); - auto function = BuildFunction(function_name, return_type, in_types); - - auto entry = llvm::BasicBlock::Create(*context(), "entry", function); - ir_builder()->SetInsertPoint(entry); +llvm::Value* DecimalIR::CallDecimalFunction(const std::string& function_name, + llvm::Type* return_type, + const std::vector<llvm::Value*>& params) { + if (kDecimalIRBuilderFunctions.count(function_name) != 0) { + // this is fn built with the irbuilder. + return ir_builder()->CreateCall(module()->getFunction(function_name), params); + } - std::vector<llvm::Value*> args; - int arg_idx = 0; - auto arg_iter = function->arg_begin(); - for (auto& type : in_types) { - if (type.type == i128) { + // ppre-compiler fn : disassemble i128 to two i64s and re-assemble. + auto i128 = types()->i128_type(); + auto i64 = types()->i64_type(); + std::vector<llvm::Value*> dis_assembled_args; + for (auto& arg : params) { + if (arg->getType() == i128) { // split i128 arg into two int64s. - auto split = ValueSplit::MakeFromInt128(this, &arg_iter[arg_idx]); - args.push_back(split.high()); - args.push_back(split.low()); + auto split = ValueSplit::MakeFromInt128(this, arg); + dis_assembled_args.push_back(split.high()); + dis_assembled_args.push_back(split.low()); } else { - args.push_back(&arg_iter[arg_idx]); + dis_assembled_args.push_back(arg); } - ++arg_idx; } - auto internal_name = function_name + "_internal"; llvm::Value* result = nullptr; if (return_type == i128) { // for i128 ret, replace with two int64* args, and join them. auto block = ir_builder()->GetInsertBlock(); auto out_high_ptr = new llvm::AllocaInst(i64, 0, "out_hi", block); auto out_low_ptr = new llvm::AllocaInst(i64, 0, "out_low", block); - args.push_back(out_high_ptr); - args.push_back(out_low_ptr); + dis_assembled_args.push_back(out_high_ptr); + dis_assembled_args.push_back(out_low_ptr); // Make call to pre-compiled IR function. - ir_builder()->CreateCall(module()->getFunction(internal_name), args); + ir_builder()->CreateCall(module()->getFunction(function_name), dis_assembled_args); auto out_high = ir_builder()->CreateLoad(out_high_ptr); auto out_low = ir_builder()->CreateLoad(out_low_ptr); @@ -547,21 +452,14 @@ Status DecimalIR::BuildDecimalFunction(const std::string& function_name, DCHECK_NE(return_type, types()->void_type()); // Make call to pre-compiled IR function. - result = ir_builder()->CreateCall(module()->getFunction(internal_name), args); + result = ir_builder()->CreateCall(module()->getFunction(function_name), + dis_assembled_args); } - ir_builder()->CreateRet(result); - return Status::OK(); + return result; } Status DecimalIR::AddFunctions(Engine* engine) { auto decimal_ir = std::make_shared<DecimalIR>(engine); - auto i128 = decimal_ir->types()->i128_type(); - auto i32 = decimal_ir->types()->i32_type(); - auto i1 = decimal_ir->types()->i1_type(); - auto i64 = decimal_ir->types()->i64_type(); - auto f64 = decimal_ir->types()->double_type(); - auto i8_ptr = decimal_ir->types()->i8_ptr_type(); - auto i32_ptr = decimal_ir->types()->i32_ptr_type(); // Populate global variables used by decimal operations. decimal_ir->AddGlobals(engine); @@ -571,278 +469,12 @@ Status DecimalIR::AddFunctions(Engine* engine) { ARROW_RETURN_NOT_OK(decimal_ir->BuildAdd()); ARROW_RETURN_NOT_OK(decimal_ir->BuildSubtract()); - ARROW_RETURN_NOT_OK(decimal_ir->BuildMultiply()); - ARROW_RETURN_NOT_OK(decimal_ir->BuildDivideOrMod( - "divide_decimal128_decimal128", "divide_internal_decimal128_decimal128")); - ARROW_RETURN_NOT_OK(decimal_ir->BuildDivideOrMod("mod_decimal128_decimal128", - "mod_internal_decimal128_decimal128")); - - ARROW_RETURN_NOT_OK( - decimal_ir->BuildCompare("equal_decimal128_decimal128", llvm::ICmpInst::ICMP_EQ)); - ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare("not_equal_decimal128_decimal128", - llvm::ICmpInst::ICMP_NE)); - ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare("less_than_decimal128_decimal128", - llvm::ICmpInst::ICMP_SLT)); - ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare( - "less_than_or_equal_to_decimal128_decimal128", llvm::ICmpInst::ICMP_SLE)); - ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare("greater_than_decimal128_decimal128", - llvm::ICmpInst::ICMP_SGT)); - ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare( - "greater_than_or_equal_to_decimal128_decimal128", llvm::ICmpInst::ICMP_SGE)); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("abs_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("ceil_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("floor_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("round_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("round_decimal128_int32", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"round_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("truncate_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("truncate_decimal128_int32", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"round_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_int64", i128, - { - {"value", i64}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_float64", i128, - { - {"value", f64}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_decimal128", i128, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castBIGINT_decimal128", i64, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castFLOAT8_decimal128", f64, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash_decimal128", i32, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash32_decimal128", i32, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash64_decimal128", i64, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash32WithSeed_decimal128", i32, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - {"seed", i32}, - {"seed_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash64WithSeed_decimal128", i64, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - {"seed", i64}, - {"seed_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash32AsDouble_decimal128", i32, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash64AsDouble_decimal128", i64, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK( - decimal_ir->BuildDecimalFunction("hash32AsDoubleWithSeed_decimal128", i32, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - {"seed", i32}, - {"seed_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK( - decimal_ir->BuildDecimalFunction("hash64AsDoubleWithSeed_decimal128", i64, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - {"seed", i64}, - {"seed_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("isnull_decimal128", i1, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("isnotnull_decimal128", i1, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("isnumeric_decimal128", i1, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK( - decimal_ir->BuildDecimalFunction("is_distinct_from_decimal128_decimal128", i1, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - {"y_value", i128}, - {"y_precision", i32}, - {"y_scale", i32}, - {"y_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK( - decimal_ir->BuildDecimalFunction("is_not_distinct_from_decimal128_decimal128", i1, - { - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"x_isvalid", i1}, - {"y_value", i128}, - {"y_precision", i32}, - {"y_scale", i32}, - {"y_isvalid", i1}, - })); - - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_utf8", i128, - { - {"context", i64}, - {"in", i8_ptr}, - {"in_len", i32}, - {"out_precision", i32}, - {"out_scale", i32}, - })); - ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castVARCHAR_decimal128_int64", - i8_ptr, - { - {"context", i64}, - {"x_value", i128}, - {"x_precision", i32}, - {"x_scale", i32}, - {"out_len_param", i64}, - {"out_length", i32_ptr}, - })); - + ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kEQFunction, llvm::ICmpInst::ICMP_EQ)); + ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kNEFunction, llvm::ICmpInst::ICMP_NE)); + ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kLTFunction, llvm::ICmpInst::ICMP_SLT)); + ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kLEFunction, llvm::ICmpInst::ICMP_SLE)); + ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kGTFunction, llvm::ICmpInst::ICMP_SGT)); + ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kGEFunction, llvm::ICmpInst::ICMP_SGE)); return Status::OK(); } diff --git a/cpp/src/gandiva/decimal_ir.h b/cpp/src/gandiva/decimal_ir.h index c2a22b3..6503c82 100644 --- a/cpp/src/gandiva/decimal_ir.h +++ b/cpp/src/gandiva/decimal_ir.h @@ -37,6 +37,10 @@ class DecimalIR : public FunctionIRBuilder { void EnableTraces() { enable_ir_traces_ = true; } + llvm::Value* CallDecimalFunction(const std::string& function_name, + llvm::Type* return_type, + const std::vector<llvm::Value*>& args); + private: /// The intrinsic fn for divide with small divisors is about 10x slower, so not /// using these. diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc b/cpp/src/gandiva/function_registry_arithmetic.cc index f7f88bb..f5d5ce7 100644 --- a/cpp/src/gandiva/function_registry_arithmetic.cc +++ b/cpp/src/gandiva/function_registry_arithmetic.cc @@ -46,7 +46,9 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() { UNARY_CAST_TO_FLOAT64(float32), UNARY_CAST_TO_FLOAT64(decimal128), // cast to decimal + UNARY_SAFE_NULL_IF_NULL(castDECIMAL, int32, decimal128), UNARY_SAFE_NULL_IF_NULL(castDECIMAL, int64, decimal128), + UNARY_SAFE_NULL_IF_NULL(castDECIMAL, float32, decimal128), UNARY_SAFE_NULL_IF_NULL(castDECIMAL, float64, decimal128), UNARY_SAFE_NULL_IF_NULL(castDECIMAL, decimal128, decimal128), UNARY_UNSAFE_NULL_IF_NULL(castDECIMAL, utf8, decimal128), diff --git a/cpp/src/gandiva/gdv_function_stubs.cc b/cpp/src/gandiva/gdv_function_stubs.cc index 1d8fe9b..08d12d0 100644 --- a/cpp/src/gandiva/gdv_function_stubs.cc +++ b/cpp/src/gandiva/gdv_function_stubs.cc @@ -119,10 +119,10 @@ char* gdv_fn_dec_to_string(int64_t context, int64_t x_high, uint64_t x_low, std::string dec_str = dec.ToString(x_scale); *dec_str_len = static_cast<int32_t>(dec_str.length()); char* ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, *dec_str_len)); - if (ret == NULLPTR) { + if (ret == nullptr) { std::string err_msg = "Could not allocate memory for string: " + dec_str; gdv_fn_context_set_error_msg(context, err_msg.data()); - return NULLPTR; + return nullptr; } memcpy(ret, dec_str.data(), *dec_str_len); return ret; diff --git a/cpp/src/gandiva/llvm_generator.cc b/cpp/src/gandiva/llvm_generator.cc index f540755..57f67cb 100644 --- a/cpp/src/gandiva/llvm_generator.cc +++ b/cpp/src/gandiva/llvm_generator.cc @@ -25,6 +25,7 @@ #include <vector> #include "gandiva/bitmap_accumulator.h" +#include "gandiva/decimal_ir.h" #include "gandiva/dex.h" #include "gandiva/expr_decomposer.h" #include "gandiva/expression.h" @@ -1112,6 +1113,7 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func, auto types = generator_->types(); auto arrow_return_type_id = arrow_return_type->id(); auto llvm_return_type = types->IRType(arrow_return_type_id); + DecimalIR decimalIR(generator_->engine_.get()); if (arrow_return_type_id == arrow::Type::DECIMAL) { // For decimal fns, the output precision/scale are passed along as parameters. @@ -1127,10 +1129,16 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func, params->push_back(ret_lvalue->scale()); // Make the function call - auto out = generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params); + auto out = decimalIR.CallDecimalFunction(func->pc_name(), llvm_return_type, *params); ret_lvalue->set_data(out); return std::move(ret_lvalue); } else { + bool isDecimalFunction = false; + for (auto& arg : *params) { + if (arg->getType() == types->i128_type()) { + isDecimalFunction = true; + } + } // add extra arg for return length for variable len return types (alloced on stack). llvm::AllocaInst* result_len_ptr = nullptr; if (arrow::is_binary_like(arrow_return_type_id)) { @@ -1142,7 +1150,10 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func, // Make the function call llvm::IRBuilder<>* builder = ir_builder(); - auto value = generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params); + auto value = + isDecimalFunction + ? decimalIR.CallDecimalFunction(func->pc_name(), llvm_return_type, *params) + : generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params); auto value_len = (result_len_ptr == nullptr) ? nullptr : builder->CreateLoad(result_len_ptr); return std::make_shared<LValue>(value, value_len); diff --git a/cpp/src/gandiva/precompiled/decimal_wrapper.cc b/cpp/src/gandiva/precompiled/decimal_wrapper.cc index 620b443..66ccb3e 100644 --- a/cpp/src/gandiva/precompiled/decimal_wrapper.cc +++ b/cpp/src/gandiva/precompiled/decimal_wrapper.cc @@ -35,12 +35,11 @@ void add_large_decimal128_decimal128(int64_t x_high, uint64_t x_low, int32_t x_p } FORCE_INLINE -void multiply_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - int64_t y_high, uint64_t y_low, - int32_t y_precision, int32_t y_scale, - int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void multiply_decimal128_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int64_t y_high, uint64_t y_low, + int32_t y_precision, int32_t y_scale, + int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x(x_high, x_low, x_precision, x_scale); gandiva::BasicDecimalScalar128 y(y_high, y_low, y_precision, y_scale); bool overflow; @@ -53,10 +52,11 @@ void multiply_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low, } FORCE_INLINE -void divide_internal_decimal128_decimal128( - int64_t context, int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale, - int64_t y_high, uint64_t y_low, int32_t y_precision, int32_t y_scale, - int32_t out_precision, int32_t out_scale, int64_t* out_high, uint64_t* out_low) { +void divide_decimal128_decimal128(int64_t context, int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, int64_t y_high, + uint64_t y_low, int32_t y_precision, int32_t y_scale, + int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x(x_high, x_low, x_precision, x_scale); gandiva::BasicDecimalScalar128 y(y_high, y_low, y_precision, y_scale); bool overflow; @@ -69,12 +69,11 @@ void divide_internal_decimal128_decimal128( } FORCE_INLINE -void mod_internal_decimal128_decimal128(int64_t context, int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - int64_t y_high, uint64_t y_low, - int32_t y_precision, int32_t y_scale, - int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void mod_decimal128_decimal128(int64_t context, int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, int64_t y_high, + uint64_t y_low, int32_t y_precision, int32_t y_scale, + int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x(x_high, x_low, x_precision, x_scale); gandiva::BasicDecimalScalar128 y(y_high, y_low, y_precision, y_scale); bool overflow; @@ -87,7 +86,7 @@ void mod_internal_decimal128_decimal128(int64_t context, int64_t x_high, uint64_ } FORCE_INLINE -int32_t compare_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low, +int32_t compare_decimal128_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale, int64_t y_high, uint64_t y_low, int32_t y_precision, int32_t y_scale) { @@ -98,9 +97,9 @@ int32_t compare_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low, } FORCE_INLINE -void abs_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void abs_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale, + int32_t out_precision, int32_t out_scale, int64_t* out_high, + uint64_t* out_low) { gandiva::BasicDecimal128 x(x_high, x_low); x.Abs(); *out_high = x.high_bits(); @@ -108,9 +107,9 @@ void abs_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision } FORCE_INLINE -void ceil_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void ceil_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale, + int32_t out_precision, int32_t out_scale, int64_t* out_high, + uint64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -120,9 +119,9 @@ void ceil_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precisio } FORCE_INLINE -void floor_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void floor_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -132,9 +131,9 @@ void floor_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precisi } FORCE_INLINE -void round_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void round_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -144,10 +143,10 @@ void round_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precisi } FORCE_INLINE -void round_decimal128_int32_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t rounding_scale, - int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void round_decimal128_int32(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int32_t rounding_scale, + int32_t out_precision, int32_t out_scale, int64_t* out_high, + uint64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -157,10 +156,9 @@ void round_decimal128_int32_internal(int64_t x_high, uint64_t x_low, int32_t x_p } FORCE_INLINE -void truncate_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t out_precision, - int32_t out_scale, int64_t* out_high, - uint64_t* out_low) { +void truncate_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -170,11 +168,10 @@ void truncate_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_prec } FORCE_INLINE -void truncate_decimal128_int32_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - int32_t rounding_scale, int32_t out_precision, - int32_t out_scale, int64_t* out_high, - uint64_t* out_low) { +void truncate_decimal128_int32(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int32_t rounding_scale, + int32_t out_precision, int32_t out_scale, + int64_t* out_high, uint64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -184,8 +181,8 @@ void truncate_decimal128_int32_internal(int64_t x_high, uint64_t x_low, } FORCE_INLINE -double castFLOAT8_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale) { +double castFLOAT8_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -193,8 +190,8 @@ double castFLOAT8_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_ } FORCE_INLINE -int64_t castBIGINT_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale) { +int64_t castBIGINT_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; @@ -202,8 +199,8 @@ int64_t castBIGINT_decimal128_internal(int64_t x_high, uint64_t x_low, } FORCE_INLINE -void castDECIMAL_int64_internal(int64_t in, int32_t x_precision, int32_t x_scale, - int64_t* out_high, uint64_t* out_low) { +void castDECIMAL_int64(int64_t in, int32_t x_precision, int32_t x_scale, + int64_t* out_high, uint64_t* out_low) { bool overflow = false; auto out = gandiva::decimalops::FromInt64(in, x_precision, x_scale, &overflow); *out_high = out.high_bits(); @@ -211,8 +208,14 @@ void castDECIMAL_int64_internal(int64_t in, int32_t x_precision, int32_t x_scale } FORCE_INLINE -void castDECIMAL_float64_internal(double in, int32_t x_precision, int32_t x_scale, - int64_t* out_high, uint64_t* out_low) { +void castDECIMAL_int32(int32_t in, int32_t x_precision, int32_t x_scale, + int64_t* out_high, uint64_t* out_low) { + castDECIMAL_int64(in, x_precision, x_scale, out_high, out_low); +} + +FORCE_INLINE +void castDECIMAL_float64(double in, int32_t x_precision, int32_t x_scale, + int64_t* out_high, uint64_t* out_low) { bool overflow = false; auto out = gandiva::decimalops::FromDouble(in, x_precision, x_scale, &overflow); *out_high = out.high_bits(); @@ -220,10 +223,15 @@ void castDECIMAL_float64_internal(double in, int32_t x_precision, int32_t x_scal } FORCE_INLINE -void castDECIMAL_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, int32_t out_precision, - int32_t out_scale, int64_t* out_high, - int64_t* out_low) { +void castDECIMAL_float32(float in, int32_t x_precision, int32_t x_scale, + int64_t* out_high, uint64_t* out_low) { + castDECIMAL_float64(in, x_precision, x_scale, out_high, out_low); +} + +FORCE_INLINE +void castDECIMAL_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, int32_t out_precision, int32_t out_scale, + int64_t* out_high, int64_t* out_low) { gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale); bool overflow = false; auto out = gandiva::decimalops::Convert(x, out_precision, out_scale, &overflow); @@ -232,32 +240,31 @@ void castDECIMAL_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_p } FORCE_INLINE -int32_t hash32_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, boolean x_isvalid) { +int32_t hash32_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return x_isvalid ? hash32_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0) : 0; } FORCE_INLINE -int32_t hash_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, boolean x_isvalid) { - return hash32_decimal128_internal(x_high, x_low, x_precision, x_scale, x_isvalid); +int32_t hash_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { + return hash32_decimal128(x_high, x_low, x_precision, x_scale, x_isvalid); } FORCE_INLINE -int64_t hash64_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, boolean x_isvalid) { +int64_t hash64_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return x_isvalid ? hash64_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0) : 0; } FORCE_INLINE -int32_t hash32WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - boolean x_isvalid, int32_t seed, - boolean seed_isvalid) { +int32_t hash32WithSeed_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid, int32_t seed, + boolean seed_isvalid) { if (!x_isvalid) { return seed; } @@ -265,10 +272,9 @@ int32_t hash32WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low, } FORCE_INLINE -int64_t hash64WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - boolean x_isvalid, int64_t seed, - boolean seed_isvalid) { +int64_t hash64WithSeed_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid, int64_t seed, + boolean seed_isvalid) { if (!x_isvalid) { return seed; } @@ -276,28 +282,26 @@ int64_t hash64WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low, } FORCE_INLINE -int32_t hash32AsDouble_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - boolean x_isvalid) { +int32_t hash32AsDouble_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return x_isvalid ? hash32_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0) : 0; } FORCE_INLINE -int64_t hash64AsDouble_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - boolean x_isvalid) { +int64_t hash64AsDouble_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return x_isvalid ? hash64_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0) : 0; } FORCE_INLINE -int32_t hash32AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - boolean x_isvalid, int32_t seed, - boolean seed_isvalid) { +int32_t hash32AsDoubleWithSeed_decimal128(int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, + boolean x_isvalid, int32_t seed, + boolean seed_isvalid) { if (!x_isvalid) { return seed; } @@ -305,10 +309,10 @@ int32_t hash32AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_lo } FORCE_INLINE -int64_t hash64AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_low, - int32_t x_precision, int32_t x_scale, - boolean x_isvalid, int64_t seed, - boolean seed_isvalid) { +int64_t hash64AsDoubleWithSeed_decimal128(int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, + boolean x_isvalid, int64_t seed, + boolean seed_isvalid) { if (!x_isvalid) { return seed; } @@ -316,52 +320,54 @@ int64_t hash64AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_lo } FORCE_INLINE -boolean isnull_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, boolean x_isvalid) { +boolean isnull_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return !x_isvalid; } FORCE_INLINE -boolean isnotnull_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, boolean x_isvalid) { +boolean isnotnull_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return x_isvalid; } FORCE_INLINE -boolean isnumeric_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision, - int32_t x_scale, boolean x_isvalid) { +boolean isnumeric_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, + int32_t x_scale, boolean x_isvalid) { return x_isvalid; } FORCE_INLINE -boolean is_not_distinct_from_decimal128_decimal128_internal( - int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale, - boolean x_isvalid, int64_t y_high, uint64_t y_low, int32_t y_precision, - int32_t y_scale, boolean y_isvalid) { +boolean is_not_distinct_from_decimal128_decimal128(int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, + boolean x_isvalid, int64_t y_high, + uint64_t y_low, int32_t y_precision, + int32_t y_scale, boolean y_isvalid) { if (x_isvalid != y_isvalid) { return false; } if (!x_isvalid) { return true; } - return 0 == compare_internal_decimal128_decimal128(x_high, x_low, x_precision, x_scale, + return 0 == compare_decimal128_decimal128_internal(x_high, x_low, x_precision, x_scale, y_high, y_low, y_precision, y_scale); } FORCE_INLINE -boolean is_distinct_from_decimal128_decimal128_internal( - int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale, - boolean x_isvalid, int64_t y_high, uint64_t y_low, int32_t y_precision, - int32_t y_scale, boolean y_isvalid) { - return !is_not_distinct_from_decimal128_decimal128_internal( - x_high, x_low, x_precision, x_scale, x_isvalid, y_high, y_low, y_precision, y_scale, - y_isvalid); +boolean is_distinct_from_decimal128_decimal128(int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, + boolean x_isvalid, int64_t y_high, + uint64_t y_low, int32_t y_precision, + int32_t y_scale, boolean y_isvalid) { + return !is_not_distinct_from_decimal128_decimal128(x_high, x_low, x_precision, x_scale, + x_isvalid, y_high, y_low, + y_precision, y_scale, y_isvalid); } FORCE_INLINE -void castDECIMAL_utf8_internal(int64_t context, const char* in, int32_t in_length, - int32_t out_precision, int32_t out_scale, - int64_t* out_high, uint64_t* out_low) { +void castDECIMAL_utf8(int64_t context, const char* in, int32_t in_length, + int32_t out_precision, int32_t out_scale, int64_t* out_high, + uint64_t* out_low) { int64_t dec_high_from_str; uint64_t dec_low_from_str; int32_t precision_from_str; @@ -382,10 +388,9 @@ void castDECIMAL_utf8_internal(int64_t context, const char* in, int32_t in_lengt } FORCE_INLINE -char* castVARCHAR_decimal128_int64_internal(int64_t context, int64_t x_high, - uint64_t x_low, int32_t x_precision, - int32_t x_scale, int64_t out_len_param, - int32_t* out_length) { +char* castVARCHAR_decimal128_int64(int64_t context, int64_t x_high, uint64_t x_low, + int32_t x_precision, int32_t x_scale, + int64_t out_len_param, int32_t* out_length) { int32_t full_dec_str_len; char* dec_str = gdv_fn_dec_to_string(context, x_high, x_low, x_scale, &full_dec_str_len); diff --git a/cpp/src/gandiva/tests/decimal_test.cc b/cpp/src/gandiva/tests/decimal_test.cc index 1762d5b..2c29ccf 100644 --- a/cpp/src/gandiva/tests/decimal_test.cc +++ b/cpp/src/gandiva/tests/decimal_test.cc @@ -412,15 +412,22 @@ TEST_F(TestDecimal, TestCastFunctions) { constexpr int32_t scale = 2; auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale); auto decimal_type_scale_1 = std::make_shared<arrow::Decimal128Type>(precision, 1); - auto field_int64 = field("intt64", arrow::int64()); + auto field_int32 = field("int32", arrow::int32()); + auto field_int64 = field("int64", arrow::int64()); + auto field_float32 = field("float32", arrow::float32()); auto field_float64 = field("float64", arrow::float64()); auto field_dec = field("dec", decimal_type); - auto schema = arrow::schema({field_int64, field_float64, field_dec}); + auto schema = + arrow::schema({field_int32, field_int64, field_float32, field_float64, field_dec}); // build expressions auto exprs = std::vector<ExpressionPtr>{ + TreeExprBuilder::MakeExpression("castDECIMAL", {field_int32}, + field("int32_to_dec", decimal_type)), TreeExprBuilder::MakeExpression("castDECIMAL", {field_int64}, field("int64_to_dec", decimal_type)), + TreeExprBuilder::MakeExpression("castDECIMAL", {field_float32}, + field("float32_to_dec", decimal_type)), TreeExprBuilder::MakeExpression("castDECIMAL", {field_float64}, field("float64_to_dec", decimal_type)), TreeExprBuilder::MakeExpression("castDECIMAL", {field_dec}, @@ -440,15 +447,18 @@ TEST_F(TestDecimal, TestCastFunctions) { int num_records = 4; auto validity = {true, true, true, true}; + auto array_int32 = MakeArrowArrayInt32({123, 158, -123, -158}); auto array_int64 = MakeArrowArrayInt64({123, 158, -123, -158}); + auto array_float32 = MakeArrowArrayFloat32({1.23f, 1.58f, -1.23f, -1.58f}); auto array_float64 = MakeArrowArrayFloat64({1.23, 1.58, -1.23, -1.58}); auto array_dec = MakeArrowArrayDecimal( decimal_type, MakeDecimalVector({"1.23", "1.58", "-1.23", "-1.58"}, scale), validity); // prepare input record batch - auto in_batch = arrow::RecordBatch::Make(schema, num_records, - {array_int64, array_float64, array_dec}); + auto in_batch = arrow::RecordBatch::Make( + schema, num_records, + {array_int32, array_int64, array_float32, array_float64, array_dec}); // Evaluate expression arrow::ArrayVector outputs; @@ -457,28 +467,34 @@ TEST_F(TestDecimal, TestCastFunctions) { // Validate results - // castDECIMAL(int64) + // castDECIMAL(int32) EXPECT_ARROW_ARRAY_EQUALS( MakeArrowArrayDecimal(decimal_type, MakeDecimalVector({"123", "158", "-123", "-158"}, scale), validity), outputs[0]); + // castDECIMAL(int64) + EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[2]); + + // castDECIMAL(float32) + EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[2]); + // castDECIMAL(float64) - EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[1]); + EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[3]); // castDECIMAL(decimal) EXPECT_ARROW_ARRAY_EQUALS( MakeArrowArrayDecimal(arrow::decimal(precision, 1), MakeDecimalVector({"1.2", "1.6", "-1.2", "-1.6"}, 1), validity), - outputs[2]); + outputs[4]); // castBIGINT(decimal) - EXPECT_ARROW_ARRAY_EQUALS(MakeArrowArrayInt64({1, 1, -1, -1}), outputs[3]); + EXPECT_ARROW_ARRAY_EQUALS(MakeArrowArrayInt64({1, 1, -1, -1}), outputs[5]); // castDOUBLE(decimal) - EXPECT_ARROW_ARRAY_EQUALS(array_float64, outputs[4]); + EXPECT_ARROW_ARRAY_EQUALS(array_float64, outputs[6]); } // isnull, isnumeric