diff --git a/src/function/built_in_vector_functions.cpp b/src/function/built_in_vector_functions.cpp index 84e972460f6..6c7460a25a9 100644 --- a/src/function/built_in_vector_functions.cpp +++ b/src/function/built_in_vector_functions.cpp @@ -435,6 +435,7 @@ void BuiltInVectorFunctions::registerCastFunctions() { void BuiltInVectorFunctions::registerListFunctions() { vectorFunctions.insert({LIST_CREATION_FUNC_NAME, ListCreationVectorFunction::getDefinitions()}); + vectorFunctions.insert({LIST_RANGE_FUNC_NAME, ListRangeVectorFunction::getDefinitions()}); vectorFunctions.insert({LIST_LEN_FUNC_NAME, ListLenVectorFunction::getDefinitions()}); vectorFunctions.insert({LIST_EXTRACT_FUNC_NAME, ListExtractVectorFunction::getDefinitions()}); vectorFunctions.insert({LIST_ELEMENT_FUNC_NAME, ListExtractVectorFunction::getDefinitions()}); diff --git a/src/function/vector_list_functions.cpp b/src/function/vector_list_functions.cpp index 561703568c0..ba248c52e48 100644 --- a/src/function/vector_list_functions.cpp +++ b/src/function/vector_list_functions.cpp @@ -15,6 +15,7 @@ #include "function/list/functions/list_len_function.h" #include "function/list/functions/list_position_function.h" #include "function/list/functions/list_prepend_function.h" +#include "function/list/functions/list_range_function.h" #include "function/list/functions/list_reverse_sort_function.h" #include "function/list/functions/list_slice_function.h" #include "function/list/functions/list_sort_function.h" @@ -94,6 +95,32 @@ vector_function_definitions ListCreationVectorFunction::getDefinitions() { return result; } +std::unique_ptr ListRangeVectorFunction::bindFunc( + const binder::expression_vector& arguments, kuzu::function::FunctionDefinition* definition) { + auto varListTypeInfo = + std::make_unique(std::make_unique(LogicalTypeID::INT64)); + auto resultType = LogicalType{LogicalTypeID::VAR_LIST, std::move(varListTypeInfo)}; + return std::make_unique(resultType); +} + +vector_function_definitions ListRangeVectorFunction::getDefinitions() { + vector_function_definitions result; + // start, end + result.push_back(std::make_unique(LIST_RANGE_FUNC_NAME, + std::vector{LogicalTypeID::INT64, LogicalTypeID::INT64}, + LogicalTypeID::VAR_LIST, + BinaryExecListStructFunction, nullptr, bindFunc, + false)); + // start, end, step + result.push_back(std::make_unique(LIST_RANGE_FUNC_NAME, + std::vector{ + LogicalTypeID::INT64, LogicalTypeID::INT64, LogicalTypeID::INT64}, + LogicalTypeID::VAR_LIST, + TernaryExecListStructFunction, nullptr, + bindFunc, false)); + return result; +} + vector_function_definitions ListLenVectorFunction::getDefinitions() { vector_function_definitions result; auto execFunc = UnaryExecFunction; diff --git a/src/include/common/expression_type.h b/src/include/common/expression_type.h index 8ece29f37e0..dbbc34f86dc 100644 --- a/src/include/common/expression_type.h +++ b/src/include/common/expression_type.h @@ -35,6 +35,7 @@ const std::string CAST_TO_BLOB_FUNC_NAME = "BLOB"; // list const std::string LIST_CREATION_FUNC_NAME = "LIST_CREATION"; +const std::string LIST_RANGE_FUNC_NAME = "RANGE"; const std::string LIST_EXTRACT_FUNC_NAME = "LIST_EXTRACT"; const std::string LIST_ELEMENT_FUNC_NAME = "LIST_ELEMENT"; const std::string LIST_LEN_FUNC_NAME = "LEN"; diff --git a/src/include/function/list/functions/list_range_function.h b/src/include/function/list/functions/list_range_function.h new file mode 100644 index 00000000000..c2f7c66d9e7 --- /dev/null +++ b/src/include/function/list/functions/list_range_function.h @@ -0,0 +1,54 @@ +#pragma once + +#include "common/types/ku_list.h" + +namespace kuzu { +namespace function { + +struct Range { +public: + // range function: + // - include end + // - when start = end: there is only one element in result varlist + // - when end - start are of opposite sign of step, the result will be empty + // - default step = 1 + static inline void operation(int64_t& start, int64_t& end, common::list_entry_t& result, + common::ValueVector& leftVector, common::ValueVector& rightVector, + common::ValueVector& resultVector) { + // step = 1 + auto number = start; + auto size = end - start; + size < 0 ? size = 0 : size++; + + result = common::ListVector::addList(&resultVector, size); + auto resultDataVector = common::ListVector::getDataVector(&resultVector); + auto resultPos = result.offset; + for (auto i = 0u; i < size; i++) { + resultDataVector->setValue(resultPos++, number++); + } + } + + static inline void operation(int64_t& start, int64_t& end, int64_t& step, + common::list_entry_t& result, common::ValueVector& inputVector, + common::ValueVector& resultVector) { + if (step == 0) { + throw common::RuntimeException("Step of range cannot be 0."); + } + + // start, start + step, start + 2step, ..., end + auto number = start; + auto size = (end - start) * 1.0 / step; + size < 0 ? size = 0 : size = (int)(size + 1); + + result = common::ListVector::addList(&resultVector, size); + auto resultDataVector = common::ListVector::getDataVector(&resultVector); + auto resultPos = result.offset; + for (auto i = 0u; i < size; i++) { + resultDataVector->setValue(resultPos++, number); + number += step; + } + } +}; + +} // namespace function +} // namespace kuzu \ No newline at end of file diff --git a/src/include/function/list/vector_list_functions.h b/src/include/function/list/vector_list_functions.h index cd808953989..4f74056a8fc 100644 --- a/src/include/function/list/vector_list_functions.h +++ b/src/include/function/list/vector_list_functions.h @@ -75,6 +75,12 @@ struct ListCreationVectorFunction : public VectorListFunction { common::ValueVector& result); }; +struct ListRangeVectorFunction : public VectorListFunction { + static vector_function_definitions getDefinitions(); + static std::unique_ptr bindFunc( + const binder::expression_vector& arguments, FunctionDefinition* definition); +}; + struct ListLenVectorFunction : public VectorListFunction { static vector_function_definitions getDefinitions(); }; diff --git a/test/test_files/tinysnb/function/range.test b/test/test_files/tinysnb/function/range.test new file mode 100644 index 00000000000..5f98a8bb0c0 --- /dev/null +++ b/test/test_files/tinysnb/function/range.test @@ -0,0 +1,101 @@ +-GROUP TinySnbReadTest +-DATASET CSV tck + +-- + +-CASE RangeUnflat +-STATEMENT CREATE NODE TABLE A(ID SERIAL, AGE INT64, NAME STRING, NUMBER INT32, PRIMARY KEY(ID)); +---- ok +-STATEMENT CREATE REL TABLE T(FROM A TO A); +---- ok +-STATEMENT CREATE ({AGE: 1, NAME: "Alice", NUMBER: 1})-[]-({AGE: 2, NAME: "Alice", NUMBER: 2}); +---- ok +-STATEMENT CREATE ({AGE: 0, NAME:"Alice", NUMBER:3}); +---- ok +-STATEMENT MATCH (a) RETURN range(a.AGE, 3); +---- 3 +[1,2,3] +[2,3] +[0,1,2,3] +-STATEMENT MATCH(a) RETURN range(1, a.AGE, 1); +---- 3 +[1] +[1,2] +[] +-STATEMENT MATCH (a)--() RETURN range(a.AGE, a.AGE, a.AGE); +---- 2 +[1] +[2] +-STATEMENT MATCH (a)--() RETURN range(1, 5, a.AGE); +---- 2 +[1,2,3,4,5] +[1,3,5] +-STATEMENT MATCH (a) RETURN range(a.NUMBER, a.AGE, -1); +---- 3 +[1] +[2] +[3,2,1,0] +-STATEMENT MATCH (a) RETURN range(-4, a.AGE, a.NUMBER); +---- 3 +[-4,-3,-2,-1,0,1] +[-4,-2,0,2] +[-4,-1] +-STATEMENT MATCH (b)--() RETURN range(b.AGE, 4, b.NUMBER); +---- 2 +[1,2,3,4] +[2,4] +-STATEMENT MATCH (a) RETURN range(a.NUMBER, 5, a.AGE); +---- error +Runtime exception: Step of range cannot be 0. +-STATEMENT MATCH (a) RETURN range(a.NAME, 4, 1); +---- error +Binder exception: Cannot match a built-in function for given function RANGE(STRING,INT64,INT64). Supported inputs are +(INT64,INT64) -> VAR_LIST +(INT64,INT64,INT64) -> VAR_LIST + + +-CASE RangeWithNoStep +-STATEMENT RETURN range(4, 3); +---- 1 +[] +-STATEMENT RETURN range(0, 0); +---- 1 +[0] +-STATEMENT RETURN range(1, 5); +---- 1 +[1,2,3,4,5] + +-CASE RangeWithStep +-STATEMENT RETURN range(4, 4, 2); +---- 1 +[4] +-STATEMENT RETURN range(4, 4, -2); +---- 1 +[4] +-STATEMENT RETURN range(5, 1, -1); +---- 1 +[5,4,3,2,1] +-STATEMENT RETURN range(5, 1, -2); +---- 1 +[5,3,1] +-STATEMENT RETURN range(5, 1, -3); +---- 1 +[5,2] +-STATEMENT RETURN range(6, 2, 2); +---- 1 +[] +-STATEMENT RETURN range(3, 6, -5); +---- 1 +[] +-STATEMENT RETURN range(3, 6, -1); +---- 1 +[] +-STATEMENT RETURN range(TO_INT32(3), 8, 2); +---- 1 +[3,5,7] +-STATEMENT RETURN range(TO_INT8(0), TO_INT16(-9), TO_INT8(-2)); +---- 1 +[0,-2,-4,-6,-8] +-STATEMENT RETURN range(3, 4, 0); +---- error +Runtime exception: Step of range cannot be 0. \ No newline at end of file