Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement array to string function #3320

Merged
merged 4 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/function/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_subdirectory(arithmetic)
add_subdirectory(cast)
add_subdirectory(pattern)
add_subdirectory(table)
add_subdirectory(list)

add_library(kuzu_function
OBJECT
Expand Down
2 changes: 1 addition & 1 deletion src/function/function_collection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ FunctionCollection* FunctionCollection::getFunctions() {
SCALAR_FUNCTION(ListSumFunction), SCALAR_FUNCTION(ListProductFunction),
SCALAR_FUNCTION(ListDistinctFunction), SCALAR_FUNCTION(ListUniqueFunction),
SCALAR_FUNCTION(ListAnyValueFunction), SCALAR_FUNCTION(ListReverseFunction),
SCALAR_FUNCTION(SizeFunction),
SCALAR_FUNCTION(SizeFunction), SCALAR_FUNCTION(ListToStringFunction),

// Cast functions
SCALAR_FUNCTION(CastToDateFunction), SCALAR_FUNCTION_ALIAS(CastToDateFunction),
Expand Down
7 changes: 7 additions & 0 deletions src/function/list/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_library(kuzu_list_function
OBJECT
list_to_string_function.cpp)

set(ALL_OBJECT_FILES
${ALL_OBJECT_FILES} $<TARGET_OBJECTS:kuzu_list_function>
PARENT_SCOPE)
25 changes: 25 additions & 0 deletions src/function/list/list_to_string_function.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "function/list/functions/list_to_string_function.h"

#include "common/type_utils.h"

namespace kuzu {
namespace function {

void ListToString::operation(common::list_entry_t& input, common::ku_string_t& delim,
common::ku_string_t& result, common::ValueVector& inputVector,
common::ValueVector& /*delimVector*/, common::ValueVector& resultVector) {
std::string resultStr = "";
auto dataVector = common::ListVector::getDataVector(&inputVector);
for (auto i = 0u; i < input.size - 1; i++) {
resultStr += common::TypeUtils::entryToString(dataVector->dataType,
common::ListVector::getListValuesWithOffset(&inputVector, input, i), dataVector);
resultStr += delim.getAsString();
}
resultStr += common::TypeUtils::entryToString(dataVector->dataType,
common::ListVector::getListValuesWithOffset(&inputVector, input, input.size - 1),
dataVector);
common::StringVector::addString(&resultVector, result, resultStr);
}

} // namespace function
} // namespace kuzu
11 changes: 11 additions & 0 deletions src/function/vector_list_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "function/list/functions/list_slice_function.h"
#include "function/list/functions/list_sort_function.h"
#include "function/list/functions/list_sum_function.h"
#include "function/list/functions/list_to_string_function.h"
#include "function/list/functions/list_unique_function.h"
#include "function/scalar_function.h"

Expand Down Expand Up @@ -924,5 +925,15 @@ function_set ListReverseFunction::getFunctionSet() {
return result;
}

function_set ListToStringFunction::getFunctionSet() {
function_set result;
result.push_back(std::make_unique<ScalarFunction>(name,
std::vector<LogicalTypeID>{LogicalTypeID::LIST, LogicalTypeID::STRING},
LogicalTypeID::STRING,
ScalarFunction::BinaryExecListStructFunction<list_entry_t, ku_string_t, ku_string_t,
ListToString>));
return result;
}

} // namespace function
} // namespace kuzu
16 changes: 16 additions & 0 deletions src/include/function/list/functions/list_to_string_function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "common/types/ku_string.h"
#include "common/vector/value_vector.h"

namespace kuzu {
namespace function {

struct ListToString {
static void operation(common::list_entry_t& input, common::ku_string_t& delim,
common::ku_string_t& result, common::ValueVector& inputVector,
common::ValueVector& /*delimVector*/, common::ValueVector& resultVector);
};

} // namespace function
} // namespace kuzu
13 changes: 9 additions & 4 deletions src/include/function/list/functions/list_unique_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,23 @@ struct ValueEquality {

using ValueSet = std::unordered_set<common::Value, ValueHashFunction, ValueEquality>;

using duplicateValueHandler = std::function<void(const std::string&)>;
using uniqueValueHandler = std::function<void(common::ValueVector& dataVector, uint64_t pos)>;
using duplicate_value_handler = std::function<void(const std::string&)>;
using unique_value_handler = std::function<void(common::ValueVector& dataVector, uint64_t pos)>;
using null_value_handler = std::function<void()>;

struct ListUnique {
static uint64_t appendListElementsToValueSet(common::list_entry_t& input,
common::ValueVector& inputVector, duplicateValueHandler duplicateValHandler = nullptr,
uniqueValueHandler uniqueValueHandler = nullptr) {
common::ValueVector& inputVector, duplicate_value_handler duplicateValHandler = nullptr,
unique_value_handler uniqueValueHandler = nullptr,
null_value_handler nullValueHandler = nullptr) {
ValueSet uniqueKeys;
auto dataVector = common::ListVector::getDataVector(&inputVector);
auto val = common::Value::createDefaultValue(dataVector->dataType);
for (auto i = 0u; i < input.size; i++) {
if (dataVector->isNull(input.offset + i)) {
if (nullValueHandler != nullptr) {
nullValueHandler();
}
continue;
}
auto entryVal = common::ListVector::getListValuesWithOffset(&inputVector, input, i);
Expand Down
6 changes: 6 additions & 0 deletions src/include/function/list/vector_list_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,11 @@ struct ListReverseFunction {
static function_set getFunctionSet();
};

struct ListToStringFunction {
static constexpr const char* name = "LIST_TO_STRING";

static function_set getFunctionSet();
};

} // namespace function
} // namespace kuzu
14 changes: 10 additions & 4 deletions src/include/function/map/functions/map_creation_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
namespace kuzu {
namespace function {

static void duplicateValueHandler(const std::string& key) {
throw common::RuntimeException{common::stringFormat("Found duplicate key: {} in map.", key)};
}

static void nullValueHandler() {
throw common::RuntimeException("Null value key is not allowed in map.");
}

static void validateKeys(common::list_entry_t& keyEntry, common::ValueVector& keyVector) {
ListUnique::appendListElementsToValueSet(keyEntry, keyVector, [](const std::string& key) {
throw common::RuntimeException{
common::stringFormat("Found duplicate key: {} in map.", key)};
});
ListUnique::appendListElementsToValueSet(keyEntry, keyVector, duplicateValueHandler,
nullptr /* uniqueValueHandler */, nullValueHandler);
}

struct MapCreation {
Expand Down
52 changes: 52 additions & 0 deletions test/test_files/tinysnb/function/list.test
Original file line number Diff line number Diff line change
Expand Up @@ -2130,3 +2130,55 @@ Ad
-STATEMENT Return list_product(["ok"]);
---- error
Binder exception: Unsupported inner data type for LIST_PRODUCT: STRING

-LOG ListToStringInt128
-STATEMENT RETURN LIST_TO_STRING([CAST(5, 'INT128'), CAST(7, 'INT128'), CAST(10, 'INT128')], '--')
---- 1
5--7--10

-LOG ListToStringInt64
-STATEMENT RETURN LIST_TO_STRING([CAST(255, 'INT64'), CAST(-51, 'INT64'), CAST(3132, 'INT64')], '--')
---- 1
255---51--3132

-LOG ListToStringBOOL
-STATEMENT RETURN LIST_TO_STRING([true, false, false, true], '/')
---- 1
True/False/False/True

-LOG ListToStringUUID
-STATEMENT MATCH (p:person) return list_to_string(collect(p.u), '*')
---- 1
a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a15*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a16*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17*a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18

-LOG ListToStringDate
-STATEMENT MATCH (p:person) return list_to_string(collect(p.birthdate), '+')
---- 1
1900-01-01+1900-01-01+1940-06-22+1950-07-23+1980-10-26+1980-10-26+1980-10-26+1990-11-27

-LOG ListToStringTimestamp
-STATEMENT MATCH (p:person) return list_to_string(collect(p.registerTime), '==')
---- 1
2011-08-20 11:25:30==2008-11-03 15:25:30.000526==1911-08-20 02:32:21==2031-11-30 12:25:30==1976-12-23 11:21:42==1972-07-31 13:22:30.678559==1976-12-23 04:41:42==2023-02-21 13:25:30

-LOG ListToStringList
-STATEMENT MATCH (p:person) return list_to_string(p.workedHours, ',')
---- 8
10,5
12,8
4,5
1,9
2
3,4,5,6,7
1
10,11,12,3,4,5,6,7

-LOG ListToStringStruct
-STATEMENT MATCH (o:organisation) return list_to_string(collect(o.state), '|')
---- 1
{revenue: 138, location: ['toronto','montr,eal'], stock: {price: [96,56], volume: 1000}}|{revenue: 152, location: ["vanco,uver north area"], stock: {price: [15,78,671], volume: 432}}|{revenue: 558, location: ['very long city name','new york'], stock: {price: [22], volume: 99}}

-LOG ListToStringArray
-STATEMENT MATCH (p:person) return list_to_string(collect(p.grades), '/')
---- 1
[96,54,86,92]/[98,42,93,88]/[91,75,21,95]/[76,88,99,89]/[96,59,65,88]/[80,78,34,83]/[43,83,67,43]/[77,64,100,54]
5 changes: 5 additions & 0 deletions test/test_files/tinysnb/projection/single_label.test
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,11 @@ Runtime exception: Found duplicate key: {a: 5, b: 3} in map.
---- error
Runtime exception: Found duplicate key: 0 in map.

-LOG MapWithNullKey
-STATEMENT RETURN map([cast(5, 'int128'), NULL, cast(5, 'int128')], [20, 34, 50]);
---- error
Runtime exception: Null value key is not allowed in map.
acquamarin marked this conversation as resolved.
Show resolved Hide resolved

-LOG ReturnMapLiteralWithProp
-STATEMENT MATCH (p:person) RETURN map([p.ID, p.age], [p.fName, p.fName]);
---- 8
Expand Down
Loading