From 791d77bb68daa18b1b1a1cc2b7aed7c0a98a6c5f Mon Sep 17 00:00:00 2001 From: AEsir777 Date: Wed, 1 Nov 2023 12:17:52 -0400 Subject: [PATCH] add function CAST(item, type) --- src/binder/bind/bind_graph_pattern.cpp | 6 +- .../bind_function_expression.cpp | 35 ++- src/binder/expression/function_expression.cpp | 4 + src/c_api/value.cpp | 2 +- src/common/types/ku_string.cpp | 9 + .../function_evaluator.cpp | 13 +- src/function/built_in_functions.cpp | 17 + src/function/cast_string_to_functions.cpp | 195 +++++++++--- src/function/vector_cast_functions.cpp | 111 ++++++- .../binder/expression/function_expression.h | 10 +- src/include/binder/expression_binder.h | 4 +- src/include/common/enums/expression_type.h | 1 + src/include/common/types/ku_string.h | 1 + .../expression_evaluator/function_evaluator.h | 5 +- src/include/function/built_in_function.h | 2 + .../cast/functions/cast_string_to_functions.h | 290 ++++++------------ .../function/cast/vector_cast_functions.h | 32 +- src/include/function/function.h | 8 + src/include/function/scalar_function.h | 26 +- .../in_mem_column_chunk.h | 2 +- .../in_mem_storage_structure/in_mem_lists.h | 2 +- src/parser/transform/transform_expression.cpp | 8 +- src/storage/store/table_copy_utils.cpp | 43 +-- test/test_files/tinysnb/function/cast.test | 15 + 24 files changed, 548 insertions(+), 293 deletions(-) diff --git a/src/binder/bind/bind_graph_pattern.cpp b/src/binder/bind/bind_graph_pattern.cpp index 49a87abae17..7746a701e7e 100644 --- a/src/binder/bind/bind_graph_pattern.cpp +++ b/src/binder/bind/bind_graph_pattern.cpp @@ -401,11 +401,13 @@ std::pair Binder::bindVariableLengthRelBound( auto recursiveInfo = relPattern.getRecursiveInfo(); uint32_t lowerBound; function::CastStringToTypes::operation( - recursiveInfo->lowerBound.c_str(), recursiveInfo->lowerBound.length(), lowerBound); + ku_string_t{recursiveInfo->lowerBound.c_str(), recursiveInfo->lowerBound.length()}, + lowerBound); auto upperBound = clientContext->varLengthExtendMaxDepth; if (!recursiveInfo->upperBound.empty()) { function::CastStringToTypes::operation( - recursiveInfo->upperBound.c_str(), recursiveInfo->upperBound.length(), upperBound); + ku_string_t{recursiveInfo->upperBound.c_str(), recursiveInfo->upperBound.length()}, + upperBound); } if (lowerBound > upperBound) { throw BinderException( diff --git a/src/binder/bind_expression/bind_function_expression.cpp b/src/binder/bind_expression/bind_function_expression.cpp index 9362ac1024e..2cf587445e4 100644 --- a/src/binder/bind_expression/bind_function_expression.cpp +++ b/src/binder/bind_expression/bind_function_expression.cpp @@ -42,6 +42,17 @@ std::shared_ptr ExpressionBinder::bindFunctionExpression( std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( const ParsedExpression& parsedExpression, const std::string& functionName) { expression_vector children; + + if (functionName == "CAST") { + if (parsedExpression.getNumChildren() != 2) { + throw BinderException("Cannot match a built-in function for given function CAST"); + } + auto type = binder->bindDataType(parsedExpression.getChild(1)->toString()); + children.push_back(bindExpression(*parsedExpression.getChild(0))); + + return bindScalarFunctionExpression(children, functionName, type.get()); + } + for (auto i = 0u; i < parsedExpression.getNumChildren(); ++i) { auto child = bindExpression(*parsedExpression.getChild(i)); children.push_back(std::move(child)); @@ -50,14 +61,21 @@ std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( } std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( - const expression_vector& children, const std::string& functionName) { + const expression_vector& children, const std::string& functionName, const LogicalType* type) { auto builtInFunctions = binder->catalog.getBuiltInFunctions(); std::vector childrenTypes; for (auto& child : children) { childrenTypes.push_back(&child->dataType); } - auto function = reinterpret_cast( - builtInFunctions->matchScalarFunction(functionName, childrenTypes)); + + function::ScalarFunction* function; + if (type) { + function = reinterpret_cast( + builtInFunctions->matchCastScalarFunction(functionName, childrenTypes, type)); + } else { + function = reinterpret_cast( + builtInFunctions->matchScalarFunction(functionName, childrenTypes)); + } expression_vector childrenAfterCast; for (auto i = 0u; i < children.size(); ++i) { auto targetType = @@ -68,14 +86,19 @@ std::shared_ptr ExpressionBinder::bindScalarFunctionExpression( if (function->bindFunc) { bindData = function->bindFunc(childrenAfterCast, function); } else { - bindData = - std::make_unique(LogicalType(function->returnTypeID)); + if (function->castFunc) { + bindData = std::make_unique( + LogicalType(function->returnTypeID)); + } else { + bindData = + std::make_unique(LogicalType(function->returnTypeID)); + } } auto uniqueExpressionName = ScalarFunctionExpression::getUniqueName(function->name, childrenAfterCast); return make_shared(functionName, FUNCTION, std::move(bindData), std::move(childrenAfterCast), function->execFunc, function->selectFunc, - function->compileFunc, uniqueExpressionName); + function->compileFunc, function->castFunc, uniqueExpressionName); } std::shared_ptr ExpressionBinder::bindAggregateFunctionExpression( diff --git a/src/binder/expression/function_expression.cpp b/src/binder/expression/function_expression.cpp index f3f4dd21f50..d0f4e4e09a9 100644 --- a/src/binder/expression/function_expression.cpp +++ b/src/binder/expression/function_expression.cpp @@ -18,6 +18,10 @@ std::string ScalarFunctionExpression::getUniqueName( std::string ScalarFunctionExpression::toStringInternal() const { auto result = functionName + "("; result += ExpressionUtil::toString(children); + if (functionName == "CAST") { + result += ", "; + result += common::LogicalTypeUtils::dataTypeToString(bindData->resultType); + } result += ")"; return result; } diff --git a/src/c_api/value.cpp b/src/c_api/value.cpp index 21f73c6260b..5f84f044cf9 100644 --- a/src/c_api/value.cpp +++ b/src/c_api/value.cpp @@ -269,7 +269,7 @@ kuzu_int128_t kuzu_int128_t_from_string(const char* str) { int128_t int128_val = 0; kuzu_int128_t c_int128; try { - kuzu::function::CastStringToTypes::operation(str, strlen(str), int128_val); + kuzu::function::CastStringToTypes::operation(ku_string_t{str, strlen(str)}, int128_val); c_int128.low = int128_val.low; c_int128.high = int128_val.high; } catch (ConversionException& e) { diff --git a/src/common/types/ku_string.cpp b/src/common/types/ku_string.cpp index 1f81183426b..f1db589b9c0 100644 --- a/src/common/types/ku_string.cpp +++ b/src/common/types/ku_string.cpp @@ -3,6 +3,15 @@ namespace kuzu { namespace common { +ku_string_t::ku_string_t(const char* value, uint64_t length) : len(length) { + if (isShortString(length)) { + memcpy(prefix, value, length); + return; + } + overflowPtr = (uint64_t)(value); + memcpy(prefix, value, PREFIX_LENGTH); +} + void ku_string_t::set(const std::string& value) { set(value.data(), value.length()); } diff --git a/src/expression_evaluator/function_evaluator.cpp b/src/expression_evaluator/function_evaluator.cpp index 46b37062e27..5320ab87410 100644 --- a/src/expression_evaluator/function_evaluator.cpp +++ b/src/expression_evaluator/function_evaluator.cpp @@ -11,9 +11,11 @@ namespace evaluator { void FunctionExpressionEvaluator::init(const ResultSet& resultSet, MemoryManager* memoryManager) { ExpressionEvaluator::init(resultSet, memoryManager); - execFunc = ((binder::ScalarFunctionExpression&)*expression).execFunc; + auto expr = reinterpret_cast(expression.get()); + execFunc = expr->execFunc; + castFunc = expr->castFunc; if (expression->dataType.getLogicalTypeID() == LogicalTypeID::BOOL) { - selectFunc = ((binder::ScalarFunctionExpression&)*expression).selectFunc; + selectFunc = expr->selectFunc; } } @@ -21,6 +23,13 @@ void FunctionExpressionEvaluator::evaluate() { for (auto& child : children) { child->evaluate(); } + if (castFunc != nullptr) { + auto expr = reinterpret_cast(expression.get()); + castFunc(parameters, *resultVector, + &reinterpret_cast(expr->getBindData()) + ->csvConfig); + return; + } if (execFunc != nullptr) { execFunc(parameters, *resultVector); } diff --git a/src/function/built_in_functions.cpp b/src/function/built_in_functions.cpp index 0ab534eb4e8..021c258f446 100644 --- a/src/function/built_in_functions.cpp +++ b/src/function/built_in_functions.cpp @@ -87,6 +87,22 @@ Function* BuiltInFunctions::matchScalarFunction( return candidateFunctions[0]; } +Function* BuiltInFunctions::matchCastScalarFunction( + const std::string& name, const std::vector& inputTypes, const LogicalType* type) { + auto& functionSet = functions.at(name); + std::vector candidateFunctions; + for (auto& function : functionSet) { + if (function->parameterTypeIDs[0] == inputTypes[0]->getLogicalTypeID() && + reinterpret_cast(function.get())->returnTypeID == + type->getLogicalTypeID()) { + candidateFunctions.push_back(function.get()); + break; + } + } + validateNonEmptyCandidateFunctions(candidateFunctions, name, inputTypes); + return candidateFunctions[0]; +} + AggregateFunction* BuiltInFunctions::matchAggregateFunction( const std::string& name, const std::vector& inputTypes, bool isDistinct) { auto& functionSet = functions.at(name); @@ -597,6 +613,7 @@ void BuiltInFunctions::registerCastFunctions() { functions.insert({CAST_TO_UINT8_FUNC_NAME, CastToUInt8Function::getFunctionSet()}); functions.insert({CAST_TO_INT128_FUNC_NAME, CastToInt128Function::getFunctionSet()}); functions.insert({CAST_TO_BOOL_FUNC_NAME, CastToBoolFunction::getFunctionSet()}); + functions.insert({CAST_FUNC_NAME, CastAnyFunction::getFunctionSet()}); } void BuiltInFunctions::registerListFunctions() { diff --git a/src/function/cast_string_to_functions.cpp b/src/function/cast_string_to_functions.cpp index ded1a86e31b..5cbfe9b7c6e 100644 --- a/src/function/cast_string_to_functions.cpp +++ b/src/function/cast_string_to_functions.cpp @@ -13,26 +13,118 @@ using namespace kuzu::common; namespace kuzu { namespace function { +// ---------------------- cast String to Types Helper ------------------------------ // +struct CastStringToTypesHelper { + template + static void cast(const char* input, uint64_t len, T& result, ValueVector* /*vector*/ = nullptr, + uint64_t /*rowToAdd*/ = 0, const CSVReaderConfig* /*csvReaderConfig*/ = nullptr) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::INT64}); + } +}; + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, int128_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleInt128Cast(input, len, result); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, int32_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::INT32}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, int16_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::INT16}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, int8_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::INT8}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, uint64_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::UINT64}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, uint32_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::UINT32}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, uint16_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::UINT16}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, uint8_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + simpleIntegerCast(input, len, result, LogicalType{LogicalTypeID::UINT8}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, float_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + doubleCast(input, len, result, LogicalType{LogicalTypeID::FLOAT}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, double_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + doubleCast(input, len, result, LogicalType{LogicalTypeID::DOUBLE}); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, bool& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + castStringToBool(input, len, result); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, date_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + result = Date::fromCString(input, len); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, timestamp_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + result = Timestamp::fromCString(input, len); +} + +template<> +inline void CastStringToTypesHelper::cast(const char* input, uint64_t len, interval_t& result, + ValueVector* /*vector*/, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*csvReaderConfig*/) { + result = Interval::fromCString(input, len); +} + // ---------------------- cast String to Blob ------------------------------ // template<> -void CastStringToTypes::operation( - common::ku_string_t& input, common::blob_t& result, common::ValueVector& resultVector) { - result.value.len = common::Blob::getBlobSize(input); - if (!common::ku_string_t::isShortString(result.value.len)) { - auto overflowBuffer = common::StringVector::getInMemOverflowBuffer(&resultVector); +void CastStringToTypes::operation(const ku_string_t& input, blob_t& result, + ValueVector* resultVector, uint64_t /*rowToAdd*/, const CSVReaderConfig* /*CSVReaderConfig*/) { + result.value.len = Blob::getBlobSize(input); + if (!ku_string_t::isShortString(result.value.len)) { + auto overflowBuffer = StringVector::getInMemOverflowBuffer(resultVector); auto overflowPtr = overflowBuffer->allocateSpace(result.value.len); result.value.overflowPtr = reinterpret_cast(overflowPtr); - common::Blob::fromString( - reinterpret_cast(input.getData()), input.len, overflowPtr); - memcpy(result.value.prefix, overflowPtr, common::ku_string_t::PREFIX_LENGTH); + Blob::fromString(reinterpret_cast(input.getData()), input.len, overflowPtr); + memcpy(result.value.prefix, overflowPtr, ku_string_t::PREFIX_LENGTH); } else { - common::Blob::fromString( + Blob::fromString( reinterpret_cast(input.getData()), input.len, result.value.prefix); } } template<> -void CastStringToTypes::operation(const char* input, uint64_t len, common::blob_t& /*result*/, +void CastStringToTypesHelper::cast(const char* input, uint64_t len, blob_t& /*result*/, ValueVector* vector, uint64_t rowToAdd, const CSVReaderConfig* /*CSVReaderConfig*/) { // base case: blob storage::TableCopyUtils::validateStrLen(len); @@ -200,7 +292,7 @@ static inline void startListCast(const char* input, uint64_t len, T split, } template<> -void CastStringToTypes::operation(const char* input, uint64_t len, list_entry_t& /*result*/, +void CastStringToTypesHelper::cast(const char* input, uint64_t len, list_entry_t& /*result*/, ValueVector* vector, uint64_t rowToAdd, const CSVReaderConfig* csvReaderConfig) { // calculate the number of elements in array CountPartOperation state; @@ -214,6 +306,13 @@ void CastStringToTypes::operation(const char* input, uint64_t len, list_entry_t& startListCast(input, len, split, csvReaderConfig, vector); } +template<> +void CastStringToTypes::operation(const ku_string_t& input, list_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig) { + CastStringToTypesHelper::cast(reinterpret_cast(input.getData()), input.len, result, + resultVector, rowToAdd, CSVReaderConfig); +} + // ---------------------- cast String to FixedList ------------------------------ // template struct SplitStringFixedListOperation { @@ -231,7 +330,7 @@ struct SplitStringFixedListOperation { throw ConversionException("Cast failed. NULL is not allowed for FIXEDLIST."); } auto type = FixedListType::getChildType(&resultVector->dataType); - function::CastStringToTypes::operation(start, str.length(), value); + CastStringToTypesHelper::cast(start, str.length(), value); resultVector->setValue(offset, value); offset++; } @@ -379,7 +478,7 @@ static bool splitCStringMap( } template<> -void CastStringToTypes::operation(const char* input, uint64_t len, common::map_entry_t& /*result*/, +void CastStringToTypesHelper::cast(const char* input, uint64_t len, map_entry_t& /*result*/, ValueVector* vector, uint64_t rowToAdd, const CSVReaderConfig* csvReaderConfig) { // count the number of maps in map CountPartOperation state; @@ -396,6 +495,13 @@ void CastStringToTypes::operation(const char* input, uint64_t len, common::map_e } } +template<> +void CastStringToTypes::operation(const ku_string_t& input, map_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig) { + CastStringToTypesHelper::cast(reinterpret_cast(input.getData()), input.len, result, + resultVector, rowToAdd, CSVReaderConfig); +} + // ---------------------- cast String to Struct ------------------------------ // static bool parseStructFieldName(const char*& input, const char* end) { while (input < end) { @@ -486,7 +592,7 @@ static bool tryCastStringToStruct(const char* input, uint64_t len, ValueVector* } template<> -void CastStringToTypes::operation(const char* input, uint64_t len, struct_entry_t& /*result*/, +void CastStringToTypesHelper::cast(const char* input, uint64_t len, struct_entry_t& /*result*/, ValueVector* vector, uint64_t rowToAdd, const CSVReaderConfig* csvReaderConfig) { if (!tryCastStringToStruct(input, len, vector, rowToAdd, csvReaderConfig)) { throw ConversionException("Cast failed. " + std::string{input, len} + " is not in " + @@ -494,6 +600,13 @@ void CastStringToTypes::operation(const char* input, uint64_t len, struct_entry_ } } +template<> +void CastStringToTypes::operation(const ku_string_t& input, struct_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig) { + CastStringToTypesHelper::cast(reinterpret_cast(input.getData()), input.len, result, + resultVector, rowToAdd, CSVReaderConfig); +} + // ---------------------- cast String to Union ------------------------------ // template static inline void testAndSetValue(ValueVector* vector, uint64_t rowToAdd, T result, bool success) { @@ -589,7 +702,7 @@ static bool tryCastUnionField( } template<> -void CastStringToTypes::operation(const char* input, uint64_t len, union_entry_t& /*result*/, +void CastStringToTypesHelper::cast(const char* input, uint64_t len, union_entry_t& /*result*/, ValueVector* vector, uint64_t rowToAdd, const CSVReaderConfig* /*CSVReaderConfig**/) { auto& type = vector->dataType; union_field_idx_t selectedFieldIdx = INVALID_STRUCT_FIELD_IDX; @@ -616,6 +729,13 @@ void CastStringToTypes::operation(const char* input, uint64_t len, union_entry_t ->setNull(rowToAdd, false /* isNull */); } +template<> +void CastStringToTypes::operation(const ku_string_t& input, union_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig) { + CastStringToTypesHelper::cast(reinterpret_cast(input.getData()), input.len, result, + resultVector, rowToAdd, CSVReaderConfig); +} + void CastStringToTypes::copyStringToVector(ValueVector* vector, uint64_t rowToAdd, std::string_view strVal, const CSVReaderConfig* csvReaderConfig) { auto& type = vector->dataType; @@ -629,67 +749,68 @@ void CastStringToTypes::copyStringToVector(ValueVector* vector, uint64_t rowToAd switch (type.getLogicalTypeID()) { case LogicalTypeID::INT128: { int128_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::INT64: { int64_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::INT32: { int32_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::INT16: { int16_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::INT8: { int8_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::UINT64: { uint64_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::UINT32: { uint32_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::UINT16: { uint16_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::UINT8: { uint8_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::FLOAT: { float_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::DOUBLE: { double_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::BOOL: { bool val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::BLOB: { blob_t val; - operation(strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); + CastStringToTypesHelper::cast( + strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); } break; case LogicalTypeID::STRING: { storage::TableCopyUtils::validateStrLen(strVal.length()); @@ -700,26 +821,28 @@ void CastStringToTypes::copyStringToVector(ValueVector* vector, uint64_t rowToAd } break; case LogicalTypeID::DATE: { date_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::TIMESTAMP: { timestamp_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::INTERVAL: { interval_t val; - operation(strVal.data(), strVal.length(), val); + CastStringToTypesHelper::cast(strVal.data(), strVal.length(), val); vector->setValue(rowToAdd, val); } break; case LogicalTypeID::MAP: { map_entry_t val; - operation(strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); + CastStringToTypesHelper::cast( + strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); } break; case LogicalTypeID::VAR_LIST: { list_entry_t val; - operation(strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); + CastStringToTypesHelper::cast( + strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); } break; case LogicalTypeID::FIXED_LIST: { // TODO: add fix list function wrapper @@ -727,11 +850,13 @@ void CastStringToTypes::copyStringToVector(ValueVector* vector, uint64_t rowToAd } break; case LogicalTypeID::STRUCT: { struct_entry_t val; - operation(strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); + CastStringToTypesHelper::cast( + strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); } break; case LogicalTypeID::UNION: { union_entry_t val; - operation(strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); + CastStringToTypesHelper::cast( + strVal.data(), strVal.length(), val, vector, rowToAdd, csvReaderConfig); } break; default: { // LCOV_EXCL_START throw NotImplementedException("CastStringToTypes::operation"); diff --git a/src/function/vector_cast_functions.cpp b/src/function/vector_cast_functions.cpp index 7049e106b7b..c3e7f36e289 100644 --- a/src/function/vector_cast_functions.cpp +++ b/src/function/vector_cast_functions.cpp @@ -125,20 +125,19 @@ void CastFunction::bindImplicitCastFunc( } case LogicalTypeID::DATE: { assert(sourceTypeID == LogicalTypeID::STRING); - func = &ScalarFunction::UnaryStringExecFunction; + func = &UnaryStringCastExecFunction; return; } case LogicalTypeID::TIMESTAMP: { assert(sourceTypeID == LogicalTypeID::STRING || sourceTypeID == LogicalTypeID::DATE); func = sourceTypeID == LogicalTypeID::STRING ? - &ScalarFunction::UnaryStringExecFunction : + &UnaryStringCastExecFunction : &ScalarFunction::UnaryExecFunction; return; } case LogicalTypeID::INTERVAL: { assert(sourceTypeID == LogicalTypeID::STRING); - func = &ScalarFunction::UnaryStringExecFunction; + func = &UnaryStringCastExecFunction; return; } default: @@ -453,5 +452,109 @@ function_set CastToUInt8Function::getFunctionSet() { return result; } +function_set CastAnyFunction::getFunctionSet() { + function_set result; + // cast string to + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::DATE)); + result.push_back(CastFunction::bindCastStringToFunction( + CAST_FUNC_NAME, LogicalTypeID::TIMESTAMP)); + result.push_back(CastFunction::bindCastStringToFunction( + CAST_FUNC_NAME, LogicalTypeID::INTERVAL)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::BLOB)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::BOOL)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::DOUBLE)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::FLOAT)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::INT128)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::INT64)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::INT64)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::INT32)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::INT16)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::INT8)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::UINT64)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::UINT32)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::UINT16)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::UINT8)); + result.push_back(CastFunction::bindCastStringToFunction( + CAST_FUNC_NAME, LogicalTypeID::VAR_LIST)); + result.push_back( + CastFunction::bindCastStringToFunction(CAST_FUNC_NAME, LogicalTypeID::MAP)); + result.push_back(CastFunction::bindCastStringToFunction( + CAST_FUNC_NAME, LogicalTypeID::STRUCT)); + result.push_back(CastFunction::bindCastStringToFunction( + CAST_FUNC_NAME, LogicalTypeID::UNION)); + // cast to other types + for (auto& type : LogicalTypeUtils::getAllValidLogicTypes()) { + scalar_exec_func execFunc; + CastToStringFunction::getUnaryCastToStringExecFunction(type.getLogicalTypeID(), execFunc); + auto func = std::make_unique(CAST_FUNC_NAME, + std::vector{type.getLogicalTypeID()}, LogicalTypeID::STRING, execFunc); + result.push_back(std::move(func)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_FUNC_NAME, typeID, LogicalTypeID::DOUBLE)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_FLOAT_FUNC_NAME, typeID, LogicalTypeID::FLOAT)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_INT128_FUNC_NAME, typeID, LogicalTypeID::INT128)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_SERIAL_FUNC_NAME, typeID, LogicalTypeID::SERIAL)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_INT64_FUNC_NAME, typeID, LogicalTypeID::INT64)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_INT32_FUNC_NAME, typeID, LogicalTypeID::INT32)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_INT16_FUNC_NAME, typeID, LogicalTypeID::INT16)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_INT8_FUNC_NAME, typeID, LogicalTypeID::INT8)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_UINT64_FUNC_NAME, typeID, LogicalTypeID::UINT64)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_UINT32_FUNC_NAME, typeID, LogicalTypeID::UINT32)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_UINT16_FUNC_NAME, typeID, LogicalTypeID::UINT16)); + } + for (auto typeID : LogicalTypeUtils::getNumericalLogicalTypeIDs()) { + result.push_back(CastFunction::bindNumericCastFunction( + CAST_TO_UINT8_FUNC_NAME, typeID, LogicalTypeID::UINT8)); + } + return result; +} + } // namespace function } // namespace kuzu diff --git a/src/include/binder/expression/function_expression.h b/src/include/binder/expression/function_expression.h index d4357b425c7..1c5a9eb842e 100644 --- a/src/include/binder/expression/function_expression.h +++ b/src/include/binder/expression/function_expression.h @@ -45,17 +45,18 @@ class ScalarFunctionExpression : public FunctionExpression { function::scalar_exec_func execFunc, function::scalar_select_func selectFunc, const std::string& uniqueName) : ScalarFunctionExpression{std::move(functionName), expressionType, std::move(bindData), - std::move(children), std::move(execFunc), std::move(selectFunc), nullptr, + std::move(children), std::move(execFunc), std::move(selectFunc), nullptr, nullptr, uniqueName} {} ScalarFunctionExpression(std::string functionName, common::ExpressionType expressionType, std::unique_ptr bindData, expression_vector children, function::scalar_exec_func execFunc, function::scalar_select_func selectFunc, - function::scalar_compile_func compileFunc, const std::string& uniqueName) + function::scalar_compile_func compileFunc, function::string_cast_func castFunc, + const std::string& uniqueName) : FunctionExpression{std::move(functionName), expressionType, std::move(bindData), std::move(children), uniqueName}, - execFunc{std::move(execFunc)}, selectFunc{std::move(selectFunc)}, compileFunc{std::move( - compileFunc)} {} + execFunc{std::move(execFunc)}, selectFunc{std::move(selectFunc)}, castFunc{castFunc}, + compileFunc{std::move(compileFunc)} {} static std::string getUniqueName(const std::string& functionName, expression_vector& children); @@ -65,6 +66,7 @@ class ScalarFunctionExpression : public FunctionExpression { function::scalar_exec_func execFunc; function::scalar_select_func selectFunc; function::scalar_compile_func compileFunc; + function::string_cast_func castFunc; }; class AggregateFunctionExpression : public FunctionExpression { diff --git a/src/include/binder/expression_binder.h b/src/include/binder/expression_binder.h index 4a1956fe6fb..d96ef200962 100644 --- a/src/include/binder/expression_binder.h +++ b/src/include/binder/expression_binder.h @@ -62,8 +62,8 @@ class ExpressionBinder { std::shared_ptr bindScalarFunctionExpression( const parser::ParsedExpression& parsedExpression, const std::string& functionName); - std::shared_ptr bindScalarFunctionExpression( - const expression_vector& children, const std::string& functionName); + std::shared_ptr bindScalarFunctionExpression(const expression_vector& children, + const std::string& functionName, const common::LogicalType* type = nullptr); std::shared_ptr bindAggregateFunctionExpression( const parser::ParsedExpression& parsedExpression, const std::string& functionName, bool isDistinct); diff --git a/src/include/common/enums/expression_type.h b/src/include/common/enums/expression_type.h index 9e2a1cfd076..87abf22c255 100644 --- a/src/include/common/enums/expression_type.h +++ b/src/include/common/enums/expression_type.h @@ -20,6 +20,7 @@ const std::string MAX_FUNC_NAME = "MAX"; const std::string COLLECT_FUNC_NAME = "COLLECT"; // cast +const std::string CAST_FUNC_NAME = "CAST"; const std::string CAST_DATE_FUNC_NAME = "DATE"; const std::string CAST_TO_DATE_FUNC_NAME = "TO_DATE"; const std::string CAST_TO_TIMESTAMP_FUNC_NAME = "TIMESTAMP"; diff --git a/src/include/common/types/ku_string.h b/src/include/common/types/ku_string.h index 273a04ae3ae..73d27d3b064 100644 --- a/src/include/common/types/ku_string.h +++ b/src/include/common/types/ku_string.h @@ -21,6 +21,7 @@ struct ku_string_t { }; ku_string_t() : len{0}, overflowPtr{0} {} + ku_string_t(const char* value, uint64_t length); static bool isShortString(uint32_t len) { return len <= SHORT_STR_LENGTH; } diff --git a/src/include/expression_evaluator/function_evaluator.h b/src/include/expression_evaluator/function_evaluator.h index f49197ff150..688bfedf275 100644 --- a/src/include/expression_evaluator/function_evaluator.h +++ b/src/include/expression_evaluator/function_evaluator.h @@ -10,8 +10,8 @@ class FunctionExpressionEvaluator : public ExpressionEvaluator { public: FunctionExpressionEvaluator(std::shared_ptr expression, std::vector> children) - : ExpressionEvaluator{std::move(children)}, - expression{std::move(expression)}, execFunc{nullptr}, selectFunc{nullptr} {} + : ExpressionEvaluator{std::move(children)}, expression{std::move(expression)}, + execFunc{nullptr}, selectFunc{nullptr}, castFunc{nullptr} {} void init( const processor::ResultSet& resultSet, storage::MemoryManager* memoryManager) override; @@ -30,6 +30,7 @@ class FunctionExpressionEvaluator : public ExpressionEvaluator { std::shared_ptr expression; function::scalar_exec_func execFunc; function::scalar_select_func selectFunc; + function::string_cast_func castFunc; std::vector> parameters; }; diff --git a/src/include/function/built_in_function.h b/src/include/function/built_in_function.h index e4c2a5091db..69313d87e35 100644 --- a/src/include/function/built_in_function.h +++ b/src/include/function/built_in_function.h @@ -25,6 +25,8 @@ class BuiltInFunctions { // functions. Function* matchScalarFunction( const std::string& name, const std::vector& inputTypes); + Function* matchCastScalarFunction(const std::string& name, + const std::vector& inputTypes, const common::LogicalType* type); AggregateFunction* matchAggregateFunction(const std::string& name, const std::vector& inputTypes, bool isDistinct); diff --git a/src/include/function/cast/functions/cast_string_to_functions.h b/src/include/function/cast/functions/cast_string_to_functions.h index 3dcac7841d8..10c352ee1e4 100644 --- a/src/include/function/cast/functions/cast_string_to_functions.h +++ b/src/include/function/cast/functions/cast_string_to_functions.h @@ -10,276 +10,158 @@ #include "common/types/blob.h" #include "common/vector/value_vector.h" +using namespace kuzu::common; + namespace kuzu { namespace function { struct CastStringToTypes { - static void copyStringToVector(common::ValueVector* vector, uint64_t rowToAdd, - std::string_view strVal, const common::CSVReaderConfig* csvReaderConfig); + static void copyStringToVector(ValueVector* vector, uint64_t rowToAdd, std::string_view strVal, + const CSVReaderConfig* csvReaderConfig); template - static inline bool tryCast(const char* input, uint64_t len, T& result) { + static inline bool tryCast(const ku_string_t& input, T& result) { // try cast for signed integer types - return trySimpleIntegerCast(input, len, result); + return trySimpleIntegerCast( + reinterpret_cast(input.getData()), input.len, result); } template - static inline void operation( - common::ku_string_t& input, T& result, common::ValueVector& /*resultVector*/) { + static inline void operation(const ku_string_t& input, T& result, + ValueVector* /*resultVector*/ = nullptr, uint64_t /*rowToAdd*/ = 0, + const CSVReaderConfig* /*CSVReaderConfig*/ = nullptr) { // base case: int64 - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::INT64}); - } - - template - static void operation(const char* input, uint64_t len, T& result, - common::ValueVector* /*vector*/ = nullptr, uint64_t /*rowToAdd*/ = 0, - const common::CSVReaderConfig* /*csvReaderConfig*/ = nullptr) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::INT64}); + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalType{LogicalTypeID::INT64}); } }; template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, common::int128_t& result, common::ValueVector& /*resultVector*/) { - simpleInt128Cast((char*)input.getData(), input.len, result); +inline void CastStringToTypes::operation(const ku_string_t& input, int128_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleInt128Cast(reinterpret_cast(input.getData()), input.len, result); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, int32_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::INT32}); +inline void CastStringToTypes::operation(const ku_string_t& input, int32_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, + LogicalType{LogicalTypeID::INT32}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, int16_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::INT16}); +inline void CastStringToTypes::operation(const ku_string_t& input, int16_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, + LogicalType{LogicalTypeID::INT16}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, int8_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::INT8}); +inline void CastStringToTypes::operation(const ku_string_t& input, int8_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, result, + LogicalType{LogicalTypeID::INT8}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, uint64_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::UINT64}); +inline void CastStringToTypes::operation(const ku_string_t& input, uint64_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalType{LogicalTypeID::UINT64}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, uint32_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::UINT32}); +inline void CastStringToTypes::operation(const ku_string_t& input, uint32_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalType{LogicalTypeID::UINT32}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, uint16_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::UINT16}); +inline void CastStringToTypes::operation(const ku_string_t& input, uint16_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalType{LogicalTypeID::UINT16}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, uint8_t& result, common::ValueVector& /*resultVector*/) { - simpleIntegerCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::UINT8}); +inline void CastStringToTypes::operation(const ku_string_t& input, uint8_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + simpleIntegerCast(reinterpret_cast(input.getData()), input.len, + result, LogicalType{LogicalTypeID::UINT8}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, float_t& result, common::ValueVector& /*resultVector*/) { - doubleCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::FLOAT}); +inline void CastStringToTypes::operation(const ku_string_t& input, float_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + doubleCast(reinterpret_cast(input.getData()), input.len, result, + LogicalType{LogicalTypeID::FLOAT}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, double_t& result, common::ValueVector& /*resultVector*/) { - doubleCast((char*)input.getData(), input.len, result, - common::LogicalType{common::LogicalTypeID::DOUBLE}); +inline void CastStringToTypes::operation(const ku_string_t& input, double_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + doubleCast(reinterpret_cast(input.getData()), input.len, result, + LogicalType{LogicalTypeID::DOUBLE}); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, common::date_t& result, common::ValueVector& /*resultVector*/) { - result = common::Date::fromCString((const char*)input.getData(), input.len); +inline void CastStringToTypes::operation(const ku_string_t& input, date_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + result = Date::fromCString((const char*)input.getData(), input.len); } template<> -inline void CastStringToTypes::operation(common::ku_string_t& input, common::timestamp_t& result, - common::ValueVector& /*resultVector*/) { - result = common::Timestamp::fromCString((const char*)input.getData(), input.len); +inline void CastStringToTypes::operation(const ku_string_t& input, timestamp_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + result = Timestamp::fromCString((const char*)input.getData(), input.len); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, common::interval_t& result, common::ValueVector& /*resultVector*/) { - result = common::Interval::fromCString((const char*)input.getData(), input.len); +inline void CastStringToTypes::operation(const ku_string_t& input, interval_t& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { + result = Interval::fromCString((const char*)input.getData(), input.len); } template<> -inline void CastStringToTypes::operation( - common::ku_string_t& input, bool& result, common::ValueVector& /*resultVector*/) { +inline void CastStringToTypes::operation(const ku_string_t& input, bool& result, + ValueVector* /*resultVector*/, uint64_t /*rowToAdd*/, + const CSVReaderConfig* /*CSVReaderConfig*/) { castStringToBool(reinterpret_cast(input.getData()), input.len, result); } template<> -void CastStringToTypes::operation( - common::ku_string_t& input, common::blob_t& result, common::ValueVector& resultVector); - -template<> -void CastStringToTypes::operation( - common::ku_string_t& input, common::list_entry_t& result, common::ValueVector& resultVector); - -template<> -void CastStringToTypes::operation( - common::ku_string_t& input, common::map_entry_t& result, common::ValueVector& resultVector); - -template<> -void CastStringToTypes::operation( - common::ku_string_t& input, common::union_entry_t& result, common::ValueVector& resultVector); - -template<> -void CastStringToTypes::operation( - common::ku_string_t& input, common::struct_entry_t& result, common::ValueVector& resultVector); - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, common::int128_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleInt128Cast(input, len, result); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, int32_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::INT32}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, int16_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::INT16}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, int8_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast(input, len, result, common::LogicalType{common::LogicalTypeID::INT8}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, uint64_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::UINT64}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, uint32_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::UINT32}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, uint16_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::UINT16}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, uint8_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - simpleIntegerCast( - input, len, result, common::LogicalType{common::LogicalTypeID::UINT8}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, float_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - doubleCast(input, len, result, common::LogicalType{common::LogicalTypeID::FLOAT}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, double_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - doubleCast(input, len, result, common::LogicalType{common::LogicalTypeID::DOUBLE}); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, bool& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - castStringToBool(input, len, result); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, common::date_t& result, - common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - result = common::Date::fromCString(input, len); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, - common::timestamp_t& result, common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - result = common::Timestamp::fromCString(input, len); -} - -template<> -inline void CastStringToTypes::operation(const char* input, uint64_t len, - common::interval_t& result, common::ValueVector* /*vector*/, uint64_t /*rowToAdd*/, - const common::CSVReaderConfig* /*csvReaderConfig*/) { - result = common::Interval::fromCString(input, len); -} - -template<> -void CastStringToTypes::operation(const char* input, uint64_t len, common::blob_t& result, - common::ValueVector* vector, uint64_t rowToAdd, const common::CSVReaderConfig* csvReaderConfig); +void CastStringToTypes::operation(const ku_string_t& input, blob_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig); template<> -void CastStringToTypes::operation(const char* input, uint64_t len, - common::list_entry_t& result, common::ValueVector* vector, uint64_t rowToAdd, - const common::CSVReaderConfig* csvReaderConfig); +void CastStringToTypes::operation(const ku_string_t& input, list_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig); template<> -void CastStringToTypes::operation(const char* input, uint64_t len, - common::map_entry_t& result, common::ValueVector* vector, uint64_t rowToAdd, - const common::CSVReaderConfig* csvReaderConfig); +void CastStringToTypes::operation(const ku_string_t& input, map_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig); template<> -void CastStringToTypes::operation(const char* input, uint64_t len, - common::struct_entry_t& result, common::ValueVector* vector, uint64_t rowToAdd, - const common::CSVReaderConfig* csvReaderConfig); +void CastStringToTypes::operation(const ku_string_t& input, struct_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig); template<> -void CastStringToTypes::operation(const char* input, uint64_t len, - common::union_entry_t& result, common::ValueVector* vector, uint64_t rowToAdd, - const common::CSVReaderConfig* csvReaderConfig); +void CastStringToTypes::operation(const ku_string_t& input, union_entry_t& result, + ValueVector* resultVector, uint64_t rowToAdd, const CSVReaderConfig* CSVReaderConfig); } // namespace function } // namespace kuzu diff --git a/src/include/function/cast/vector_cast_functions.h b/src/include/function/cast/vector_cast_functions.h index 394a5911ff1..da34bcf8356 100644 --- a/src/include/function/cast/vector_cast_functions.h +++ b/src/include/function/cast/vector_cast_functions.h @@ -87,13 +87,37 @@ struct CastFunction { } } + template + static void UnaryStringCastFunction( + const std::vector>& params, + common::ValueVector& result, const common::CSVReaderConfig* csvConfig) { + assert(params.size() == 1); + result.resetAuxiliaryBuffer(); + auto resultValues = (RESULT_TYPE*)result.getData(); + auto operand = params[0].get(); + + // TODO: null-non guarentee + for (auto selectedPos = 0u; selectedPos < operand->state->selVector->selectedSize; + ++selectedPos) { + auto input = ((OPERAND_TYPE*)operand->getData())[selectedPos]; + FUNC::template operation( + input, resultValues[selectedPos], &result, selectedPos, csvConfig); + } + } + + template + static inline void UnaryStringCastExecFunction( + const std::vector>& params, + common::ValueVector& result) { + UnaryStringCastFunction(params, result, nullptr); + } + template inline static std::unique_ptr bindCastStringToFunction( const std::string& funcName, common::LogicalTypeID targetTypeID) { return std::make_unique(funcName, std::vector{common::LogicalTypeID::STRING}, targetTypeID, - ScalarFunction::UnaryStringExecFunction); + UnaryStringCastFunction); } }; @@ -171,5 +195,9 @@ struct CastToUInt8Function { static function_set getFunctionSet(); }; +struct CastAnyFunction { + static function_set getFunctionSet(); +}; + } // namespace function } // namespace kuzu diff --git a/src/include/function/function.h b/src/include/function/function.h index 62e0ba5cb4b..d16ac31532d 100644 --- a/src/include/function/function.h +++ b/src/include/function/function.h @@ -1,6 +1,7 @@ #pragma once #include "binder/expression/expression.h" +#include "common/copier_config/copier_config.h" #include "common/enums/expression_type.h" namespace kuzu { @@ -14,6 +15,13 @@ struct FunctionBindData { virtual ~FunctionBindData() = default; }; +struct StringCastFunctionBindData : public FunctionBindData { + common::CSVReaderConfig csvConfig; + + StringCastFunctionBindData(common::LogicalType dataType) + : FunctionBindData{std::move(dataType)} {} +}; + struct Function; using scalar_bind_func = std::function( const binder::expression_vector&, Function* definition)>; diff --git a/src/include/function/scalar_function.h b/src/include/function/scalar_function.h index afb98d8615e..6c0167cdbf2 100644 --- a/src/include/function/scalar_function.h +++ b/src/include/function/scalar_function.h @@ -20,35 +20,52 @@ using scalar_exec_func = std::function>&, common::SelectionVector&)>; using function_set = std::vector>; +using string_cast_func = + std::function>&, + common::ValueVector&, const common::CSVReaderConfig*)>; struct ScalarFunction : public BaseScalarFunction { ScalarFunction(std::string name, std::vector parameterTypeIDs, common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, bool isVarLength = false) : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, - std::move(execFunc), nullptr, nullptr, nullptr, isVarLength} {} + std::move(execFunc), nullptr, nullptr, nullptr, nullptr, isVarLength} {} + + ScalarFunction(std::string name, std::vector parameterTypeIDs, + common::LogicalTypeID returnTypeID, string_cast_func castFunc, bool isVarLength = false) + : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, nullptr, + nullptr, nullptr, std::move(castFunc), nullptr, isVarLength} {} ScalarFunction(std::string name, std::vector parameterTypeIDs, common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, scalar_select_func selectFunc, bool isVarLength = false) : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, - std::move(execFunc), std::move(selectFunc), nullptr, nullptr, isVarLength} {} + std::move(execFunc), std::move(selectFunc), nullptr, nullptr, nullptr, isVarLength} {} ScalarFunction(std::string name, std::vector parameterTypeIDs, common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, scalar_select_func selectFunc, scalar_bind_func bindFunc, bool isVarLength = false) : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, - std::move(execFunc), std::move(selectFunc), nullptr, std::move(bindFunc), + std::move(execFunc), std::move(selectFunc), nullptr, nullptr, std::move(bindFunc), isVarLength} {} ScalarFunction(std::string name, std::vector parameterTypeIDs, common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, scalar_select_func selectFunc, scalar_compile_func compileFunc, scalar_bind_func bindFunc, bool isVarLength = false) + : ScalarFunction{std::move(name), std::move(parameterTypeIDs), returnTypeID, + std::move(execFunc), std::move(selectFunc), std::move(compileFunc), nullptr, + std::move(bindFunc), isVarLength} {} + + ScalarFunction(std::string name, std::vector parameterTypeIDs, + common::LogicalTypeID returnTypeID, scalar_exec_func execFunc, + scalar_select_func selectFunc, scalar_compile_func compileFunc, string_cast_func castFunc, + scalar_bind_func bindFunc, bool isVarLength = false) : BaseScalarFunction{FunctionType::SCALAR, std::move(name), std::move(parameterTypeIDs), returnTypeID, std::move(bindFunc)}, execFunc{std::move(execFunc)}, selectFunc(std::move(selectFunc)), - compileFunc{std::move(compileFunc)}, isVarLength{isVarLength} {} + compileFunc{std::move(compileFunc)}, castFunc{std::move(castFunc)}, isVarLength{ + isVarLength} {} template static void TernaryExecFunction(const std::vector>& params, @@ -136,6 +153,7 @@ struct ScalarFunction : public BaseScalarFunction { scalar_exec_func execFunc; scalar_select_func selectFunc; scalar_compile_func compileFunc; + string_cast_func castFunc; // Currently we only one variable-length function which is list creation. The expectation is // that all parameters must have the same type as parameterTypes[0]. bool isVarLength; diff --git a/src/include/storage/in_mem_storage_structure/in_mem_column_chunk.h b/src/include/storage/in_mem_storage_structure/in_mem_column_chunk.h index 0700a2135a7..7b6017afc2a 100644 --- a/src/include/storage/in_mem_storage_structure/in_mem_column_chunk.h +++ b/src/include/storage/in_mem_storage_structure/in_mem_column_chunk.h @@ -53,7 +53,7 @@ class InMemColumnChunk { template void setValueFromString(const char* value, uint64_t length, common::offset_t pos) { T val; - function::CastStringToTypes::operation(value, length, val); + function::CastStringToTypes::operation(ku_string_t{value, length}, val); setValue(val, pos); } diff --git a/src/include/storage/in_mem_storage_structure/in_mem_lists.h b/src/include/storage/in_mem_storage_structure/in_mem_lists.h index c21f3b70621..c90f9fa7007 100644 --- a/src/include/storage/in_mem_storage_structure/in_mem_lists.h +++ b/src/include/storage/in_mem_storage_structure/in_mem_lists.h @@ -51,7 +51,7 @@ class InMemLists { void setValueFromString( common::offset_t nodeOffset, uint64_t pos, const char* val, uint64_t length) { T result; - function::CastStringToTypes::operation(val, length, result); + function::CastStringToTypes::operation(ku_string_t{val, length}, result); setValue(nodeOffset, pos, (uint8_t*)&result); } diff --git a/src/parser/transform/transform_expression.cpp b/src/parser/transform/transform_expression.cpp index 9c1ad4cac50..f45829c6bcc 100644 --- a/src/parser/transform/transform_expression.cpp +++ b/src/parser/transform/transform_expression.cpp @@ -579,13 +579,14 @@ std::string Transformer::transformPropertyKeyName(CypherParser::OC_PropertyKeyNa std::unique_ptr Transformer::transformIntegerLiteral( CypherParser::OC_IntegerLiteralContext& ctx) { auto text = ctx.DecimalInteger()->getText(); + ku_string_t literal{text.c_str(), text.length()}; int64_t result; - if (function::CastStringToTypes::tryCast(text.c_str(), text.length(), result)) { + if (function::CastStringToTypes::tryCast(literal, result)) { return std::make_unique( std::make_unique(result), ctx.getText()); } int128_t result128; - function::CastStringToTypes::operation(text.c_str(), text.length(), result128); + function::CastStringToTypes::operation(literal, result128); return std::make_unique( std::make_unique(result128), ctx.getText()); } @@ -593,8 +594,9 @@ std::unique_ptr Transformer::transformIntegerLiteral( std::unique_ptr Transformer::transformDoubleLiteral( CypherParser::OC_DoubleLiteralContext& ctx) { auto text = ctx.RegularDecimalReal()->getText(); + ku_string_t literal{text.c_str(), text.length()}; double_t result; - function::CastStringToTypes::operation(text.c_str(), text.length(), result); + function::CastStringToTypes::operation(literal, result); return std::make_unique( std::make_unique(result), ctx.getText()); } diff --git a/src/storage/store/table_copy_utils.cpp b/src/storage/store/table_copy_utils.cpp index 8cacdbd835c..3a3f9a66d92 100644 --- a/src/storage/store/table_copy_utils.cpp +++ b/src/storage/store/table_copy_utils.cpp @@ -170,35 +170,36 @@ std::unique_ptr TableCopyUtils::getArrowFixedList(std::string_view l, if (element.empty()) { continue; } + ku_string_t input{element.data(), element.length()}; switch (childDataType->getLogicalTypeID()) { case LogicalTypeID::INT64: { int64_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); memcpy(listVal.get() + numElementsRead * sizeof(int64_t), &val, sizeof(int64_t)); numElementsRead++; } break; case LogicalTypeID::INT32: { int32_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); memcpy(listVal.get() + numElementsRead * sizeof(int32_t), &val, sizeof(int32_t)); numElementsRead++; } break; case LogicalTypeID::INT16: { int16_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); memcpy(listVal.get() + numElementsRead * sizeof(int16_t), &val, sizeof(int16_t)); numElementsRead++; } break; // TODO: other types not supported - only support int64, int32, int16, double, float case LogicalTypeID::DOUBLE: { double_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); memcpy(listVal.get() + numElementsRead * sizeof(double_t), &val, sizeof(double_t)); numElementsRead++; } break; case LogicalTypeID::FLOAT: { float_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); memcpy(listVal.get() + numElementsRead * sizeof(float_t), &val, sizeof(float_t)); numElementsRead++; } break; @@ -297,65 +298,67 @@ std::vector TableCopyUtils::parseStructFieldNameAndValue std::unique_ptr TableCopyUtils::convertStringToValue( std::string_view element, const LogicalType& type, const CSVReaderConfig& csvReaderConfig) { std::unique_ptr value; + ku_string_t input{element.data(), element.length()}; + switch (type.getLogicalTypeID()) { case LogicalTypeID::INT64: { int64_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::INT32: { int32_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::INT16: { int16_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::INT8: { int8_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::UINT64: { uint64_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::UINT32: { uint32_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::UINT16: { uint16_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::UINT8: { uint8_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::INT128: { int128_t val{}; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::FLOAT: { float_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::DOUBLE: { double_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::BOOL: { bool val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::STRING: { @@ -363,17 +366,17 @@ std::unique_ptr TableCopyUtils::convertStringToValue( } break; case LogicalTypeID::DATE: { date_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::TIMESTAMP: { timestamp_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::INTERVAL: { interval_t val; - function::CastStringToTypes::operation(element.data(), element.length(), val); + function::CastStringToTypes::operation(input, val); value = std::make_unique(val); } break; case LogicalTypeID::VAR_LIST: { diff --git a/test/test_files/tinysnb/function/cast.test b/test/test_files/tinysnb/function/cast.test index 8e8e495438f..cbe32c54d44 100644 --- a/test/test_files/tinysnb/function/cast.test +++ b/test/test_files/tinysnb/function/cast.test @@ -9,27 +9,42 @@ -STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=0 RETURN to_int16(e.level), to_int32(e.level), to_int64(e.level), to_int128(e.level), to_float(e.level), to_double(e.level) ---- 1 5|5|5|5|5.000000|5.000000 +-STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=0 RETURN CAST(e.level, INT16), CAST(e.level, INT32), CAST(e.level, INT64), CAST(e.level, INT128), CAST(e.level, FLOAT), CAST(e.level, DOUBLE) +---- 1 +5|5|5|5|5.000000|5.000000 -LOG CastFromINT16 -STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=0 RETURN to_int8(e.length), to_int32(e.length), to_int64(e.length), to_int128(e.length), to_float(e.length), to_double(e.length) ---- 1 5|5|5|5|5.000000|5.000000 +-STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=0 RETURN cast(e.length, int8), cast(e.length, int32), cast(e.length, int64), cast(e.length, int128), cast(e.length, float), cast(e.length, double) +---- 1 +5|5|5|5|5.000000|5.000000 -LOG CastFromINT32 -STATEMENT MATCH (m:movies) WHERE m.name='Roma' RETURN to_int16(m.length), to_int64(m.length), to_int128(m.length), to_float(m.length), to_double(m.length) ---- 1 298|298|298|298.000000|298.000000 +-STATEMENT MATCH (m:movies) WHERE m.name='Roma' RETURN cast(m.length, int16), cast(m.length, int64), cast(m.length, int128), cast(m.length, float), cast(m.length, double) +---- 1 +298|298|298|298.000000|298.000000 -LOG CastFromINT64 -STATEMENT MATCH (p:person) WHERE p.ID=0 RETURN to_int8(p.gender), to_int16(p.gender), to_int32(p.gender), to_int128(p.gender), to_float(p.gender), to_double(p.gender) ---- 1 1|1|1|1|1.000000|1.000000 +-STATEMENT MATCH (p:person) WHERE p.ID=0 RETURN cast(p.gender, int8), cast(p.gender, int16), cast(p.gender, int32), cast(p.gender, int64), cast(p.gender, int128), cast(p.gender, float), cast(p.gender, double) +---- 1 +1|1|1|1|1|1.000000|1.000000 -LOG CastFromUINT8 -STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=0 RETURN to_int16(e.ulevel), to_int32(e.ulevel), to_int64(e.ulevel), to_int128(e.ulevel), to_float(e.ulevel), to_double(e.ulevel) ---- 1 250|250|250|250|250.000000|250.000000 +-STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=0 RETURN cast(e.ulevel, int16), cast(e.ulevel, int32), cast(e.ulevel, int64), cast(e.ulevel, int128), cast(e.ulevel, float), cast(e.ulevel, double) +---- 1 +250|250|250|250|250.000000|250.000000 -LOG CastFromUINT16 -STATEMENT MATCH (p:person)-[e:studyAt]->(o:organisation) WHERE p.ID=2 RETURN to_int8(e.ulength), to_int32(e.ulength), to_int64(e.ulength), to_int128(e.ulength), to_float(e.ulength), to_double(e.ulength)