| // 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 "gandiva/gdv_function_stubs.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "gandiva/engine.h" |
| #include "gandiva/exported_funcs.h" |
| #include "gandiva/in_holder.h" |
| #include "gandiva/like_holder.h" |
| #include "gandiva/random_generator_holder.h" |
| #include "gandiva/to_date_holder.h" |
| |
| /// Stub functions that can be accessed from LLVM or the pre-compiled library. |
| |
| extern "C" { |
| |
| bool gdv_fn_like_utf8_utf8(int64_t ptr, const char* data, int data_len, |
| const char* pattern, int pattern_len) { |
| gandiva::LikeHolder* holder = reinterpret_cast<gandiva::LikeHolder*>(ptr); |
| return (*holder)(std::string(data, data_len)); |
| } |
| |
| double gdv_fn_random(int64_t ptr) { |
| gandiva::RandomGeneratorHolder* holder = |
| reinterpret_cast<gandiva::RandomGeneratorHolder*>(ptr); |
| return (*holder)(); |
| } |
| |
| double gdv_fn_random_with_seed(int64_t ptr, int32_t seed, bool seed_validity) { |
| gandiva::RandomGeneratorHolder* holder = |
| reinterpret_cast<gandiva::RandomGeneratorHolder*>(ptr); |
| return (*holder)(); |
| } |
| |
| int64_t gdv_fn_to_date_utf8_utf8(int64_t context_ptr, int64_t holder_ptr, |
| const char* data, int data_len, bool in1_validity, |
| const char* pattern, int pattern_len, bool in2_validity, |
| bool* out_valid) { |
| gandiva::ExecutionContext* context = |
| reinterpret_cast<gandiva::ExecutionContext*>(context_ptr); |
| gandiva::ToDateHolder* holder = reinterpret_cast<gandiva::ToDateHolder*>(holder_ptr); |
| return (*holder)(context, data, data_len, in1_validity, out_valid); |
| } |
| |
| int64_t gdv_fn_to_date_utf8_utf8_int32(int64_t context_ptr, int64_t holder_ptr, |
| const char* data, int data_len, bool in1_validity, |
| const char* pattern, int pattern_len, |
| bool in2_validity, int32_t suppress_errors, |
| bool in3_validity, bool* out_valid) { |
| gandiva::ExecutionContext* context = |
| reinterpret_cast<gandiva::ExecutionContext*>(context_ptr); |
| gandiva::ToDateHolder* holder = reinterpret_cast<gandiva::ToDateHolder*>(holder_ptr); |
| return (*holder)(context, data, data_len, in1_validity, out_valid); |
| } |
| |
| bool gdv_fn_in_expr_lookup_int32(int64_t ptr, int32_t value, bool in_validity) { |
| if (!in_validity) { |
| return false; |
| } |
| gandiva::InHolder<int32_t>* holder = reinterpret_cast<gandiva::InHolder<int32_t>*>(ptr); |
| return holder->HasValue(value); |
| } |
| |
| bool gdv_fn_in_expr_lookup_int64(int64_t ptr, int64_t value, bool in_validity) { |
| if (!in_validity) { |
| return false; |
| } |
| gandiva::InHolder<int64_t>* holder = reinterpret_cast<gandiva::InHolder<int64_t>*>(ptr); |
| return holder->HasValue(value); |
| } |
| |
| bool gdv_fn_in_expr_lookup_utf8(int64_t ptr, const char* data, int data_len, |
| bool in_validity) { |
| if (!in_validity) { |
| return false; |
| } |
| gandiva::InHolder<std::string>* holder = |
| reinterpret_cast<gandiva::InHolder<std::string>*>(ptr); |
| return holder->HasValue(std::string(data, data_len)); |
| } |
| |
| int32_t gdv_fn_populate_varlen_vector(int64_t context_ptr, int8_t* data_ptr, |
| int32_t* offsets, int64_t slot, |
| const char* entry_buf, int32_t entry_len) { |
| auto buffer = reinterpret_cast<arrow::ResizableBuffer*>(data_ptr); |
| int32_t offset = static_cast<int32_t>(buffer->size()); |
| |
| // This also sets the size in the buffer. |
| auto status = buffer->Resize(offset + entry_len, false /*shrink*/); |
| if (!status.ok()) { |
| gandiva::ExecutionContext* context = |
| reinterpret_cast<gandiva::ExecutionContext*>(context_ptr); |
| |
| context->set_error_msg(status.message().c_str()); |
| return -1; |
| } |
| |
| // append the new entry. |
| memcpy(buffer->mutable_data() + offset, entry_buf, entry_len); |
| |
| // update offsets buffer. |
| offsets[slot] = offset; |
| offsets[slot + 1] = offset + entry_len; |
| return 0; |
| } |
| |
| int32_t gdv_fn_dec_from_string(int64_t context, const char* in, int32_t in_length, |
| int32_t* precision_from_str, int32_t* scale_from_str, |
| int64_t* dec_high_from_str, uint64_t* dec_low_from_str) { |
| arrow::Decimal128 dec; |
| auto status = arrow::Decimal128::FromString(std::string(in, in_length), &dec, |
| precision_from_str, scale_from_str); |
| if (!status.ok()) { |
| gdv_fn_context_set_error_msg(context, status.message().data()); |
| return -1; |
| } |
| *dec_high_from_str = dec.high_bits(); |
| *dec_low_from_str = dec.low_bits(); |
| return 0; |
| } |
| |
| char* gdv_fn_dec_to_string(int64_t context, int64_t x_high, uint64_t x_low, |
| int32_t x_scale, int32_t* dec_str_len) { |
| arrow::Decimal128 dec(arrow::BasicDecimal128(x_high, 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) { |
| std::string err_msg = "Could not allocate memory for string: " + dec_str; |
| gdv_fn_context_set_error_msg(context, err_msg.data()); |
| return nullptr; |
| } |
| memcpy(ret, dec_str.data(), *dec_str_len); |
| return ret; |
| } |
| } |
| |
| namespace gandiva { |
| |
| void ExportedStubFunctions::AddMappings(Engine* engine) const { |
| std::vector<llvm::Type*> args; |
| auto types = engine->types(); |
| |
| // gdv_fn_dec_from_string |
| args = { |
| types->i64_type(), // context |
| types->i8_ptr_type(), // const char* in |
| types->i32_type(), // int32_t in_length |
| types->i32_ptr_type(), // int32_t* precision_from_str |
| types->i32_ptr_type(), // int32_t* scale_from_str |
| types->i64_ptr_type(), // int64_t* dec_high_from_str |
| types->i64_ptr_type(), // int64_t* dec_low_from_str |
| }; |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_dec_from_string", |
| types->i32_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_dec_from_string)); |
| |
| // gdv_fn_dec_to_string |
| args = { |
| types->i64_type(), // context |
| types->i64_type(), // int64_t x_high |
| types->i64_type(), // int64_t x_low |
| types->i32_type(), // int32_t x_scale |
| types->i64_ptr_type(), // int64_t* dec_str_len |
| }; |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_dec_to_string", |
| types->i8_ptr_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_dec_to_string)); |
| |
| // gdv_fn_like_utf8_utf8 |
| args = {types->i64_type(), // int64_t ptr |
| types->i8_ptr_type(), // const char* data |
| types->i32_type(), // int data_len |
| types->i8_ptr_type(), // const char* pattern |
| types->i32_type()}; // int pattern_len |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_like_utf8_utf8", |
| types->i1_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_like_utf8_utf8)); |
| |
| // gdv_fn_to_date_utf8_utf8 |
| args = {types->i64_type(), // int64_t execution_context |
| types->i64_type(), // int64_t holder_ptr |
| types->i8_ptr_type(), // const char* data |
| types->i32_type(), // int data_len |
| types->i1_type(), // bool in1_validity |
| types->i8_ptr_type(), // const char* pattern |
| types->i32_type(), // int pattern_len |
| types->i1_type(), // bool in2_validity |
| types->ptr_type(types->i8_type())}; // bool* out_valid |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_to_date_utf8_utf8", |
| types->i64_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_to_date_utf8_utf8)); |
| |
| // gdv_fn_to_date_utf8_utf8_int32 |
| args = {types->i64_type(), // int64_t execution_context |
| types->i64_type(), // int64_t holder_ptr |
| types->i8_ptr_type(), // const char* data |
| types->i32_type(), // int data_len |
| types->i1_type(), // bool in1_validity |
| types->i8_ptr_type(), // const char* pattern |
| types->i32_type(), // int pattern_len |
| types->i1_type(), // bool in2_validity |
| types->i32_type(), // int32_t suppress_errors |
| types->i1_type(), // bool in3_validity |
| types->ptr_type(types->i8_type())}; // bool* out_valid |
| |
| engine->AddGlobalMappingForFunc( |
| "gdv_fn_to_date_utf8_utf8_int32", types->i64_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_to_date_utf8_utf8_int32)); |
| |
| // gdv_fn_in_expr_lookup_int32 |
| args = {types->i64_type(), // int64_t in holder ptr |
| types->i32_type(), // int32 value |
| types->i1_type()}; // bool in_validity |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_in_expr_lookup_int32", |
| types->i1_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_in_expr_lookup_int32)); |
| |
| // gdv_fn_in_expr_lookup_int64 |
| args = {types->i64_type(), // int64_t in holder ptr |
| types->i64_type(), // int64 value |
| types->i1_type()}; // bool in_validity |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_in_expr_lookup_int64", |
| types->i1_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_in_expr_lookup_int64)); |
| |
| // gdv_fn_in_expr_lookup_utf8 |
| args = {types->i64_type(), // int64_t in holder ptr |
| types->i8_ptr_type(), // const char* value |
| types->i32_type(), // int value_len |
| types->i1_type()}; // bool in_validity |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_in_expr_lookup_utf8", |
| types->i1_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_in_expr_lookup_utf8)); |
| |
| // gdv_fn_populate_varlen_vector |
| args = {types->i64_type(), // int64_t execution_context |
| types->i8_ptr_type(), // int8_t* data ptr |
| types->i32_ptr_type(), // int32_t* offsets ptr |
| types->i64_type(), // int64_t slot |
| types->i8_ptr_type(), // const char* entry_buf |
| types->i32_type()}; // int32_t entry__len |
| |
| engine->AddGlobalMappingForFunc("gdv_fn_populate_varlen_vector", |
| types->i32_type() /*return_type*/, args, |
| reinterpret_cast<void*>(gdv_fn_populate_varlen_vector)); |
| |
| // gdv_fn_random |
| args = {types->i64_type()}; |
| engine->AddGlobalMappingForFunc("gdv_fn_random", types->double_type(), args, |
| reinterpret_cast<void*>(gdv_fn_random)); |
| |
| args = {types->i64_type(), types->i32_type(), types->i1_type()}; |
| engine->AddGlobalMappingForFunc("gdv_fn_random_with_seed", types->double_type(), args, |
| reinterpret_cast<void*>(gdv_fn_random_with_seed)); |
| } |
| |
| } // namespace gandiva |