blob: 8252331981a37320a7df674efe6bbf631fffb2e0 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "core/column/column_struct.h"
#include "core/data_type/data_type_struct.h"
#include "core/types.h"
#include "exprs/function/cast/cast_base.h"
namespace doris::CastWrapper {
#include "common/compile_check_begin.h"
// check struct value type and get to_type value
// TODO: need handle another type to cast struct
WrapperType create_struct_wrapper(FunctionContext* context, const DataTypePtr& from_type,
const DataTypeStruct& to_type) {
// support CAST AS Struct from string
if (is_string_type(from_type->get_primitive_type())) {
if (context->enable_strict_mode()) {
return cast_from_string_to_complex_type_strict_mode;
} else {
return cast_from_string_to_complex_type;
}
}
// only support CAST AS Struct from struct or string types
const auto* from = check_and_get_data_type<DataTypeStruct>(from_type.get());
if (!from) {
return CastWrapper::create_unsupport_wrapper(
fmt::format("CAST AS Struct can only be performed between struct types or from "
"String. Left type: {}, right type: {}",
from_type->get_name(), to_type.get_name()));
}
const auto& from_element_types = from->get_elements();
const auto& to_element_types = to_type.get_elements();
// only support CAST AS Struct from struct type with same number of elements
if (from_element_types.size() != to_element_types.size()) {
return CastWrapper::create_unsupport_wrapper(
fmt::format("CAST AS Struct can only be performed between struct types with "
"the same number of elements. Left type: {}, right type: {}",
from_type->get_name(), to_type.get_name()));
}
auto element_wrappers = get_element_wrappers(context, from_element_types, to_element_types);
return [element_wrappers, from_element_types, to_element_types](
FunctionContext* context, Block& block, const ColumnNumbers& arguments,
uint32_t result, size_t /*input_rows_count*/,
const NullMap::value_type* null_map = nullptr) -> Status {
auto& from_column = block.get_by_position(arguments.front()).column;
const auto* from_col_struct = check_and_get_column<ColumnStruct>(from_column.get());
if (!from_col_struct) {
return Status::RuntimeError("Illegal column {} for function CAST AS Struct",
from_column->get_name());
}
size_t elements_num = to_element_types.size();
Columns converted_columns(elements_num);
for (size_t i = 0; i < elements_num; ++i) {
ColumnWithTypeAndName from_element_column {from_col_struct->get_column_ptr(i),
from_element_types[i], ""};
ColumnNumbers element_arguments {block.columns()};
block.insert(from_element_column);
auto element_result = block.columns();
block.insert({to_element_types[i], ""});
RETURN_IF_ERROR(element_wrappers[i](context, block, element_arguments, element_result,
from_col_struct->get_column(i).size(), null_map));
converted_columns[i] = block.get_by_position(element_result).column;
}
block.get_by_position(result).column = ColumnStruct::create(converted_columns);
return Status::OK();
};
}
#include "common/compile_check_end.h"
} // namespace doris::CastWrapper