From da5eac690a5435cb14b147961180c9257a36c610 Mon Sep 17 00:00:00 2001 From: xiyang Date: Thu, 15 Feb 2024 11:17:33 +0800 Subject: [PATCH] Fix cast node, rel, recursive to string --- src/common/type_utils.cpp | 140 +++++++++++++----- src/function/cast/cast_fixed_list.cpp | 16 +- src/function/vector_cast_functions.cpp | 12 +- src/include/common/type_utils.h | 9 +- .../function/cast/functions/cast_functions.h | 31 ++-- test/test_files/copy/copy_to_csv.test | 57 ++++++- .../tinysnb/cast/cast_to_nested_types.test | 8 +- test/test_files/update_node/set_empty.test | 4 - 8 files changed, 190 insertions(+), 87 deletions(-) diff --git a/src/common/type_utils.cpp b/src/common/type_utils.cpp index 6fe2833f04..ce9133a4a7 100644 --- a/src/common/type_utils.cpp +++ b/src/common/type_utils.cpp @@ -7,8 +7,8 @@ namespace kuzu { namespace common { -std::string TypeUtils::castValueToString( - const LogicalType& dataType, const uint8_t* value, void* vector) { +static std::string entryToString( + const LogicalType& dataType, const uint8_t* value, ValueVector* vector) { auto valueVector = reinterpret_cast(vector); switch (dataType.getLogicalTypeID()) { case LogicalTypeID::BOOL: @@ -53,17 +53,53 @@ std::string TypeUtils::castValueToString( return TypeUtils::toString(*reinterpret_cast(value)); case LogicalTypeID::INTERNAL_ID: return TypeUtils::toString(*reinterpret_cast(value)); + case LogicalTypeID::FIXED_LIST: + return TypeUtils::fixedListToString(value, dataType); case LogicalTypeID::VAR_LIST: return TypeUtils::toString(*reinterpret_cast(value), valueVector); + case LogicalTypeID::MAP: + return TypeUtils::toString(*reinterpret_cast(value), valueVector); case LogicalTypeID::STRUCT: return TypeUtils::toString(*reinterpret_cast(value), valueVector); + case LogicalTypeID::UNION: + return TypeUtils::toString(*reinterpret_cast(value), valueVector); case LogicalTypeID::UUID: return TypeUtils::toString(*reinterpret_cast(value)); + case LogicalTypeID::NODE: + return TypeUtils::nodeToString( + *reinterpret_cast(value), valueVector); + case LogicalTypeID::REL: + return TypeUtils::relToString(*reinterpret_cast(value), valueVector); default: KU_UNREACHABLE; } } +static std::string entryToString(sel_t pos, ValueVector* vector) { + if (vector->isNull(pos)) { + return ""; + } + return entryToString( + vector->dataType, vector->getData() + vector->getNumBytesPerValue() * pos, vector); +} + +std::string TypeUtils::fixedListToString(const uint8_t* val, const LogicalType& type) { + std::string result = "["; + auto numValuesPerList = FixedListType::getNumValuesInList(&type); + auto childType = FixedListType::getChildType(&type); + for (auto i = 0u; i < numValuesPerList - 1; ++i) { + // Note: FixedList can only store numeric types and doesn't allow nulls. + // NOLINTNEXTLINE + result += entryToString(*childType, val, nullptr /* vector */); + result += ","; + val += PhysicalTypeUtils::getFixedTypeSize(childType->getPhysicalType()); + } + // NOLINTNEXTLINE + result += entryToString(*childType, val, nullptr /* vector */); + result += "]"; + return result; +} + template<> std::string TypeUtils::toString(const int128_t& val, void* /*valueVector*/) { return Int128_t::ToString(val); @@ -136,23 +172,24 @@ std::string TypeUtils::toString(const list_entry_t& val, void* valueVector) { return "[]"; } std::string result = "["; - auto values = ListVector::getListValues(listVector, val); - auto childType = VarListType::getChildType(&listVector->dataType); auto dataVector = ListVector::getDataVector(listVector); for (auto i = 0u; i < val.size - 1; ++i) { - result += dataVector->isNull(val.offset + i) ? - "" : - castValueToString(*childType, values, dataVector); + result += entryToString(val.offset + i, dataVector); result += ","; - values += ListVector::getDataVector(listVector)->getNumBytesPerValue(); } - result += dataVector->isNull(val.offset + val.size - 1) ? - "" : - castValueToString(*childType, values, dataVector); + result += entryToString(val.offset + val.size - 1, dataVector); result += "]"; return result; } +static std::string getMapEntryStr( + sel_t pos, ValueVector* dataVector, ValueVector* keyVector, ValueVector* valVector) { + if (dataVector->isNull(pos)) { + return ""; + } + return entryToString(pos, keyVector) + "=" + entryToString(pos, valVector); +} + template<> std::string TypeUtils::toString(const map_entry_t& val, void* valueVector) { auto mapVector = (ValueVector*)valueVector; @@ -160,66 +197,87 @@ std::string TypeUtils::toString(const map_entry_t& val, void* valueVector) { return "{}"; } std::string result = "{"; - auto keyType = MapType::getKeyType(&mapVector->dataType); - auto valType = MapType::getValueType(&mapVector->dataType); auto dataVector = ListVector::getDataVector(mapVector); auto keyVector = MapVector::getKeyVector(mapVector); auto valVector = MapVector::getValueVector(mapVector); - auto keyValues = keyVector->getData() + keyVector->getNumBytesPerValue() * val.entry.offset; - auto valValues = valVector->getData() + valVector->getNumBytesPerValue() * val.entry.offset; for (auto i = 0u; i < val.entry.size - 1; ++i) { - result += dataVector->isNull(val.entry.offset + i) ? - "" : - castValueToString(*keyType, keyValues, dataVector) + "=" + - castValueToString(*valType, valValues, dataVector); + auto pos = val.entry.offset + i; + result += getMapEntryStr(pos, dataVector, keyVector, valVector); result += ", "; - keyValues += keyVector->getNumBytesPerValue(); - valValues += valVector->getNumBytesPerValue(); } - result += dataVector->isNull(val.entry.offset + val.entry.size - 1) ? - "" : - castValueToString(*keyType, keyValues, dataVector) + "=" + - castValueToString(*valType, valValues, dataVector); + auto pos = val.entry.offset + val.entry.size - 1; + result += getMapEntryStr(pos, dataVector, keyVector, valVector); result += "}"; return result; } -template<> -std::string TypeUtils::toString(const struct_entry_t& val, void* valVector) { - auto structVector = (ValueVector*)valVector; - auto fields = StructType::getFields(&structVector->dataType); +template +static std::string structToString(const struct_entry_t& val, ValueVector* vector) { + auto fields = StructType::getFields(&vector->dataType); if (fields.size() == 0) { return "{}"; } std::string result = "{"; auto i = 0u; for (; i < fields.size() - 1; ++i) { - auto fieldVector = StructVector::getFieldVector(structVector, i); - result += StructType::getField(&structVector->dataType, i)->getName(); + auto fieldVector = StructVector::getFieldVector(vector, i); + if constexpr (SKIP_NULL_ENTRY) { + if (fieldVector->isNull(val.pos)) { + continue; + } + } + if (i != 0) { + result += ", "; + } + result += StructType::getField(&vector->dataType, i)->getName(); result += ": "; - result += castValueToString(*fields[i]->getType(), - fieldVector->getData() + fieldVector->getNumBytesPerValue() * val.pos, - fieldVector.get()); + result += entryToString(val.pos, fieldVector.get()); + } + auto fieldVector = StructVector::getFieldVector(vector, i); + if constexpr (SKIP_NULL_ENTRY) { + if (fieldVector->isNull(val.pos)) { + result += "}"; + return result; + } + } + if (i != 0) { result += ", "; } - auto fieldVector = StructVector::getFieldVector(structVector, i); - result += StructType::getField(&structVector->dataType, i)->getName(); + result += StructType::getField(&vector->dataType, i)->getName(); result += ": "; - result += castValueToString(*fields[i]->getType(), - fieldVector->getData() + fieldVector->getNumBytesPerValue() * val.pos, fieldVector.get()); + result += entryToString(val.pos, fieldVector.get()); result += "}"; return result; } +std::string TypeUtils::nodeToString(const struct_entry_t& val, ValueVector* vector) { + // Internal ID vector is the first field vector. + if (StructVector::getFieldVector(vector, 0)->isNull(val.pos)) { + return ""; + } + return structToString(val, vector); +} + +std::string TypeUtils::relToString(const struct_entry_t& val, ValueVector* vector) { + // Internal ID vector is the third field vector. + if (StructVector::getFieldVector(vector, 3)->isNull(val.pos)) { + return ""; + } + return structToString(val, vector); +} + +template<> +std::string TypeUtils::toString(const struct_entry_t& val, void* valVector) { + return structToString(val, (ValueVector*)valVector); +} + template<> std::string TypeUtils::toString(const union_entry_t& val, void* valVector) { auto structVector = (ValueVector*)valVector; auto unionFieldIdx = UnionVector::getTagVector(structVector)->getValue(val.entry.pos); auto unionFieldVector = UnionVector::getValVector(structVector, unionFieldIdx); - return castValueToString(unionFieldVector->dataType, - unionFieldVector->getData() + unionFieldVector->getNumBytesPerValue() * val.entry.pos, - unionFieldVector); + return entryToString(val.entry.pos, unionFieldVector); } } // namespace common diff --git a/src/function/cast/cast_fixed_list.cpp b/src/function/cast/cast_fixed_list.cpp index 80052d147e..9d5eedd36c 100644 --- a/src/function/cast/cast_fixed_list.cpp +++ b/src/function/cast/cast_fixed_list.cpp @@ -103,19 +103,9 @@ static void CastFixedListToString( if (param.isNull(pos)) { return; } - std::string result = "["; - auto numValuesPerList = FixedListType::getNumValuesInList(¶m.dataType); - auto childType = FixedListType::getChildType(¶m.dataType); - auto values = param.getData() + pos * param.getNumBytesPerValue(); - for (auto i = 0u; i < numValuesPerList - 1; ++i) { - // Note: FixedList can only store numeric types and doesn't allow nulls. - result += TypeUtils::castValueToString(*childType, values, nullptr /* vector */); - result += ","; - values += PhysicalTypeUtils::getFixedTypeSize(childType->getPhysicalType()); - } - result += TypeUtils::castValueToString(*childType, values, nullptr /* vector */); - result += "]"; - resultVector.setValue(resultPos, result); + auto value = param.getData() + pos * param.getNumBytesPerValue(); + auto result = TypeUtils::fixedListToString(value, param.dataType); + StringVector::addString(&resultVector, resultPos, result); } template<> diff --git a/src/function/vector_cast_functions.cpp b/src/function/vector_cast_functions.cpp index 1f79cb8f62..72a8247ca3 100644 --- a/src/function/vector_cast_functions.cpp +++ b/src/function/vector_cast_functions.cpp @@ -469,8 +469,15 @@ static std::unique_ptr bindCastToStringFunction( func = ScalarFunction::UnaryCastExecFunction; } break; - case LogicalTypeID::NODE: - case LogicalTypeID::REL: + case LogicalTypeID::NODE: { + func = ScalarFunction::UnaryCastExecFunction; + } break; + case LogicalTypeID::REL: { + func = ScalarFunction::UnaryCastExecFunction; + } break; + case LogicalTypeID::RECURSIVE_REL: case LogicalTypeID::STRUCT: { func = ScalarFunction::UnaryCastExecFunction; @@ -479,7 +486,6 @@ static std::unique_ptr bindCastToStringFunction( func = ScalarFunction::UnaryCastExecFunction; } break; - // ToDo(Kebing): RECURSIVE_REL to string default: KU_UNREACHABLE; } diff --git a/src/include/common/type_utils.h b/src/include/common/type_utils.h index 189f2b274a..91a70547f3 100644 --- a/src/include/common/type_utils.h +++ b/src/include/common/type_utils.h @@ -15,6 +15,7 @@ namespace kuzu { namespace common { +class ValueVector; struct blob_t; struct uuid_t; @@ -25,7 +26,6 @@ struct overload : Funcs... { }; class TypeUtils { - public: template static inline std::string toString(const T& val, void* /*valueVector*/ = nullptr) { @@ -36,6 +36,10 @@ class TypeUtils { std::is_same::value || std::is_same::value); return std::to_string(val); } + // Fixed list does not have a physical class. So we cannot reuse above toString template. + static std::string fixedListToString(const uint8_t* val, const common::LogicalType& type); + static std::string nodeToString(const struct_entry_t& val, ValueVector* vector); + static std::string relToString(const struct_entry_t& val, ValueVector* vector); static inline void encodeOverflowPtr( uint64_t& overflowPtr, page_idx_t pageIdx, uint16_t pageOffset) { @@ -49,9 +53,6 @@ class TypeUtils { memcpy(&pageOffset, ((uint8_t*)&overflowPtr) + 4, 2); } - static std::string castValueToString( - const LogicalType& dataType, const uint8_t* value, void* vector); - template static inline constexpr common::PhysicalTypeID getPhysicalTypeIDForType() { if constexpr (std::is_same_v) { diff --git a/src/include/function/cast/functions/cast_functions.h b/src/include/function/cast/functions/cast_functions.h index 984026c023..4574ae315f 100644 --- a/src/include/function/cast/functions/cast_functions.h +++ b/src/include/function/cast/functions/cast_functions.h @@ -1,7 +1,5 @@ #pragma once -#include "common/constants.h" -#include "common/exception/message.h" #include "common/exception/overflow.h" #include "common/string_format.h" #include "common/type_utils.h" @@ -15,17 +13,24 @@ struct CastToString { template static inline void operation(T& input, common::ku_string_t& result, common::ValueVector& inputVector, common::ValueVector& resultVector) { - std::string resultStr = common::TypeUtils::toString(input, (void*)&inputVector); - if (resultStr.length() > common::ku_string_t::SHORT_STR_LENGTH) { - if (resultStr.length() > common::BufferPoolConstants::PAGE_256KB_SIZE) { - throw common::RuntimeException( - common::ExceptionMessage::overLargeStringValueException(resultStr.length())); - } - result.overflowPtr = reinterpret_cast( - common::StringVector::getInMemOverflowBuffer(&resultVector) - ->allocateSpace(resultStr.length())); - } - result.set(resultStr); + auto str = common::TypeUtils::toString(input, (void*)&inputVector); + common::StringVector::addString(&resultVector, result, str); + } +}; + +struct CastNodeToString { + static inline void operation(common::struct_entry_t& input, common::ku_string_t& result, + common::ValueVector& inputVector, common::ValueVector& resultVector) { + auto str = common::TypeUtils::nodeToString(input, &inputVector); + common::StringVector::addString(&resultVector, result, str); + } +}; + +struct CastRelToString { + static inline void operation(common::struct_entry_t& input, common::ku_string_t& result, + common::ValueVector& inputVector, common::ValueVector& resultVector) { + auto str = common::TypeUtils::relToString(input, &inputVector); + common::StringVector::addString(&resultVector, result, str); } }; diff --git a/test/test_files/copy/copy_to_csv.test b/test/test_files/copy/copy_to_csv.test index 954a74ecb9..e93b963d96 100644 --- a/test/test_files/copy/copy_to_csv.test +++ b/test/test_files/copy/copy_to_csv.test @@ -56,14 +56,64 @@ Roma|298|the movie is very interesting and funny|{rating: 1223.000000, stars: 10 7|8|[96,59,65,88]|[80,78,34,83] 7|9|[96,59,65,88]|[43,83,67,43] --CASE CopyToWithNullAndEmptyList +-STATEMENT COPY (MATCH (a:person) WHERE a.ID = 0 RETURN a) TO "${DATABASE_PATH}/person1.csv" (header=true); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/person1.csv' (header=true) RETURN a; +---- 1 +{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11} +-STATEMENT COPY (MATCH (a:person:organisation) WHERE a.ID = 0 RETURN a) TO "${DATABASE_PATH}/person2.csv" (header=true); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/person2.csv' (header=true) RETURN a; +---- 1 +{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11} +-STATEMENT COPY (OPTIONAL MATCH (a:person:organisation) WHERE a.ID = -1 RETURN a, 1 AS b) TO "${DATABASE_PATH}/person3.csv" (header=true); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/person3.csv' (header=true) RETURN a, b; +---- 1 +|1 +-STATEMENT COPY (MATCH (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 RETURN e) TO "${DATABASE_PATH}/knows1.csv" (header=true); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/knows1.csv' (header=true) RETURN e; +---- 3 +{_SRC: 0:0, _DST: 0:1, _LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}} +{_SRC: 0:0, _DST: 0:2, _LABEL: knows, _ID: 3:1, date: 2021-06-30, meetTime: 1946-08-25 19:07:22, validInterval: 20 years 30 days 48:00:00, comments: [njnojppo9u0jkmf,fjiojioh9h9h89hph], summary: {locations: , transfer: }, notes: 2020-10-10, someMap: {c=d, e=f, 1=2}} +{_SRC: 0:0, _DST: 0:3, _LABEL: knows, _ID: 3:2, date: 2021-06-30, meetTime: 2012-12-11 20:07:22, validInterval: 10 days, comments: [ioji232,jifhe8w99u43434], summary: {locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}}, notes: nice weather} +-STATEMENT COPY (MATCH (a:person)-[e:knows|:studyAt]->(b:person) WHERE a.ID = 0 RETURN e) TO "${DATABASE_PATH}/knows2.csv" (header=true); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/knows2.csv' (header=true) RETURN e; +---- 3 +{_SRC: 0:0, _DST: 0:1, _LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}} +{_SRC: 0:0, _DST: 0:2, _LABEL: knows, _ID: 3:1, date: 2021-06-30, meetTime: 1946-08-25 19:07:22, validInterval: 20 years 30 days 48:00:00, comments: [njnojppo9u0jkmf,fjiojioh9h9h89hph], summary: {locations: , transfer: }, notes: 2020-10-10, someMap: {c=d, e=f, 1=2}} +{_SRC: 0:0, _DST: 0:3, _LABEL: knows, _ID: 3:2, date: 2021-06-30, meetTime: 2012-12-11 20:07:22, validInterval: 10 days, comments: [ioji232,jifhe8w99u43434], summary: {locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}}, notes: nice weather} +-STATEMENT COPY (MATCH p = (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 RETURN p) TO "${DATABASE_PATH}/path1.csv" (header=true); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/path1.csv' (header=true) RETURN p; +---- 3 +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:1, _LABEL: person, ID: 2, fName: Bob, gender: 2, isStudent: True, isWorker: False, age: 30, eyeSight: 5.100000, birthdate: 1900-01-01, registerTime: 2008-11-03 15:25:30.000526, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [12,8], usedNames: [Bobby], courseScoresPerTerm: [[8,9],[9,10]], grades: [98,42,93,88], height: 0.990000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12}], _RELS: [{_SRC: 0:0, _DST: 0:1, _LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}}]} +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:2, _LABEL: person, ID: 3, fName: Carol, gender: 1, isStudent: False, isWorker: True, age: 45, eyeSight: 5.000000, birthdate: 1940-06-22, registerTime: 1911-08-20 02:32:21, lastJobDuration: 48:24:11, workedHours: [4,5], usedNames: [Carmen,Fred], courseScoresPerTerm: [[8,10]], grades: [91,75,21,95], height: 1.000000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13}], _RELS: [{_SRC: 0:0, _DST: 0:2, _LABEL: knows, _ID: 3:1, date: 2021-06-30, meetTime: 1946-08-25 19:07:22, validInterval: 20 years 30 days 48:00:00, comments: [njnojppo9u0jkmf,fjiojioh9h9h89hph], summary: {locations: , transfer: }, notes: 2020-10-10, someMap: {c=d, e=f, 1=2}}]} +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:3, _LABEL: person, ID: 5, fName: Dan, gender: 2, isStudent: False, isWorker: True, age: 20, eyeSight: 4.800000, birthdate: 1950-07-23, registerTime: 2031-11-30 12:25:30, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1,9], usedNames: [Wolfeschlegelstein,Daniel], courseScoresPerTerm: [[7,4],[8,8],[9]], grades: [76,88,99,89], height: 1.300000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14}], _RELS: [{_SRC: 0:0, _DST: 0:3, _LABEL: knows, _ID: 3:2, date: 2021-06-30, meetTime: 2012-12-11 20:07:22, validInterval: 10 days, comments: [ioji232,jifhe8w99u43434], summary: {locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}}, notes: nice weather}]} +-STATEMENT COPY (MATCH p = (a:person)-[e:knows]->(b:person) WHERE a.ID = 0 RETURN nodes(p) AS n, rels(p) AS r) TO "${DATABASE_PATH}/path1.csv" (header=true, DELIM='|'); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/path1.csv' (header=true, DELIM='|') RETURN n, r; +---- 3 +[{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:1, _LABEL: person, ID: 2, fName: Bob, gender: 2, isStudent: True, isWorker: False, age: 30, eyeSight: 5.100000, birthdate: 1900-01-01, registerTime: 2008-11-03 15:25:30.000526, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [12,8], usedNames: [Bobby], courseScoresPerTerm: [[8,9],[9,10]], grades: [98,42,93,88], height: 0.990000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12}]|[{_SRC: 0:0, _DST: 0:1, _LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}}] +[{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:2, _LABEL: person, ID: 3, fName: Carol, gender: 1, isStudent: False, isWorker: True, age: 45, eyeSight: 5.000000, birthdate: 1940-06-22, registerTime: 1911-08-20 02:32:21, lastJobDuration: 48:24:11, workedHours: [4,5], usedNames: [Carmen,Fred], courseScoresPerTerm: [[8,10]], grades: [91,75,21,95], height: 1.000000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13}]|[{_SRC: 0:0, _DST: 0:2, _LABEL: knows, _ID: 3:1, date: 2021-06-30, meetTime: 1946-08-25 19:07:22, validInterval: 20 years 30 days 48:00:00, comments: [njnojppo9u0jkmf,fjiojioh9h9h89hph], summary: {locations: , transfer: }, notes: 2020-10-10, someMap: {c=d, e=f, 1=2}}] +[{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:3, _LABEL: person, ID: 5, fName: Dan, gender: 2, isStudent: False, isWorker: True, age: 20, eyeSight: 4.800000, birthdate: 1950-07-23, registerTime: 2031-11-30 12:25:30, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1,9], usedNames: [Wolfeschlegelstein,Daniel], courseScoresPerTerm: [[7,4],[8,8],[9]], grades: [76,88,99,89], height: 1.300000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14}]|[{_SRC: 0:0, _DST: 0:3, _LABEL: knows, _ID: 3:2, date: 2021-06-30, meetTime: 2012-12-11 20:07:22, validInterval: 10 days, comments: [ioji232,jifhe8w99u43434], summary: {locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}}, notes: nice weather}] +-STATEMENT COPY (MATCH p = (a:person)-[e:knows*0..1]->(b:person) WHERE a.ID = 0 RETURN p) TO "${DATABASE_PATH}/path2.csv" (header=true, DELIM='|'); +---- ok +-STATEMENT LOAD FROM '${DATABASE_PATH}/path2.csv' (header=true, DELIM='|') RETURN p; +---- 4 +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:1, _LABEL: person, ID: 2, fName: Bob, gender: 2, isStudent: True, isWorker: False, age: 30, eyeSight: 5.100000, birthdate: 1900-01-01, registerTime: 2008-11-03 15:25:30.000526, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [12,8], usedNames: [Bobby], courseScoresPerTerm: [[8,9],[9,10]], grades: [98,42,93,88], height: 0.990000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12}], _RELS: [{_SRC: 0:0, _DST: 0:1, _LABEL: knows, _ID: 3:0, date: 2021-06-30, meetTime: 1986-10-21 21:08:31.521, validInterval: 10 years 5 months 13:00:00.000024, comments: [rnme,m8sihsdnf2990nfiwf], summary: {locations: ['toronto','waterloo'], transfer: {day: 2021-01-02, amount: [100,200]}}, notes: 1, someMap: {a=b}}]} +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:2, _LABEL: person, ID: 3, fName: Carol, gender: 1, isStudent: False, isWorker: True, age: 45, eyeSight: 5.000000, birthdate: 1940-06-22, registerTime: 1911-08-20 02:32:21, lastJobDuration: 48:24:11, workedHours: [4,5], usedNames: [Carmen,Fred], courseScoresPerTerm: [[8,10]], grades: [91,75,21,95], height: 1.000000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a13}], _RELS: [{_SRC: 0:0, _DST: 0:2, _LABEL: knows, _ID: 3:1, date: 2021-06-30, meetTime: 1946-08-25 19:07:22, validInterval: 20 years 30 days 48:00:00, comments: [njnojppo9u0jkmf,fjiojioh9h9h89hph], summary: {locations: , transfer: }, notes: 2020-10-10, someMap: {c=d, e=f, 1=2}}]} +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11},{_ID: 0:3, _LABEL: person, ID: 5, fName: Dan, gender: 2, isStudent: False, isWorker: True, age: 20, eyeSight: 4.800000, birthdate: 1950-07-23, registerTime: 2031-11-30 12:25:30, lastJobDuration: 10 years 5 months 13:00:00.000024, workedHours: [1,9], usedNames: [Wolfeschlegelstein,Daniel], courseScoresPerTerm: [[7,4],[8,8],[9]], grades: [76,88,99,89], height: 1.300000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14}], _RELS: [{_SRC: 0:0, _DST: 0:3, _LABEL: knows, _ID: 3:2, date: 2021-06-30, meetTime: 2012-12-11 20:07:22, validInterval: 10 days, comments: [ioji232,jifhe8w99u43434], summary: {locations: ['shanghai'], transfer: {day: 1990-09-10, amount: [10]}}, notes: nice weather}]} +{_NODES: [{_ID: 0:0, _LABEL: person, ID: 0, fName: Alice, gender: 1, isStudent: True, isWorker: False, age: 35, eyeSight: 5.000000, birthdate: 1900-01-01, registerTime: 2011-08-20 11:25:30, lastJobDuration: 3 years 2 days 13:02:00, workedHours: [10,5], usedNames: [Aida], courseScoresPerTerm: [[10,8],[6,7,8]], grades: [96,54,86,92], height: 1.731000, u: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}], _RELS: []} + -STATEMENT COPY (RETURN NULL,[],[1,3,NULL,5],[[2,3],[2],NULL,[1,5,6]], [['a'], []]) TO "${DATABASE_PATH}/nullAndEmptyList.csv" (header=false) ---- ok -STATEMENT load from "${DATABASE_PATH}/nullAndEmptyList.csv" (header=false) return * ---- 1 |[]|[1,3,,5]|[[2,3],[2],,[1,5,6]]|[[a],[]] --CASE CopyToTimestamp -STATEMENT COPY (RETURN cast("2012-01-01 11:12:12.12345", "TIMESTAMP_NS"), cast("2012-01-01 11:12:12.12345", "TIMESTAMP_MS"), cast("2012-01-01 11:12:12.12345", "TIMESTAMP_SEC"), cast("2012-01-01 11:12:12.12345", "TIMESTAMP_TZ")) TO "${DATABASE_PATH}/timestamp.csv" (header=false) @@ -72,14 +122,12 @@ Roma|298|the movie is very interesting and funny|{rating: 1223.000000, stars: 10 ---- 1 2012-01-01 11:12:12.12345|2012-01-01 11:12:12.123|2012-01-01 11:12:12|2012-01-01 11:12:12.12345+00 --CASE StringEscapeCopyTo -STATEMENT COPY (RETURN 100,'a string with "quotes"',5.6,'","',',') TO "${DATABASE_PATH}/string.csv" (header=true) ---- ok -STATEMENT LOAD FROM '${DATABASE_PATH}/string.csv'(header=true) RETURN * ---- 1 100|a string with "quotes"|5.600000|","|, --CASE StringCopyToWithOption -STATEMENT COPY (RETURN 100,'kuzu is # a |graph database') TO "${DATABASE_PATH}/copy_to_with_option.csv" (delim = '|', QUOTE='#', Escape = '!', header = false) ---- ok -STATEMENT LOAD FROM '${DATABASE_PATH}/copy_to_with_option.csv' (delim = '|', QUOTE='#', Escape = '!', header=false) RETURN * @@ -90,3 +138,4 @@ Roma|298|the movie is very interesting and funny|{rating: 1223.000000, stars: 10 -STATEMENT COPY (RETURN 100) TO "${DATABASE_PATH}/copy_to_with_option.parquet" (delim = '|', QUOTE='#', Escape = '!') ---- error Binder exception: Only copy to csv can have options. + diff --git a/test/test_files/tinysnb/cast/cast_to_nested_types.test b/test/test_files/tinysnb/cast/cast_to_nested_types.test index e7c0358ff9..7deea065ae 100644 --- a/test/test_files/tinysnb/cast/cast_to_nested_types.test +++ b/test/test_files/tinysnb/cast/cast_to_nested_types.test @@ -232,8 +232,7 @@ False|-4325|14|18446744073709551616.000000| dfsa {}|{} -STATEMENT RETURN cast(cast(cast("{=, {NULL=NULL, NULL=1.1, {}=NULL, {}=1.12}={1.23={a=10}}, {{0=0, 1=, 0=NULL, =}=1.232}={1.321={}}, {{1=1,2=2}=1.232, {3=3}=1.432}={1.321={a=0}, 2={b=1}}, =}", "MAP(MAP(MAP(INT8, INT8), FLOAT), MAP(DOUBLE, MAP(STRING, UINT8)))"), "MAP(MAP(MAP(INT8, INT8), FLOAT), MAP(DOUBLE, MAP(STRING, UINT8)))"), "MAP(MAP(MAP(INT32, UINT8), DOUBLE), MAP(FLOAT, MAP(STRING, INT128)))"), cast(cast("{=, {NULL=NULL, NULL=1.1, {}=NULL, {}=1.12}={1.23={a=10}}, {{0=0, 1=, 0=NULL, =}=1.232}={1.321={}}, {{1=1,2=2}=1.232, {3=3}=1.432}={1.321={a=0}, 2={b=1}}, =}", "MAP(MAP(MAP(INT8, INT8), FLOAT), MAP(DOUBLE, MAP(STRING, UINT8)))"), "MAP(MAP(STRING, INT16), MAP(INT128, STRING))"); ---- 1 -{=, {=, =1.100000, {}=, {}=1.120000}={1.230000={a=10}}, {{0=0, 1=, 0=, =}=1.232000}={1.321000={}}, {{1=1, 2=2}=1.232000, {3=3}=1.432000}={1.321000={a=0}, 2.000000={b=1}}, =}|{=, {=, =1, {}=, {}=1}={1={a=10}}, {{0=0, 1=0, 0=0, 0=0}=1}={1={}}, {{1=1, 2=2}=1, {3=3}=1}={1={a=0}, 2={b=1}}, =} - +{=, {=, =1.100000, {}=, {}=1.120000}={1.230000={a=10}}, {{0=0, 1=, 0=, =}=1.232000}={1.321000={}}, {{1=1, 2=2}=1.232000, {3=3}=1.432000}={1.321000={a=0}, 2.000000={b=1}}, =}|{=, {=, =1, {}=, {}=1}={1={a=10}}, {{0=0, 1=, 0=, =}=1}={1={}}, {{1=1, 2=2}=1, {3=3}=1}={1={a=0}, 2={b=1}}, =} -LOG CastStructToStruct -STATEMENT RETURN cast(cast(cast("{a: 12, b: 0}", "STRUCT(a STRING, b STRING, c STRING)"), "STRUCT(a INT128, b INT128, c INT128)"), "STRUCT(a INT64, b INT64, c INT64)"), cast(cast(cast("{a: 15}", "STRUCT(a STRING, b STRING)"), "STRUCT(a INT32, b INT32)"), "STRUCT(a INT16, b INT16)"), cast(cast(cast("{b: 15}", "STRUCT(a STRING, b STRING)"), "STRUCT(a INT8, b INT8)"), "STRUCT(a UINT16, b UINT16)"), cast(cast(cast("{}", "STRUCT(a STRING, b STRING)"), "STRUCT(a UINT32, b UINT32)"), "STRUCT(a UINT64, b UINT64)"), cast(cast("{a: 12, b: 0}", "STRUCT(a STRING, b STRING)"), "STRUCT(a DOUBLE, b DOUBLE)"), cast(cast("{a: 12, b: 0}", "STRUCT(a STRING, b STRING)"), "STRUCT(a FLOAT, b FLOAT)"); ---- 1 @@ -255,9 +254,8 @@ False|-4325|14|18446744073709551616.000000| dfsa -STATEMENT LOAD WITH HEADERS (list STRING[], str STRING, struct STRUCT(a STRUCT(b STRUCT(c INT64[])))) FROM "${KUZU_ROOT_DIRECTORY}/dataset/load-from-test/var_list/change_config.csv" (HEADER=true, DELIM="|", DELIM="|", ESCAPE="~", QUOTE="'") RETURN cast(struct, "STRUCT(a STRUCT(b STRUCT(c INT128[])))"), cast(struct, "STRUCT(a STRUCT(b STRUCT(c DOUBLE[])))"), cast(struct, "STRUCT(a STRUCT(b STRUCT(c STRING)))"), cast(struct, "STRUCT(a STRUCT(b STRING))"), cast(struct, "STRUCT(a STRING)"); ---- 3 {a: {b: {c: [3432423,-43423,31231,]}}}|{a: {b: {c: [3432423.000000,-43423.000000,31231.000000,]}}}|{a: {b: {c: [3432423,-43423,31231,]}}}|{a: {b: {c: [3432423,-43423,31231,]}}}|{a: {b: {c: [3432423,-43423,31231,]}}} -{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: []}}}|{a: {b: {c: []}}} -{a: {b: }}|{a: {b: }}|{a: {b: }}|{a: {b: }}|{a: {b: {c: []}}} - +{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}}|{a: {b: {c: }}} +{a: {b: }}|{a: {b: }}|{a: {b: }}|{a: {b: }}|{a: {b: }} -LOG CastNestedToNestedType -STATEMENT RETURN cast(cast("{[123, 1432, 1142]={a: -1, b: 1, c: {1=1}}}", "MAP(INT64[], STRUCT(a INT8, b UINT8, c MAP(INT8, INT8)))"), "MAP(DOUBLE[], STRUCT(a FLOAT, b FLOAT, c MAP(DOUBLE, UINT8)))"); ---- 1 diff --git a/test/test_files/update_node/set_empty.test b/test/test_files/update_node/set_empty.test index 5f99e80c00..44248da45f 100644 --- a/test/test_files/update_node/set_empty.test +++ b/test/test_files/update_node/set_empty.test @@ -116,7 +116,3 @@ ${STRING_EXCEEDS_PAGE} -STATEMENT match (p:person0) return p.ID; ---- 1 ${STRING_LARGE_BUT_FITS} --LOG SetLongStringPKError --STATEMENT match (p:person0) SET p.ID=${STRING_EXCEEDS_LARGE_PAGE} ----- error -Runtime exception: The maximum length of strings is 262144 bytes. The input string's length was 288897.