#include "common/exception/runtime.h"
#include "common/type_utils.h"
#include "function/list/vector_list_functions.h"
#include "function/scalar_function.h"
using namespace lbug::common;
namespace lbug {
namespace function {
struct Range {
template<typename T>
static void operation(T& end, list_entry_t& result, ValueVector& endVector,
ValueVector& resultVector) {
T step = 1;
T start = 0;
operation(start, end, step, result, endVector, resultVector);
}
template<typename T>
static void operation(T& start, T& end, list_entry_t& result, ValueVector& leftVector,
ValueVector& , ValueVector& resultVector) {
T step = 1;
operation(start, end, step, result, leftVector, resultVector);
}
template<typename T>
static void operation(T& start, T& end, T& step, list_entry_t& result,
ValueVector& , ValueVector& resultVector) {
if (step == 0) {
throw RuntimeException("Step of range cannot be 0.");
}
T number = start;
auto size = ((end - start) * 1.0 / step);
size < 0 ? size = 0 : size = (int64_t)(size + 1);
result = ListVector::addList(&resultVector, (int64_t)size);
auto resultDataVector = ListVector::getDataVector(&resultVector);
for (auto i = 0u; i < (int64_t)size; i++) {
resultDataVector->setValue(result.offset + i, number);
number += step;
}
}
};
static scalar_func_exec_t getBinaryExecFunc(const LogicalType& type) {
scalar_func_exec_t execFunc;
TypeUtils::visit(
type,
[&execFunc]<IntegerTypes T>(T) {
execFunc = ScalarFunction::BinaryExecListStructFunction<T, T, list_entry_t, Range>;
},
[](auto) { UNREACHABLE_CODE; });
return execFunc;
}
static scalar_func_exec_t getTernaryExecFunc(const LogicalType& type) {
scalar_func_exec_t execFunc;
TypeUtils::visit(
type,
[&execFunc]<IntegerTypes T>(T) {
execFunc = ScalarFunction::TernaryExecListStructFunction<T, T, T, list_entry_t, Range>;
},
[](auto) { UNREACHABLE_CODE; });
return execFunc;
}
static std::unique_ptr<FunctionBindData> bindFunc(const ScalarBindFuncInput& input) {
auto type = LogicalType(input.definition->parameterTypeIDs[0]);
auto resultType = LogicalType::LIST(type.copy());
auto bindData = std::make_unique<FunctionBindData>(std::move(resultType));
for (auto& _ : input.arguments) {
(void)_;
bindData->paramTypes.push_back(type.copy());
}
return bindData;
}
function_set ListRangeFunction::getFunctionSet() {
function_set result;
std::unique_ptr<ScalarFunction> func;
for (auto typeID : LogicalTypeUtils::getIntegerTypeIDs()) {
func = std::make_unique<ScalarFunction>(name, std::vector<LogicalTypeID>{typeID, typeID},
LogicalTypeID::LIST, getBinaryExecFunc(LogicalType{typeID}));
func->bindFunc = bindFunc;
result.push_back(std::move(func));
func = std::make_unique<ScalarFunction>(name,
std::vector<LogicalTypeID>{typeID, typeID, typeID}, LogicalTypeID::LIST,
getTernaryExecFunc(LogicalType{typeID}));
func->bindFunc = bindFunc;
result.push_back(std::move(func));
}
return result;
}
} }