//===----------------------------------------------------------------------===// // DuckDB // // duckdb/function/cast/vector_cast_helpers.hpp // // //===----------------------------------------------------------------------===// #pragma once #include "duckdb/function/cast/default_casts.hpp" #include "duckdb/common/vector_operations/unary_executor.hpp" #include "duckdb/common/vector_operations/general_cast.hpp" #include "duckdb/common/operator/decimal_cast_operators.hpp" #include "duckdb/common/likely.hpp" #include "duckdb/common/string_map_set.hpp" namespace duckdb { template struct VectorStringCastOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto result = (Vector *)dataptr; return OP::template Operation(input, *result); } }; struct VectorTryCastData { VectorTryCastData(Vector &result_p, string *error_message_p, bool strict_p) : result(result_p), error_message(error_message_p), strict(strict_p) { } Vector &result; string *error_message; bool strict; bool all_converted = true; }; template struct VectorTryCastOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { RESULT_TYPE output; if (DUCKDB_LIKELY(OP::template Operation(input, output))) { return output; } auto data = (VectorTryCastData *)dataptr; return HandleVectorCastError::Operation(CastExceptionText(input), mask, idx, data->error_message, data->all_converted); } }; template struct VectorTryCastStrictOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto data = (VectorTryCastData *)dataptr; RESULT_TYPE output; if (DUCKDB_LIKELY(OP::template Operation(input, output, data->strict))) { return output; } return HandleVectorCastError::Operation(CastExceptionText(input), mask, idx, data->error_message, data->all_converted); } }; template struct VectorTryCastErrorOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto data = (VectorTryCastData *)dataptr; RESULT_TYPE output; if (DUCKDB_LIKELY( OP::template Operation(input, output, data->error_message, data->strict))) { return output; } bool has_error = data->error_message && !data->error_message->empty(); return HandleVectorCastError::Operation( has_error ? *data->error_message : CastExceptionText(input), mask, idx, data->error_message, data->all_converted); } }; template struct VectorTryCastStringOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto data = (VectorTryCastData *)dataptr; RESULT_TYPE output; if (DUCKDB_LIKELY(OP::template Operation(input, output, data->result, data->error_message, data->strict))) { return output; } return HandleVectorCastError::Operation(CastExceptionText(input), mask, idx, data->error_message, data->all_converted); } }; struct VectorDecimalCastData { VectorDecimalCastData(string *error_message_p, uint8_t width_p, uint8_t scale_p) : error_message(error_message_p), width(width_p), scale(scale_p) { } string *error_message; uint8_t width; uint8_t scale; bool all_converted = true; }; template struct VectorDecimalCastOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto data = (VectorDecimalCastData *)dataptr; RESULT_TYPE result_value; if (!OP::template Operation(input, result_value, data->error_message, data->width, data->scale)) { return HandleVectorCastError::Operation("Failed to cast decimal value", mask, idx, data->error_message, data->all_converted); } return result_value; } }; struct VectorCastHelpers { template static bool TemplatedCastLoop(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { UnaryExecutor::Execute(source, result, count); return true; } template static bool TemplatedTryCastLoop(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { VectorTryCastData input(result, parameters.error_message, parameters.strict); UnaryExecutor::GenericExecute(source, result, count, &input, parameters.error_message); return input.all_converted; } template static bool TryCastLoop(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { return TemplatedTryCastLoop>(source, result, count, parameters); } template static bool TryCastStrictLoop(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { return TemplatedTryCastLoop>(source, result, count, parameters); } template static bool TryCastErrorLoop(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { return TemplatedTryCastLoop>(source, result, count, parameters); } template static bool TryCastStringLoop(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { return TemplatedTryCastLoop>(source, result, count, parameters); } template static bool StringCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { D_ASSERT(result.GetType().InternalType() == PhysicalType::VARCHAR); UnaryExecutor::GenericExecute>(source, result, count, (void *)&result); return true; } template static bool TemplatedDecimalCast(Vector &source, Vector &result, idx_t count, string *error_message, uint8_t width, uint8_t scale) { VectorDecimalCastData input(error_message, width, scale); UnaryExecutor::GenericExecute>(source, result, count, (void *)&input, error_message); return input.all_converted; } template static bool ToDecimalCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { auto &result_type = result.GetType(); auto width = DecimalType::GetWidth(result_type); auto scale = DecimalType::GetScale(result_type); switch (result_type.InternalType()) { case PhysicalType::INT16: return TemplatedDecimalCast(source, result, count, parameters.error_message, width, scale); case PhysicalType::INT32: return TemplatedDecimalCast(source, result, count, parameters.error_message, width, scale); case PhysicalType::INT64: return TemplatedDecimalCast(source, result, count, parameters.error_message, width, scale); case PhysicalType::INT128: return TemplatedDecimalCast(source, result, count, parameters.error_message, width, scale); default: throw InternalException("Unimplemented internal type for decimal"); } } }; struct VectorStringToList { static idx_t CountPartsList(const string_t &input); static bool SplitStringList(const string_t &input, string_t *child_data, idx_t &child_start, Vector &child); static bool StringToNestedTypeCastLoop(const string_t *source_data, ValidityMask &source_mask, Vector &result, ValidityMask &result_mask, idx_t count, CastParameters ¶meters, const SelectionVector *sel); }; struct VectorStringToStruct { static bool SplitStruct(const string_t &input, vector> &varchar_vectors, idx_t &row_idx, string_map_t &child_names, vector &child_masks); static bool StringToNestedTypeCastLoop(const string_t *source_data, ValidityMask &source_mask, Vector &result, ValidityMask &result_mask, idx_t count, CastParameters ¶meters, const SelectionVector *sel); }; struct VectorStringToMap { static idx_t CountPartsMap(const string_t &input); static bool SplitStringMap(const string_t &input, string_t *child_key_data, string_t *child_val_data, idx_t &child_start, Vector &varchar_key, Vector &varchar_val); static bool StringToNestedTypeCastLoop(const string_t *source_data, ValidityMask &source_mask, Vector &result, ValidityMask &result_mask, idx_t count, CastParameters ¶meters, const SelectionVector *sel); }; } // namespace duckdb