blob: adb1a2f771b82d2c988ab632bab4d88655b74a09 [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 <gtest/gtest.h>
#include <cstdint>
#include <memory>
#include <utility>
#include <variant>
#include <vector>
#include "cast_test.h"
#include "runtime/primitive_type.h"
#include "testutil/column_helper.h"
#include "vec/columns/column.h"
#include "vec/columns/column_map.h"
#include "vec/core/field.h"
#include "vec/data_types/data_type_map.h"
#include "vec/data_types/data_type_nullable.h"
#include "vec/data_types/data_type_number.h"
#include "vec/data_types/data_type_string.h"
#include "vec/functions/cast/cast_base.h"
namespace doris::vectorized {
using namespace ut_type;
template <typename KeyDataType, typename ValueDataType>
struct ColumnMapBuilder {
using Ty = std::pair<std::variant<NullTag, typename KeyDataType::FieldType>,
std::variant<NullTag, typename ValueDataType::FieldType>>;
void add(const std::vector<Ty>& values) {
for (const auto& kv : values) {
auto key = kv.first;
auto value = kv.second;
if (std::holds_alternative<typename KeyDataType::FieldType>(key)) {
key_data.push_back(std::get<typename KeyDataType::FieldType>(key));
key_null_map.push_back(0);
} else {
key_data.push_back(typename KeyDataType::FieldType {});
key_null_map.push_back(1);
}
if (std::holds_alternative<typename ValueDataType::FieldType>(value)) {
value_data.push_back(std::get<typename ValueDataType::FieldType>(value));
value_null_map.push_back(0);
} else {
value_data.push_back(typename ValueDataType::FieldType {});
value_null_map.push_back(1);
}
size++;
}
offsets.push_back(size);
null_map.push_back(0);
}
void add_null() {
null_map.push_back(1);
offsets.push_back(size);
}
ColumnWithTypeAndName build() {
auto key_column = ColumnHelper::create_nullable_column<KeyDataType>(key_data, key_null_map);
auto value_column =
ColumnHelper::create_nullable_column<ValueDataType>(value_data, value_null_map);
auto offsets_column = ColumnHelper::create_column_offsets<TYPE_UINT64>(offsets);
auto col_map = ColumnMap::create(std::move(key_column), std::move(value_column),
std::move(offsets_column));
auto col_null_map = ColumnHelper::create_column<DataTypeUInt8>(null_map);
auto col_nullable = ColumnNullable::create(std::move(col_map), col_null_map);
auto data_type = std::make_shared<DataTypeNullable>(std::make_shared<DataTypeMap>(
std::make_shared<DataTypeNullable>(std::make_shared<KeyDataType>()),
std::make_shared<DataTypeNullable>(std::make_shared<ValueDataType>())));
return ColumnWithTypeAndName(std::move(col_nullable), data_type, "column");
}
std::vector<typename KeyDataType::FieldType> key_data;
std::vector<typename ValueDataType::FieldType> value_data;
std::vector<uint8_t> key_null_map;
std::vector<uint8_t> value_null_map;
std::vector<uint8_t> null_map;
std::vector<uint64_t> offsets;
int size = 0;
};
TEST_F(FunctionCastTest, test_from_string_to_map_int_string) {
ColumnMapBuilder<DataTypeInt32, DataTypeString> builder;
std::vector<std::string> from_str;
from_str.push_back(R"({123:456})");
builder.add({{123, "456"}});
from_str.push_back(R"({789:101112})");
builder.add({{789, "101112"}});
from_str.push_back(R"({1:2, 3:4})");
builder.add({{1, "2"}, {3, "4"}});
from_str.push_back(R"({abc:101112})");
builder.add({{NullTag {}, "101112"}});
from_str.push_back(R"( {} )");
builder.add_null();
from_str.push_back(R"({})");
builder.add({});
check_cast(ColumnWithTypeAndName(ColumnHelper::create_column<DataTypeString>(from_str),
std::make_shared<DataTypeString>(), "from"),
builder.build(), false);
}
TEST_F(FunctionCastTest, test_from_string_to_map_int_bool) {
ColumnMapBuilder<DataTypeInt32, DataTypeBool> builder;
std::vector<std::string> from_str;
from_str.push_back(R"({123:true})");
builder.add({{123, true}});
from_str.push_back(R"({789:false})");
builder.add({{789, false}});
from_str.push_back(R"({1:true, 3:false})");
builder.add({{1, true}, {3, false}});
from_str.push_back(R"({abc:true})");
builder.add({{NullTag {}, true}});
from_str.push_back(R"( {} )");
builder.add_null();
from_str.push_back(R"({})");
builder.add({});
check_cast(ColumnWithTypeAndName(ColumnHelper::create_column<DataTypeString>(from_str),
std::make_shared<DataTypeString>(), "from"),
builder.build(), false);
}
TEST_F(FunctionCastTest, test_from_string_to_map_string_string) {
ColumnMapBuilder<DataTypeString, DataTypeString> builder;
std::vector<std::string> from_str;
from_str.push_back(R"({"abc":"def"})");
builder.add({{"abc", "def"}});
from_str.push_back(R"({"ghi":"jkl"})");
builder.add({{"ghi", "jkl"}});
from_str.push_back(R"({"mno":"pqr", "stu":"vwx"})");
builder.add({{"mno", "pqr"}, {"stu", "vwx"}});
from_str.push_back(R"({"xyz":"123"})");
builder.add({{"xyz", "123"}});
from_str.push_back(R"( {} )");
builder.add_null();
from_str.push_back(R"({})");
builder.add({});
check_cast(ColumnWithTypeAndName(ColumnHelper::create_column<DataTypeString>(from_str),
std::make_shared<DataTypeString>(), "from"),
builder.build(), false);
}
} // namespace doris::vectorized