blob: 0bb88b2349ea137cf8ee862abecbab0e98e00d6a [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 <cstdlib>
#include <fstream>
#include <limits>
#include <string>
#include <type_traits>
#include <utility>
#include "cast_test.h"
#include "runtime/define_primitive_type.h"
#include "vec/core/types.h"
#include "vec/data_types/data_type_date_or_datetime_v2.h"
#include "vec/data_types/data_type_decimal.h"
#include "vec/data_types/data_type_number.h"
#include "vec/data_types/number_traits.h"
#include "vec/runtime/time_value.h"
#include "vec/runtime/vdatetime_value.h"
namespace doris::vectorized {
using namespace ut_type;
struct FunctionCastToIntTest : public FunctionCastTest {
const std::vector<std::string> white_spaces = {" ", "\t", "\r", "\n", "\f", "\v"};
std::string white_spaces_str = " \t\r\n\f\v";
template <PrimitiveType PType>
void from_string_test_func() {
using T = typename PrimitiveTypeTraits<PType>::CppType;
InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
using UnsignedT = typename std::make_unsigned<T>::type;
DataTypeNumber<PType> dt;
auto max_val = std::numeric_limits<T>::max();
auto min_val = std::numeric_limits<T>::min();
auto max_val_minus_1 = max_val - T {1};
auto min_val_plus_1 = min_val + T {1};
auto min_val_abs_val = UnsignedT(max_val) + 1;
std::string min_val_str_no_sign = fmt::format("{}", min_val_abs_val);
std::vector<T> test_vals = {T {0}, T {1}, T {9}, T {123}, max_val,
T {-1}, T {-9}, T {-123}, min_val};
test_vals.push_back(max_val_minus_1);
test_vals.push_back(min_val_plus_1);
std::vector<std::pair<std::string, T>> data_pairs;
// test leading zeros, sign, leading and trailing white spaces for positive values
auto tmp_test_func = [&](bool with_spaces, bool with_sign, bool leading_zeros) {
DataSet data_set;
for (auto v : test_vals) {
bool is_negative = (v < 0);
std::string v_str;
// first get string format of number without sign
if (is_negative) {
if (v == min_val) {
v_str = min_val_str_no_sign;
} else {
v_str = dt.to_string(-v);
}
} else {
v_str = dt.to_string(v);
}
if (leading_zeros) {
v_str = "000" + v_str;
}
if (is_negative) {
v_str = "-" + v_str;
} else {
// optional '+'
if (with_sign) {
v_str = "+" + v_str;
}
}
if (with_spaces) {
/*
for (const auto& sp : white_spaces) {
// Single whitespace combinations
data_set.push_back({{sp + v_str}, v});
data_set.push_back({{v_str + sp}, v});
data_set.push_back({{sp + v_str + sp}, v});
// Multiple whitespace combinations
data_set.push_back({{sp + sp + sp + v_str}, v});
data_set.push_back({{v_str + sp + sp + sp}, v});
data_set.push_back({{sp + sp + sp + v_str + sp + sp + sp}, v});
}
*/
data_set.push_back({{white_spaces_str + v_str}, v});
data_set.push_back({{v_str + white_spaces_str}, v});
data_set.push_back({{white_spaces_str + v_str + white_spaces_str}, v});
} else {
data_set.push_back({{v_str}, v});
data_pairs.emplace_back(v_str, v);
}
}
/*
std::string dbg_str;
if (!with_spaces) {
for (const auto& p : data_set) {
dbg_str += "|" + any_cast<ut_type::STRING>(p.first[0]) + "|, ";
}
std::cout << "test cast from string to int, data set: " << dbg_str << std::endl;
}
*/
check_function_for_cast<DataTypeNumber<PType>, true>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<PType>, false>(input_types, data_set, -1, -1);
};
// test leading and trailing white spaces, sign and leading zeros
tmp_test_func(true, true, true);
// test leading and trailing spaces and sign
tmp_test_func(true, true, false);
// test leading and trailing spaces and leading zeros
tmp_test_func(true, false, true);
// test leading and trailing spaces
tmp_test_func(true, false, false);
// test with sign and leading zeros
tmp_test_func(false, true, true);
// test with sign
tmp_test_func(false, true, false);
// test only leading zeros
tmp_test_func(false, false, true);
// test strict digits
tmp_test_func(false, false, false);
/*
DataSet data_set = {
// Invalid cases - these should throw exceptions or return error status
{{std::string("")}, Exception("Empty string")},
{{std::string(" ")}, Exception("Only whitespace")},
{{std::string("+")}, Exception("Only sign")},
{{std::string("-")}, Exception("Only sign")},
{{std::string("a123")}, Exception("Leading letter")},
{{std::string("123a")}, Exception("Trailing letter")},
{{std::string("12.34")}, Exception("Decimal point")},
{{std::string("1,234")}, Exception("Comma")},
{{std::string("1_234")}, Exception("Underscore")},
{{std::string("0x123")}, Exception("Hex prefix")},
{{std::string("123e4")}, Exception("Scientific notation")},
{{std::string("++123")}, Exception("Double plus")},
{{std::string("--123")}, Exception("Double minus")},
{{std::string("+-123")}, Exception("Plus minus")},
{{std::string("-+123")}, Exception("Minus plus")},
{{std::string("123 456")}, Exception("Space between digits")},
// Overflow cases
{{std::string("128")}, Exception("Overflow")}, // > MAX_INT8
{{std::string("-129")}, Exception("Underflow")}, // < MIN_INT8
{{std::string("999999")}, Exception("Overflow")}, // Large number
{{std::string("-999999")}, Exception("Underflow")}, // Large negative
};
*/
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = "string";
std::string to_sql_type_name = get_sql_type_name(PType);
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_{}", to_sql_type_name, from_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_str");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_normal_regression_case(regression_case_name, from_sql_type_name, false,
to_sql_type_name, data_pairs, table_index++, test_data_index,
ofs_case, ofs_expected_result, ofs_const_case,
ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType PT>
void from_string_with_fraction_part_test_func() {
InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
using T = typename PrimitiveTypeTraits<PT>::CppType;
using UnsignedT = typename std::make_unsigned<T>::type;
DataTypeNumber<PT> dt;
auto max_val = std::numeric_limits<T>::max();
auto min_val = std::numeric_limits<T>::min();
auto max_val_minus_1 = max_val - T {1};
auto min_val_plus_1 = min_val + T {1};
auto min_val_abs_val = UnsignedT(max_val) + 1;
std::string min_val_str_no_sign = fmt::format("{}", min_val_abs_val);
std::vector<T> test_vals = {T {0}, T {1}, T {9}, T {123}, max_val,
T {-1}, T {-9}, T {-123}, min_val};
test_vals.push_back(max_val_minus_1);
test_vals.push_back(min_val_plus_1);
std::vector<std::pair<std::string, T>> data_pairs;
std::string table_test_expected_results;
int data_index = 0;
auto test_func_with_strict_cast = [&](auto enable_strict_cast) {
// std::cout << fmt::format("test cast from string to {}, enable_strict_cast: {}\n",
// type_to_string(PT), enable_strict_cast);
// test leading zeros, sign, leading and trailing white spaces
auto tmp_test_func = [&](bool with_spaces, bool with_sign, bool leading_zeros) {
DataSet data_set;
for (auto v : test_vals) {
bool is_negative = (v < 0);
std::string v_str;
// first get string format of number without sign
if (is_negative) {
if (v == min_val) {
v_str = min_val_str_no_sign;
} else {
v_str = dt.to_string(-v);
}
} else {
v_str = dt.to_string(v);
}
if (leading_zeros) {
v_str = "000" + v_str;
}
if (is_negative) {
v_str = "-" + v_str;
} else {
// optional '+'
if (with_sign) {
v_str = "+" + v_str;
}
}
if (enable_strict_cast) {
std::vector<std::string> test_strs;
if (with_spaces) {
test_strs.push_back(white_spaces_str + v_str + ".4");
test_strs.push_back(white_spaces_str + v_str + ".5");
test_strs.push_back(v_str + ".4" + white_spaces_str);
test_strs.push_back(v_str + ".5" + white_spaces_str);
test_strs.push_back(white_spaces_str + v_str + ".4" + white_spaces_str);
test_strs.push_back(white_spaces_str + v_str + ".5" + white_spaces_str);
} else {
test_strs.push_back(v_str + ".4");
test_strs.push_back(v_str + ".5");
}
for (const auto& v_str : test_strs) {
DataSet tmp_data_set;
tmp_data_set.push_back({{v_str}, Null()});
check_function_for_cast<DataTypeNumber<PT>, true>(
input_types, tmp_data_set, -1, -1, true, true);
}
} else {
if (with_spaces) {
data_set.push_back({{white_spaces_str + v_str + ".4"}, v});
data_set.push_back({{white_spaces_str + v_str + ".5"}, v});
data_set.push_back({{v_str + ".4" + white_spaces_str}, v});
data_set.push_back({{v_str + ".5" + white_spaces_str}, v});
data_set.push_back(
{{white_spaces_str + v_str + ".4" + white_spaces_str}, v});
data_set.push_back(
{{white_spaces_str + v_str + ".5" + white_spaces_str}, v});
} else {
data_set.push_back({{v_str + ".4"}, v});
data_set.push_back({{v_str + ".5"}, v});
data_pairs.emplace_back(v_str + ".4", v);
table_test_expected_results += fmt::format("{}\t{}\n", data_index++, v);
data_pairs.emplace_back(v_str + ".5", v);
table_test_expected_results += fmt::format("{}\t{}\n", data_index++, v);
}
}
}
if (!enable_strict_cast) {
/*
std::string dbg_str;
for (const auto& p : data_set) {
dbg_str += "|" + any_cast<ut_type::STRING>(p.first[0]) + "|, ";
}
std::cout << fmt::format(
"test cast from string to {}, enable_strict_cast: {}, data set: {}\n",
type_to_string(PT), enable_strict_cast, dbg_str);
*/
check_function_for_cast<DataTypeNumber<PT>, false>(input_types, data_set, -1,
-1);
}
};
// test leading and trailing white spaces, sign and leading zeros
tmp_test_func(true, true, true);
// test leading and trailing spaces and sign
tmp_test_func(true, true, false);
// test leading and trailing spaces and leading zeros
tmp_test_func(true, false, true);
// test leading and trailing spaces
tmp_test_func(true, false, false);
// test with sign and leading zeros
tmp_test_func(false, true, true);
// test with sign
tmp_test_func(false, true, false);
// test only leading zeros
tmp_test_func(false, false, true);
// test strict digits
tmp_test_func(false, false, false);
};
test_func_with_strict_cast(true);
test_func_with_strict_cast(false);
if (FLAGS_gen_regression_case) {
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string cast_type_name = get_sql_type_name(PT);
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_str_with_fraction", cast_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_str");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
(*ofs_const_case) << " sql \"set debug_skip_fold_constant = true;\"\n";
auto table_name = fmt::format("{}_{}", regression_case_name, table_index);
auto value_count = data_pairs.size();
auto groovy_var_name = fmt::format("{}_{}_strs", regression_case_name, table_index);
(*ofs_const_case) << fmt::format(" def {} = [", groovy_var_name);
int i = 0;
for (const auto& data : data_pairs) {
(*ofs_const_case) << fmt::format(R"("""{}""")", data.first);
++i;
if (i != value_count) {
(*ofs_const_case) << ",";
}
if (i % 20 == 0 && i != value_count) {
(*ofs_const_case) << "\n ";
}
}
(*ofs_const_case) << fmt::format("]\n");
auto const_test_with_strict_arg = [&](bool enable_strict_cast) {
(*ofs_const_case) << fmt::format("\n sql \"set enable_strict_cast={};\"\n",
enable_strict_cast);
if (enable_strict_cast) {
(*ofs_const_case) << fmt::format(R"(
for (b in ["false", "true"]) {{
sql """set debug_skip_fold_constant = "${{b}}";"""
for (test_str in {}) {{
test {{
sql """select cast("${{test_str}}" as {});"""
exception "{}"
}}
}}
}}
)",
groovy_var_name, cast_type_name, "");
} else {
(*ofs_const_case) << fmt::format(R"(
for (test_str in {}) {{
qt_sql_{} """select cast("${{test_str}}" as {});"""
testFoldConst("""select cast("${{test_str}}" as {});""")
}}
)",
groovy_var_name, table_name, cast_type_name,
cast_type_name);
for (int i = 0; i != value_count; ++i) {
(*ofs_const_expected_result) << fmt::format("-- !sql_{} --\n", table_name);
(*ofs_const_expected_result) << fmt::format("{}\n\n", data_pairs[i].second);
}
}
};
const_test_with_strict_arg(true);
const_test_with_strict_arg(false);
(*ofs_case) << fmt::format(" sql \"drop table if exists {};\"\n", table_name);
(*ofs_case) << fmt::format(
" sql \"create table {}(f1 int, f2 string) "
"properties('replication_num'='1');\"\n",
table_name);
(*ofs_case) << fmt::format(" sql \"\"\"insert into {} values ", table_name);
for (int i = 0; i != value_count;) {
(*ofs_case) << fmt::format("({}, \"{}\")", i, data_pairs[i].first);
++i;
if (i != value_count) {
(*ofs_case) << ",";
}
if (i % 20 == 0 && i != value_count) {
(*ofs_case) << "\n ";
}
}
(*ofs_case) << ";\n \"\"\"\n\n";
auto table_test_with_strict_arg = [&](bool enable_strict_cast) {
(*ofs_case) << fmt::format(" sql \"set enable_strict_cast={};\"\n",
enable_strict_cast);
if (enable_strict_cast) {
(*ofs_case) << fmt::format(R"(
def {}_data_start_index = {}
def {}_data_end_index = {}
for (int data_index = {}_data_start_index; data_index < {}_data_end_index; data_index++) {{
test {{
sql "select f1, cast(f2 as {}) from {} where f1 = ${{data_index}}"
exception "{}"
}}
}}
)",
regression_case_name, 0, regression_case_name,
value_count, regression_case_name,
regression_case_name, cast_type_name,
regression_case_name, "");
} else {
(*ofs_case) << fmt::format(
" qt_sql_{}_{} 'select f1, cast(f2 as {}) from {} "
"order by "
"1;'\n\n",
table_index, "non_strict", cast_type_name, table_name);
(*ofs_expected_result)
<< fmt::format("-- !sql_{}_{} --\n", table_index, "non_strict");
(*ofs_expected_result) << table_test_expected_results;
(*ofs_expected_result) << "\n";
}
};
table_test_with_strict_arg(true);
table_test_with_strict_arg(false);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType PT>
void from_string_overflow_test_func() {
InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
using T = typename PrimitiveTypeTraits<PT>::CppType;
using UnsignedT = typename std::make_unsigned<T>::type;
DataTypeNumber<PT> dt;
UnsignedT max_val = std::numeric_limits<T>::max();
std::vector<std::string> test_vals;
std::string dbg_str0 =
fmt::format("test cast from string to {} overflow", type_to_string(PT));
for (UnsignedT i = 1; i != 11; ++i) {
auto val_str = fmt::format("{}", max_val + i);
test_vals.push_back(val_str);
val_str = fmt::format("{}", max_val + i + 1);
val_str.insert(0, "-");
test_vals.push_back(val_str);
}
int count = 0;
for (auto i = std::numeric_limits<UnsignedT>::max(); count < 10; --i, ++count) {
auto val_str = fmt::format("{}", i);
test_vals.push_back(val_str);
val_str.insert(0, "-");
test_vals.push_back(val_str);
}
if constexpr (std::is_same_v<T, Int8>) {
test_vals.push_back(std::to_string(std::numeric_limits<Int16>::max()));
test_vals.push_back(std::to_string(std::numeric_limits<Int16>::min()));
test_vals.push_back(std::to_string(std::numeric_limits<Int32>::max()));
test_vals.push_back(std::to_string(std::numeric_limits<Int32>::min()));
test_vals.push_back(std::to_string(std::numeric_limits<Int64>::max()));
test_vals.push_back(std::to_string(std::numeric_limits<Int64>::min()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::max()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::min()));
} else if constexpr (std::is_same_v<T, Int16>) {
test_vals.push_back(std::to_string(std::numeric_limits<Int32>::max()));
test_vals.push_back(std::to_string(std::numeric_limits<Int32>::min()));
test_vals.push_back(std::to_string(std::numeric_limits<Int64>::max()));
test_vals.push_back(std::to_string(std::numeric_limits<Int64>::min()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::max()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::min()));
} else if constexpr (std::is_same_v<T, Int32>) {
test_vals.push_back(std::to_string(std::numeric_limits<Int64>::max()));
test_vals.push_back(std::to_string(std::numeric_limits<Int64>::min()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::max()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::min()));
} else if constexpr (std::is_same_v<T, Int64>) {
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::max()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<Int128>::min()));
}
test_vals.push_back(fmt::format("{}", std::numeric_limits<wide::Int256>::max()));
test_vals.push_back(fmt::format("{}", std::numeric_limits<wide::Int256>::min()));
auto test_func_with_strict_cast = [&](auto enable_strict_cast) {
// std::cout << fmt::format("{}, enable_strict_cast: {}", dbg_str0, enable_strict_cast);
// test leading zeros, sign, leading and trailing white spaces for positive values
auto tmp_test_func = [&](bool with_spaces, bool with_sign, bool leading_zeros) {
DataSet data_set;
for (auto v_str : test_vals) {
bool is_negative = (v_str[0] == '-');
if (is_negative) {
v_str = v_str.substr(1);
}
if (leading_zeros) {
v_str = "000" + v_str;
}
if (is_negative) {
v_str = "-" + v_str;
} else {
// optional '+'
if (with_sign) {
v_str = "+" + v_str;
}
}
if (with_spaces) {
if (enable_strict_cast) {
DataSet tmp_data_set;
tmp_data_set.push_back(
{{white_spaces_str + v_str + white_spaces_str}, Null()});
check_function_for_cast<DataTypeNumber<PT>, true>(
input_types, tmp_data_set, -1, -1, true, true);
} else {
data_set.push_back(
{{white_spaces_str + v_str + white_spaces_str}, Null()});
}
} else {
if (enable_strict_cast) {
DataSet tmp_data_set;
tmp_data_set.push_back({{v_str}, Null()});
check_function_for_cast<DataTypeNumber<PT>, true>(
input_types, tmp_data_set, -1, -1, true, true);
} else {
data_set.push_back({{v_str}, Null()});
}
}
}
if (!enable_strict_cast) {
/*
std::string dbg_str = dbg_str0 + ", data set: ";
for (const auto& p : data_set) {
dbg_str += any_cast<ut_type::STRING>(p.first[0]) + ", ";
}
std::cout << dbg_str << std::endl;
*/
check_function_for_cast<DataTypeNumber<PT>, false>(input_types, data_set, -1,
-1);
}
};
// test leading and trailing white spaces, sign and leading zeros
tmp_test_func(true, true, true);
// test leading and trailing spaces and sign
tmp_test_func(true, true, false);
// test leading and trailing spaces and leading zeros
tmp_test_func(true, false, true);
// test leading and trailing spaces
tmp_test_func(true, false, false);
// test with sign and leading zeros
tmp_test_func(false, true, true);
// test with sign
tmp_test_func(false, true, false);
// test only leading zeros
tmp_test_func(false, false, true);
// test strict digits
tmp_test_func(false, false, false);
};
test_func_with_strict_cast(true);
test_func_with_strict_cast(false);
if (FLAGS_gen_regression_case) {
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = "string";
std::string to_sql_type_name = get_sql_type_name(PT);
std::string regression_case_name = fmt::format("test_cast_to_{}_from_{}_overflow",
to_sql_type_name, from_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_str");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_overflow_and_invalid_regression_case(regression_case_name, from_sql_type_name,
false, to_sql_type_name, test_vals,
table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType PT>
void from_string_invalid_test_func() {
InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
std::vector<std::string> test_vals;
std::string dbg_str0 =
fmt::format("test cast from string to {} abnormal cases", type_to_string(PT));
std::vector<std::string> abnormal_inputs = {
"",
".",
" ",
"\t",
"\n",
"\r",
"\f",
"\v",
"abc",
"abc123"
"1abc12"
"123abc",
// Space between digits
"1 23",
"1\t23",
"1\n23",
"1\r23",
"1\v23",
"1\f23",
// invalid leading and trailing characters
"a123.456",
" a123.456",
"\ta123.456",
"\na123.456",
"\ra123.456",
"\fa123.456",
"\va123.456",
"123.456a",
"123.456a\t",
"123.456a\n",
"123.456a\r",
"123.456a\f",
"123.456a\v",
"123.456\ta",
"123.456\na",
"123.456\ra",
"123.456\fa",
"123.456\va",
// invalid char between numbers
"12a3.456",
"123a.456",
"123.a456",
"123.4a56",
// multiple positive/negative signs
"++123"
"--123"
"+-123"
"-+123"
"+-123.456",
"+- 123.456", // sign with following spaces
"-+123.456",
"++123.456",
"--123.456",
"+-.456",
"-+.456",
"++.456",
"--.456",
// hexadecimal
"0x123",
"0x123.456",
// does not support scientific notation
"1.234e3",
// invalid scientific notation
"e",
"-e",
"+e",
"e+",
"e-",
"e1",
"e+1",
"e-1",
".e",
"+.e",
"-.e",
".e+",
".e-",
".e+",
"1e",
"1e+",
"1e-",
"1e1a",
"1ea1",
"1e1.1",
"1e+1.1",
"1e-1.1",
};
// non-strict mode
{
DataSet data_set;
for (const auto& input : abnormal_inputs) {
data_set.push_back({{input}, Null()});
}
check_function_for_cast<DataTypeNumber<PT>, false>(input_types, data_set, -1, -1);
}
// strict mode
for (const auto& input : abnormal_inputs) {
DataSet data_set;
data_set.push_back({{input}, Null()});
check_function_for_cast<DataTypeNumber<PT>, true>(input_types, data_set, -1, -1, true,
true);
}
if (FLAGS_gen_regression_case) {
std::vector<std::string> regression_invalid_inputs = {
"",
".",
" ",
"\t",
"abc",
"abc123"
"1abc12"
"123abc",
// Space between digits
"1 23",
"1\t23",
// Multiple decimal points
"1.2.3",
// invalid leading and trailing characters
"a123.456",
" a123.456",
"\ta123.456",
"123.456a",
"123.456a\t",
"123.456\ta",
"123.456\na",
// invalid char between numbers
"12a3.456",
"123a.456",
"123.a456",
"123.4a56",
// multiple positive/negative signs
"++123"
"--123"
"+-123"
"-+123"
"+-123.456",
"+- 123.456", // sign with following spaces
"-+123.456",
"++123.456",
"--123.456",
"+-.456",
"-+.456",
"++.456",
"--.456",
// hexadecimal
"0x123",
"0x123.456",
// invalid scientific notation
"e",
"-e",
"+e",
"e+",
"e-",
"e1",
"e+1",
"e-1",
".e",
"+.e",
"-.e",
".e+",
".e-",
".e+",
"1e",
"1e+",
"1e-",
"1e1a",
"1ea1",
"1e1.1",
"1e+1.1",
"1e-1.1",
// Multiple exponents
"1e2e3",
};
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = "string";
std::string to_sql_type_name = get_sql_type_name(PT);
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_str_invalid", to_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_str");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_overflow_and_invalid_regression_case(
regression_case_name, from_sql_type_name, false, to_sql_type_name,
regression_invalid_inputs, table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType FromPT, PrimitiveType ToPT>
void narrow_to_wider_int_test_func() {
using FromT = typename PrimitiveTypeTraits<FromPT>::CppType;
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(sizeof(FromT) <= sizeof(ToT), "FromT must be smaller than ToT");
DataTypeNumber<FromPT> dt;
InputTypeSet input_types = {dt.get_primitive_type()};
auto max_val = std::numeric_limits<FromT>::max();
auto min_val = std::numeric_limits<FromT>::min();
FromT max_val_minus_1 = max_val - FromT {1};
FromT min_val_plus_1 = min_val + FromT {1};
std::vector<std::pair<FromT, ToT>> test_vals = {
{FromT {0}, ToT(0)}, {FromT {1}, ToT {1}}, {FromT {9}, ToT {9}},
{FromT {123}, ToT {123}}, {max_val, ToT {max_val}}, {FromT {-1}, ToT {-1}},
{FromT {-9}, ToT {-9}}, {FromT {-123}, ToT {-123}}, {min_val, ToT {min_val}}};
test_vals.push_back({max_val_minus_1, ToT {max_val_minus_1}});
test_vals.push_back({min_val_plus_1, ToT {min_val_plus_1}});
DataSet data_set;
for (const auto& p : test_vals) {
data_set.push_back({{p.first}, p.second});
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1);
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_type_name = get_sql_type_name(FromPT);
std::string to_type_name = get_sql_type_name(ToPT);
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_{}", to_type_name, from_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_int");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_normal_regression_case(regression_case_name, from_type_name, true, to_type_name,
test_vals, table_index++, test_data_index, ofs_case,
ofs_expected_result, ofs_const_case,
ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType FromPT, PrimitiveType ToPT>
void wider_to_narrow_int_test_func() {
using FromT = typename PrimitiveTypeTraits<FromPT>::CppType;
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(sizeof(FromT) > sizeof(ToT), "FromT must be larger than ToT");
DataTypeNumber<FromPT> dt;
InputTypeSet input_types = {dt.get_primitive_type()};
// using UnsignedT = typename std::make_unsigned<FromT>::type;
// auto from_max_val = std::numeric_limits<FromT>::max();
// auto from_min_val = std::numeric_limits<FromT>::min();
auto to_max_val = std::numeric_limits<ToT>::max();
auto to_min_val = std::numeric_limits<ToT>::min();
std::vector<std::pair<FromT, ToT>> test_vals = {{FromT {0}, ToT(0)},
{FromT {1}, ToT {1}},
{FromT {9}, ToT {9}},
{FromT {123}, ToT {123}},
{FromT {to_max_val}, ToT {to_max_val}},
{FromT {-1}, ToT {-1}},
{FromT {-9}, ToT {-9}},
{FromT {-123}, ToT {-123}},
{FromT {to_min_val}, ToT {to_min_val}}};
// test_vals.push_back({max_val_minus_1, ToT {max_val_minus_1}});
// test_vals.push_back({min_val_plus_1, ToT {min_val_plus_1}});
DataSet data_set;
for (const auto& p : test_vals) {
data_set.push_back({{p.first}, p.second});
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1);
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_type_name = get_sql_type_name(FromPT);
std::string to_type_name = get_sql_type_name(ToPT);
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_{}", to_type_name, from_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_int");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_normal_regression_case(regression_case_name, from_type_name, true, to_type_name,
test_vals, table_index++, test_data_index, ofs_case,
ofs_expected_result, ofs_const_case,
ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType FromPT, PrimitiveType ToPT>
void wider_to_narrow_int_overflow_test_func() {
using FromT = typename PrimitiveTypeTraits<FromPT>::CppType;
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(sizeof(FromT) > sizeof(ToT), "FromT must be larger than ToT");
DataTypeNumber<FromPT> dt;
InputTypeSet input_types = {dt.get_primitive_type()};
constexpr auto to_max_val = std::numeric_limits<ToT>::max();
constexpr auto to_min_val = std::numeric_limits<ToT>::min();
std::vector<FromT> test_input_vals = {
static_cast<FromT>(to_max_val) + 1,
static_cast<FromT>(to_min_val) - 1,
std::numeric_limits<FromT>::max(),
std::numeric_limits<FromT>::min(),
};
// non strict mode
{
DataSet data_set;
for (auto v : test_input_vals) {
data_set.push_back({{v}, Null()});
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
}
// strict mode
{
for (auto v : test_input_vals) {
DataSet data_set;
data_set.push_back({{v}, Null()});
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1,
true, true);
}
}
if (FLAGS_gen_regression_case) {
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = get_sql_type_name(FromPT);
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::string regression_case_name = fmt::format("test_cast_to_{}_from_{}_overflow",
to_sql_type_name, from_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_int");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_overflow_and_invalid_regression_case(regression_case_name, from_sql_type_name, true,
to_sql_type_name, test_input_vals,
table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType FromPT, PrimitiveType ToPT>
void from_float_test_func() {
using FromT = typename PrimitiveTypeTraits<FromPT>::CppType;
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(std::numeric_limits<FromT>::is_iec559, "FromT must be a floating point type");
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
DataTypeNumber<FromPT> dt;
InputTypeSet input_types = {dt.get_primitive_type()};
// std::cout << fmt::format("test cast {} to {}\n", type_to_string(FromPT),
// type_to_string(ToPT));
DataSet data_set = {
// Zero and sign
{{FromT {0.0}}, ToT(0)},
{{FromT {-0.0}}, ToT(0)},
{{FromT {+0.0}}, ToT(0)},
// Positive integers
{{FromT {1.0}}, ToT(1)},
{{FromT {9.0}}, ToT(9)},
{{FromT {123.0}}, ToT(123)},
{{FromT {127.9}}, ToT(127)},
// Negative integers
{{FromT {-1.0}}, ToT(-1)},
{{FromT {-9.0}}, ToT(-9)},
{{FromT {-123.0}}, ToT(-123)},
{{FromT {-128.9}}, ToT(-128)},
{{static_cast<FromT>(std::numeric_limits<ToT>::min())},
static_cast<ToT>(static_cast<FromT>(std::numeric_limits<ToT>::min()))},
// Fractional values (truncate toward zero)
{{FromT {1.9}}, ToT(1)},
{{FromT {-1.9}}, ToT(-1)},
{{FromT {0.9999}}, ToT(0)},
{{FromT {-0.9999}}, ToT(0)},
// Subnormal (denormalized) numbers
{{FromT {std::numeric_limits<FromT>::denorm_min()}}, ToT(0)},
{{FromT {-std::numeric_limits<FromT>::denorm_min()}}, ToT(0)},
};
switch (ToPT) {
case TYPE_LARGEINT:
data_set.push_back({{FromT(std::pow(2, 64))}, ToT(std::pow(2, 64))});
data_set.push_back({{FromT(-std::pow(2, 64))}, ToT(-std::pow(2, 64))});
data_set.push_back({{FromT(std::pow(2, 126))}, ToT(std::pow(2, 126))});
data_set.push_back({{FromT(-std::pow(2, 126))}, ToT(-std::pow(2, 126))});
[[fallthrough]];
case TYPE_BIGINT:
data_set.push_back({{FromT(std::pow(2, 32))}, ToT(std::pow(2, 32))});
data_set.push_back({{FromT(-std::pow(2, 32))}, ToT(-std::pow(2, 32))});
data_set.push_back({{FromT(std::pow(2, 62))}, ToT(std::pow(2, 62))});
data_set.push_back({{FromT(-std::pow(2, 62))}, ToT(-std::pow(2, 62))});
if constexpr (FromPT == TYPE_DOUBLE) {
// 9223372036854775295 == 2^63 - 2^9 - 1
data_set.push_back({{FromT(9223372036854775295.0)}, ToT(9223372036854774784)});
// 9223372036854776832 == 2^63 + 2^10
data_set.push_back({{FromT(-9223372036854776832.0)},
ToT(std::numeric_limits<int64_t>::min())});
} else {
// 9223371761976868863 == 2^63 - 2^38 - 1
data_set.push_back({{FromT(9223371761976868863.0f)}, ToT(9223371487098961920)});
// 9223372586610589696 == 2^63 + 2^39
data_set.push_back({{FromT(-9223372586610589696.0f)},
ToT(std::numeric_limits<int64_t>::min())});
}
[[fallthrough]];
case TYPE_INT:
data_set.push_back({{FromT {32768.9}}, ToT(32768)});
data_set.push_back({{FromT {-32769.9}}, ToT(-32769)});
data_set.push_back({{FromT {999999.9}}, ToT(999999)});
data_set.push_back({{FromT {-999999.9}}, ToT(-999999)});
data_set.push_back({{FromT(std::pow(2, 30))}, ToT(std::pow(2, 30))});
data_set.push_back({{FromT(-std::pow(2, 30))}, ToT(-std::pow(2, 30))});
if constexpr (FromPT == TYPE_DOUBLE) {
// 2147483647 == 2^31 - 1
data_set.push_back({{FromT(2147483647.0)}, ToT(2147483647)});
// 2147483648 == 2^31
data_set.push_back(
{{FromT(-2147483648.0)}, ToT(std::numeric_limits<int32_t>::min())});
} else {
// 2147483583 == 2^31 - 2^6 - 1
data_set.push_back({{FromT(2147483583.0f)}, ToT(2147483520)});
// 2147483776 == 2^31 + 2^7
data_set.push_back({{FromT(-2147483776.0f)}, ToT(-2147483648)});
}
[[fallthrough]];
case TYPE_SMALLINT:
data_set.push_back({{FromT {32767.9}}, ToT(32767)});
data_set.push_back({{FromT {-32768.9}}, ToT(-32768)});
// 32767 == 2^15 - 1
data_set.push_back({{FromT(32767.0)}, ToT(32767)});
// 32768 == 2^15
data_set.push_back({{FromT(-32768.0)}, ToT(std::numeric_limits<int16_t>::min())});
break;
default:
break;
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1);
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = get_sql_type_name(FromPT);
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_{}", to_sql_type_name, from_sql_type_name);
setup_regression_case_output(
regression_case_name, ofs_const_case_uptr, ofs_const_expected_result_uptr,
ofs_case_uptr, ofs_expected_result_uptr, "to_int/from_float", false, true);
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
std::vector<std::pair<std::string, ToT>> regression_test_data_set;
for (const auto& p : data_set) {
regression_test_data_set.push_back(
{fmt::format("{}", any_cast<FromT>(p.first[0])), any_cast<ToT>(p.second)});
}
gen_normal_regression_case(regression_case_name, from_sql_type_name, true,
to_sql_type_name, regression_test_data_set, table_index++,
test_data_index, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result, false, true);
(*ofs_case) << "}";
}
}
template <PrimitiveType FromPT, PrimitiveType ToPT>
void from_float_overflow_test_func() {
using FromT = typename PrimitiveTypeTraits<FromPT>::CppType;
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
DataTypeNumber<FromPT> dt;
InputTypeSet input_types = {dt.get_primitive_type()};
std::vector<FromT> test_input_vals = {
std::numeric_limits<FromT>::max(),
std::numeric_limits<FromT>::lowest(),
std::numeric_limits<FromT>::infinity(),
std::numeric_limits<FromT>::quiet_NaN(),
};
switch (ToPT) {
case TYPE_TINYINT:
test_input_vals.push_back(FromT(128.0));
test_input_vals.push_back(FromT(-129.0));
[[fallthrough]];
case TYPE_SMALLINT:
test_input_vals.push_back(FromT(32768.0));
test_input_vals.push_back(FromT(-32769.0));
// 32768 == 2^15
test_input_vals.push_back(FromT(32768.0));
// 32769 == 2^15 + 1
test_input_vals.push_back(FromT(-32769.0));
[[fallthrough]];
case TYPE_INT:
test_input_vals.push_back(FromT(std::pow(2, 32)));
test_input_vals.push_back(FromT(-std::pow(2, 32)));
if constexpr (FromPT == TYPE_DOUBLE) {
// 2147483647 == 2^31
test_input_vals.push_back(FromT(2147483648.0));
// 2147483648 == 2^31 + 1
test_input_vals.push_back(FromT(-2147483649.0));
} else {
// 2147483584 = 2^31 - 2^6
test_input_vals.push_back(FromT(2147483584.0f));
// 2147483777 = 2^31 + 2^7 + 1
test_input_vals.push_back(FromT(-2147483777.0f));
}
[[fallthrough]];
case TYPE_BIGINT:
test_input_vals.push_back(FromT(std::pow(2, 64)));
test_input_vals.push_back(FromT(-std::pow(2, 64)));
if constexpr (FromPT == TYPE_DOUBLE) {
// 9223372036854775296 == 2^63 - 2^9
test_input_vals.push_back(FromT(9223372036854775296.0));
// 9223372036854776833 == 2^63 + 2^10 + 1
test_input_vals.push_back(FromT(-9223372036854776833.0));
} else {
// 9223371761976868864 == 2^63 - 2^38
test_input_vals.push_back(FromT(9223371761976868864.0f));
// 92233725866105896967 = 2^63 + 2^39 + 1
test_input_vals.push_back(FromT(-9223372586610589697.0f));
}
[[fallthrough]];
case TYPE_LARGEINT:
test_input_vals.push_back(FromT(std::pow(2, 128)));
test_input_vals.push_back(FromT(-std::pow(2, 128)));
if constexpr (FromPT == TYPE_DOUBLE) {
test_input_vals.push_back(FromT(std::pow(2, 129)));
test_input_vals.push_back(FromT(-std::pow(2, 129)));
test_input_vals.push_back(FromT(170141183460469250621153235194464960513.0));
test_input_vals.push_back(FromT(-170141183460469250621153235194464960513.0));
}
[[fallthrough]];
default:
break;
}
// non strict mode
{
DataSet data_set;
for (auto v : test_input_vals) {
data_set.push_back({{v}, Null()});
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
}
// strict mode
{
for (auto v : test_input_vals) {
DataSet data_set;
data_set.push_back({{v}, Null()});
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1,
true, true);
}
}
if (FLAGS_gen_regression_case) {
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = get_sql_type_name(FromPT);
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::string regression_case_name = fmt::format("test_cast_to_{}_from_{}_overflow",
to_sql_type_name, from_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_float");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
std::vector<std::string> regression_test_data_set;
for (const auto& v : test_input_vals) {
regression_test_data_set.push_back(fmt::format("{}", v));
}
gen_overflow_and_invalid_regression_case(regression_case_name, from_sql_type_name, true,
to_sql_type_name, regression_test_data_set,
table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <typename FromT, PrimitiveType ToPT>
void from_decimal_with_p_s_no_overflow_test_func(int FromPrecision, int FromScale) {
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(IsDecimalNumber<FromT>, "FromT must be a decimal type");
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
// static_assert(FromPrecision - FromScale >= 0 &&
// FromPrecision - FromScale < NumberTraits::max_ascii_len<ToT>(),
// "Decimal integral part must be less than integer max ascii len");
DataTypeDecimal<FromT::PType> dt_from =
get_decimal_data_type<FromT>(FromPrecision, FromScale);
InputTypeSet input_types = {{dt_from.get_primitive_type(), FromScale, FromPrecision}};
auto decimal_ctor = get_decimal_ctor<FromT>();
using IntType = ToT;
DataTypeNumber<ToPT> dt_to;
// constexpr IntType int_max = std::numeric_limits<IntType>::max();
// constexpr IntType int_min = std::numeric_limits<IntType>::min();
// Compute valid ranges for integral and fractional parts
// from_max_integral: 99999999
// from_large_integral1: 9999999
// from_large_integral2: 90000000
// from_large_integral3: 90000001
auto from_max_integral =
decimal_scale_multiplier<typename FromT::NativeType>(FromPrecision - FromScale) - 1;
auto from_large_integral1 = decimal_scale_multiplier<typename FromT::NativeType>(
FromPrecision - FromScale - 1) -
1;
auto from_large_integral2 = from_max_integral - from_large_integral1;
auto from_large_integral3 =
from_large_integral2 > 9 ? from_large_integral2 + 1 : from_large_integral2 - 1;
// constexpr auto min_integral = -from_max_integral;
// std::cout << "from_max_integral:\t" << fmt::format("{}", from_max_integral) << std::endl;
// std::cout << "from_large_integral1:\t" << fmt::format("{}", from_large_integral1)
// << std::endl;
// std::cout << "from_large_integral2:\t" << fmt::format("{}", from_large_integral2)
// << std::endl;
// std::cout << "from_large_integral3:\t" << fmt::format("{}", from_large_integral3)
// << std::endl;
// from_max_fractional: 99999999
// from_large_fractional1: 9999999
// from_large_fractional2: 90000000
// from_large_fractional3: 90000001
auto from_max_fractional =
decimal_scale_multiplier<typename FromT::NativeType>(FromScale) - 1;
auto from_large_fractional1 =
decimal_scale_multiplier<typename FromT::NativeType>(FromScale - 1) - 1;
auto from_large_fractional2 = from_max_fractional - from_large_fractional1;
auto from_large_fractional3 = from_large_fractional2 > 9 ? from_large_fractional2 + 1
: from_large_fractional2 - 1;
// std::cout << "from_max_fractional:\t" << fmt::format("{}", from_max_fractional)
// << std::endl;
// std::cout << "from_large_fractional1:\t" << fmt::format("{}", from_large_fractional1)
// << std::endl;
// std::cout << "from_large_fractional2:\t" << fmt::format("{}", from_large_fractional2)
// << std::endl;
// std::cout << "from_large_fractional3:\t" << fmt::format("{}", from_large_fractional3)
// << std::endl;
// constexpr auto min_fractional = -from_max_fractional;
std::vector<IntType> integral_part = {
0,
1,
9,
};
// e.g. from Decimal(9, 0) to int16
if (FromPrecision - FromScale >= NumberTraits::max_ascii_len<ToT>()) {
integral_part.push_back(std::numeric_limits<IntType>::max());
integral_part.push_back(std::numeric_limits<IntType>::max() - 1);
integral_part.push_back(std::numeric_limits<IntType>::min());
integral_part.push_back(std::numeric_limits<IntType>::min() + 1);
} else {
integral_part.push_back(from_max_integral);
if (FromPrecision - FromScale > 0) {
integral_part.push_back(from_max_integral - 1);
integral_part.push_back(from_large_integral1);
integral_part.push_back(from_large_integral2);
integral_part.push_back(from_large_integral3);
}
}
std::vector<typename FromT::NativeType> fractional_part = {0,
1,
9,
from_max_fractional,
from_max_fractional - 1,
from_large_fractional1,
from_large_fractional2,
from_large_fractional3};
DataSet data_set;
std::string dbg_str =
fmt::format("test cast {}({}, {}) to {}: \n", type_to_string(FromT::PType),
FromPrecision, FromScale, dt_to.get_family_name());
// std::cout << dbg_str << std::endl;
std::vector<std::pair<std::string, ToT>> test_data_set;
Defer defer {[&]() {
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
std::string from_decimal_sql_type_name =
FromT::PType == TYPE_DECIMALV2 ? "decimalv2" : "decimalv3";
std::string from_sql_type_name = fmt::format(
"{}({}, {})", from_decimal_sql_type_name, FromPrecision, FromScale);
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string regression_case_name = fmt::format(
"test_cast_to_{}_from_{}_{}_{}", to_sql_type_name,
to_lower(type_to_string(FromT::PType)), FromPrecision, FromScale);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_decimal");
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
if constexpr (IsDecimal256<FromT>) {
(*ofs_const_case) << " sql \"set enable_decimal256 = true;\"\n";
(*ofs_case) << " sql \"set enable_decimal256 = true;\"\n";
}
gen_normal_regression_case(regression_case_name, from_sql_type_name, true,
to_sql_type_name, test_data_set, table_index,
test_data_index, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}};
if (FromScale == 0) {
// e.g. Decimal(9, 0), only int part
for (const auto& i : integral_part) {
auto decimal_num = decimal_ctor(i, 0, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, IntType(i)});
test_data_set.emplace_back(num_str, i);
if (FromPrecision - FromScale < NumberTraits::max_ascii_len<ToT>()) {
decimal_num = decimal_ctor(-i, 0, FromScale);
num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, -i);
data_set.push_back({{decimal_num}, IntType(-i)});
test_data_set.emplace_back(num_str, -i);
}
}
// dbg_str += "\n";
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1);
return;
} else if (FromScale == FromPrecision) {
// e.g. Decimal(9, 9), only fraction part
for (const auto& f : fractional_part) {
auto decimal_num = decimal_ctor(0, f, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, 0);
data_set.push_back({{decimal_num}, IntType(0)});
test_data_set.emplace_back(num_str, 0);
decimal_num = decimal_ctor(0, -f, FromScale);
num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, 0);
data_set.push_back({{decimal_num}, IntType(0)});
test_data_set.emplace_back(num_str, 0);
}
// dbg_str += "\n";
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1);
return;
}
for (const auto& i : integral_part) {
for (const auto& f : fractional_part) {
if (FromPrecision - FromScale < NumberTraits::max_ascii_len<ToT>()) {
auto decimal_num = decimal_ctor(i, f, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, IntType(i)});
test_data_set.emplace_back(num_str, i);
decimal_num = decimal_ctor(-i, -f, FromScale);
num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, -i);
data_set.push_back({{decimal_num}, IntType(-i)});
test_data_set.emplace_back(num_str, -i);
} else {
if (i >= 0) {
auto decimal_num = decimal_ctor(i, f, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, IntType(i)});
test_data_set.emplace_back(num_str, i);
} else {
auto decimal_num = decimal_ctor(i, -f, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, IntType(i)});
test_data_set.emplace_back(num_str, i);
}
}
}
// dbg_str += "\n";
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1);
}
template <typename FromT, PrimitiveType ToT>
void from_decimal_to_int_test_func() {
constexpr auto max_decimal_pre = max_decimal_precision<FromT::PType>();
constexpr auto min_decimal_pre =
std::is_same_v<FromT, Decimal32>
? 1
: (std::is_same_v<FromT, Decimal64>
? BeConsts::MAX_DECIMAL32_PRECISION + 1
: (std::is_same_v<FromT, Decimal128V3>
? BeConsts::MAX_DECIMAL64_PRECISION + 1
: (std::is_same_v<FromT, Decimal256>
? BeConsts::MAX_DECIMAL128_PRECISION + 1
: 1)));
static_assert(min_decimal_pre == 1 || min_decimal_pre > 9);
if constexpr (std::is_same_v<FromT, Decimal128V2>) {
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(1, 0);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(1, 1);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(27, 9);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(20, 6);
} else {
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(min_decimal_pre, 0);
if constexpr (min_decimal_pre != 1) {
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(min_decimal_pre,
min_decimal_pre / 2);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(min_decimal_pre,
min_decimal_pre - 1);
}
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(min_decimal_pre,
min_decimal_pre);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(max_decimal_pre, 0);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(max_decimal_pre, 1);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(max_decimal_pre,
max_decimal_pre / 2);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(max_decimal_pre,
max_decimal_pre - 1);
from_decimal_with_p_s_no_overflow_test_func<FromT, ToT>(max_decimal_pre,
max_decimal_pre);
}
}
template <typename FromT, PrimitiveType ToPT>
void from_decimal_with_p_s_overflow_test_func(int FromPrecision, int FromScale,
const std::string& regression_case_name,
int table_index, std::ofstream* ofs_case,
std::ofstream* ofs_expected_result,
std::ofstream* ofs_const_case,
std::ofstream* ofs_const_expected_result) {
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(IsDecimalNumber<FromT>, "FromT must be a decimal type");
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
if (FromPrecision - FromScale < NumberTraits::max_ascii_len<ToT>()) {
return;
}
DataTypeDecimal<FromT::PType> dt_from =
get_decimal_data_type<FromT>(FromPrecision, FromScale);
InputTypeSet input_types = {{dt_from.get_primitive_type(), FromScale, FromPrecision}};
auto decimal_ctor = get_decimal_ctor<FromT>();
using IntType = ToT;
DataTypeNumber<ToPT> dt_to;
// from_max_integral: 99999999
auto from_max_integral =
decimal_scale_multiplier<typename FromT::NativeType>(FromPrecision - FromScale) - 1;
// constexpr auto min_integral = -from_max_integral;
// std::cout << "from_max_integral:\t" << fmt::format("{}", from_max_integral) << std::endl;
// from_max_fractional: 99999999
// from_large_fractional1: 9999999
// from_large_fractional2: 90000000
// from_large_fractional3: 90000001
auto from_max_fractional =
decimal_scale_multiplier<typename FromT::NativeType>(FromScale) - 1;
auto from_large_fractional1 =
decimal_scale_multiplier<typename FromT::NativeType>(FromScale - 1) - 1;
auto from_large_fractional2 = from_max_fractional - from_large_fractional1;
auto from_large_fractional3 = from_large_fractional2 > 9 ? from_large_fractional2 + 1
: from_large_fractional2 - 1;
// std::cout << "from_max_fractional:\t" << fmt::format("{}", from_max_fractional)
// << std::endl;
// std::cout << "from_large_fractional1:\t" << fmt::format("{}", from_large_fractional1)
// << std::endl;
// std::cout << "from_large_fractional2:\t" << fmt::format("{}", from_large_fractional2)
// << std::endl;
// std::cout << "from_large_fractional3:\t" << fmt::format("{}", from_large_fractional3)
// << std::endl;
std::vector<typename FromT::NativeType> integral_part;
if constexpr (sizeof(typename FromT::NativeType) > sizeof(IntType)) {
integral_part.push_back(
static_cast<typename FromT::NativeType>(std::numeric_limits<IntType>::max()) +
1);
integral_part.push_back(
static_cast<typename FromT::NativeType>(std::numeric_limits<IntType>::min()) -
1);
}
integral_part.push_back(from_max_integral);
integral_part.push_back(-from_max_integral);
if (FromPrecision - FromScale > 0) {
integral_part.push_back(from_max_integral - 1);
integral_part.push_back(-from_max_integral + 1);
}
std::vector<typename FromT::NativeType> fractional_part = {0,
1,
9,
from_max_fractional,
from_max_fractional - 1,
from_large_fractional1,
from_large_fractional2,
from_large_fractional3};
std::string dbg_str =
fmt::format("test cast {}({}, {}) to {}: ", type_to_string(FromT::PType),
FromPrecision, FromScale, dt_to.get_family_name());
// std::cout << dbg_str << std::endl;
std::vector<std::string> test_data_set;
Defer defer {[&]() {
if (FLAGS_gen_regression_case) {
std::string from_decimal_sql_type_name =
FromT::PType == TYPE_DECIMALV2 ? "decimalv2" : "decimalv3";
std::string from_sql_type_name = fmt::format(
"{}({}, {})", from_decimal_sql_type_name, FromPrecision, FromScale);
std::string to_sql_type_name = get_sql_type_name(ToPT);
gen_overflow_and_invalid_regression_case(regression_case_name, from_sql_type_name,
true, to_sql_type_name, test_data_set,
table_index, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
}
}};
if (FromScale == 0) {
// non strict mode
{
DataSet data_set;
// e.g. Decimal(9, 0), only int part
for (const auto& i : integral_part) {
auto decimal_num = decimal_ctor(i, 0, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, Null()});
test_data_set.emplace_back(num_str);
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
}
// strict mode
{
for (const auto& i : integral_part) {
DataSet data_set;
auto decimal_num = decimal_ctor(i, 0, FromScale);
data_set.push_back({{decimal_num}, Null()});
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1,
-1, true);
}
}
return;
}
// non strict mode
{
DataSet data_set;
for (const auto& i : integral_part) {
for (const auto& f : fractional_part) {
if (i >= 0) {
auto decimal_num = decimal_ctor(i, f, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, Null()});
test_data_set.emplace_back(num_str);
} else {
auto decimal_num = decimal_ctor(i, -f, FromScale);
auto num_str = dt_from.to_string(decimal_num);
// dbg_str += fmt::format("({}, {})|", num_str, i);
data_set.push_back({{decimal_num}, Null()});
test_data_set.emplace_back(num_str);
}
}
// dbg_str += "\n";
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1);
}
// strict mode
{
for (const auto& i : integral_part) {
for (const auto& f : fractional_part) {
DataSet data_set;
if (i >= 0) {
auto decimal_num = decimal_ctor(i, f, FromScale);
data_set.push_back({{decimal_num}, Null()});
} else {
auto decimal_num = decimal_ctor(i, -f, FromScale);
data_set.push_back({{decimal_num}, Null()});
}
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1,
-1, true);
}
}
}
}
template <typename FromT, PrimitiveType ToT>
void from_decimal_to_int_overflow_test_func() {
constexpr auto max_decimal_pre = max_decimal_precision<FromT::PType>();
constexpr auto min_decimal_pre =
std::is_same_v<FromT, Decimal32>
? 1
: (std::is_same_v<FromT, Decimal64>
? BeConsts::MAX_DECIMAL32_PRECISION + 1
: (std::is_same_v<FromT, Decimal128V3>
? BeConsts::MAX_DECIMAL64_PRECISION + 1
: (std::is_same_v<FromT, Decimal256>
? BeConsts::MAX_DECIMAL128_PRECISION + 1
: 1)));
static_assert(min_decimal_pre == 1 || min_decimal_pre > 9);
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_{}_overflow", to_lower(type_to_string(ToT)),
to_lower(type_to_string(FromT::PType)));
if (FLAGS_gen_regression_case) {
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_decimal");
}
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
if (FLAGS_gen_regression_case) {
if constexpr (IsDecimal256<FromT>) {
(*ofs_const_case) << " sql \"set enable_decimal256 = true;\"\n";
(*ofs_case) << " sql \"set enable_decimal256 = true;\"\n";
}
}
if constexpr (std::is_same_v<FromT, Decimal128V2>) {
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
1, 0, regression_case_name, table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
1, 1, regression_case_name, table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
27, 9, regression_case_name, table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
19, 6, regression_case_name, table_index++, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result);
} else {
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
min_decimal_pre, 0, regression_case_name, table_index++, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result);
if constexpr (min_decimal_pre != 1) {
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
min_decimal_pre, min_decimal_pre / 2, regression_case_name, table_index++,
ofs_case, ofs_expected_result, ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
min_decimal_pre, min_decimal_pre - 1, regression_case_name, table_index++,
ofs_case, ofs_expected_result, ofs_const_case, ofs_const_expected_result);
}
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
min_decimal_pre, min_decimal_pre, regression_case_name, table_index++, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
max_decimal_pre, 0, regression_case_name, table_index++, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
max_decimal_pre, 1, regression_case_name, table_index++, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
max_decimal_pre, max_decimal_pre / 2, regression_case_name, table_index++,
ofs_case, ofs_expected_result, ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
max_decimal_pre, max_decimal_pre - 1, regression_case_name, table_index++,
ofs_case, ofs_expected_result, ofs_const_case, ofs_const_expected_result);
from_decimal_with_p_s_overflow_test_func<FromT, ToT>(
max_decimal_pre, max_decimal_pre, regression_case_name, table_index++, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result);
}
if (FLAGS_gen_regression_case) {
(*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
template <PrimitiveType ToPT>
void from_date_test_func() {
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
using IntType = ToT;
InputTypeSet input_types = {PrimitiveType::TYPE_DATEV2};
// int scale = 6;
// test ordinary date time with microsecond: '2024-12-31 23:59:59.999999'
std::vector<uint16_t> years = {0, 1, 10, 100, 2025, 9999};
std::vector<uint8_t> months = {1, 12};
std::vector<uint8_t> days = {1, 10, 28};
DataTypeDateV2 dt;
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::string dbg_str = fmt::format("test cast datev2 to {}: ", to_sql_type_name);
// std::cout << dbg_str << std::endl;
constexpr bool is_supported_int_type =
(ToPT == TYPE_INT || ToPT == TYPE_BIGINT || ToPT == TYPE_LARGEINT);
DataSet data_set;
std::vector<std::pair<std::string, ToT>> regression_test_data_set;
for (auto year : years) {
for (auto month : months) {
for (auto day : days) {
DateV2Value<DateV2ValueType> date_val(year, month, day, 0, 0, 0, 0);
IntType expect_cast_result = year * 10000 + month * 100 + day;
if constexpr (!is_supported_int_type) {
DataSet data_set_tmp;
data_set_tmp.push_back({{date_val}, expect_cast_result});
check_function_for_cast<DataTypeNumber<ToPT>, false>(
input_types, data_set_tmp, -1, -1, false, true);
check_function_for_cast<DataTypeNumber<ToPT>, true>(
input_types, data_set_tmp, -1, -1, false, true);
} else {
// dbg_str +=
// fmt::format("({}, {})|", dt.to_string(date_val.to_date_int_val()),
// expect_cast_result);
data_set.push_back({{date_val}, expect_cast_result});
if (FLAGS_gen_regression_case) {
regression_test_data_set.push_back(
{dt.to_string(date_val.to_date_int_val()), expect_cast_result});
}
}
}
}
// dbg_str += "\n";
}
if constexpr (is_supported_int_type) {
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1,
false);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1,
false);
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string from_sql_type_name = "datev2";
std::string regression_case_name = fmt::format(
"test_cast_to_{}_from_{}", to_sql_type_name, from_sql_type_name);
setup_regression_case_output(
regression_case_name, ofs_const_case_uptr, ofs_const_expected_result_uptr,
ofs_case_uptr, ofs_expected_result_uptr, "to_int/from_datetime", false);
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_normal_regression_case(
regression_case_name, from_sql_type_name, true, to_sql_type_name,
regression_test_data_set, table_index++, test_data_index, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result, false);
// (*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
}
template <PrimitiveType ToPT>
void from_datetime_test_func(int Scale) {
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
using IntType = ToT;
InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, Scale}};
std::vector<uint16_t> years = {0, 1, 10, 100, 2025, 9999};
std::vector<uint8_t> months = {1, 12};
std::vector<uint8_t> days = {1, 28};
std::vector<uint8_t> hours = {0, 1, 23};
std::vector<uint8_t> minutes = {0, 1, 59};
std::vector<uint8_t> seconds = {0, 1, 59};
std::vector<uint32_t> mircoseconds = {0, 1, 999999};
DataTypeDateTimeV2 dt(Scale);
DataSet data_set;
std::vector<std::pair<std::string, ToT>> regression_test_data_set;
constexpr bool is_supported_int_type = (ToPT == TYPE_BIGINT || ToPT == TYPE_LARGEINT);
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::string dbg_str =
fmt::format("test cast datetimev2({}) to {}: ", Scale, to_sql_type_name);
// std::cout << dbg_str << std::endl;
for (auto year : years) {
for (auto month : months) {
for (auto day : days) {
for (auto hour : hours) {
for (auto minute : minutes) {
for (auto second : seconds) {
for (auto microsecond : mircoseconds) {
DateV2Value<DateTimeV2ValueType> date_val(
year, month, day, hour, minute, second, microsecond);
IntType expect_cast_result =
(year * 10000L + month * 100 + day) * 1000000L +
hour * 10000 + minute * 100 + second;
// dbg_str += fmt::format("({}, {})|",
// dt.to_string(date_val.to_date_int_val()),
// expect_cast_result);
if constexpr (!is_supported_int_type) {
DataSet data_set_tmp;
data_set_tmp.push_back({{date_val}, expect_cast_result});
check_function_for_cast<DataTypeNumber<ToPT>, false>(
input_types, data_set_tmp, -1, -1, false, true);
check_function_for_cast<DataTypeNumber<ToPT>, true>(
input_types, data_set_tmp, -1, -1, false, true);
} else {
data_set.push_back({{date_val}, expect_cast_result});
if (FLAGS_gen_regression_case) {
regression_test_data_set.push_back(
{dt.to_string(date_val.to_date_int_val()),
expect_cast_result});
}
}
}
if constexpr (!is_supported_int_type) {
goto loop_end;
}
}
}
}
// dbg_str += "\n";
}
}
}
loop_end:
if constexpr (is_supported_int_type) {
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1,
false);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1,
false);
if (FLAGS_gen_regression_case) {
int table_index = 0;
int test_data_index = 0;
auto test_data_total_row_count = regression_test_data_set.size();
size_t num_pieces = 10;
size_t regression_case_avg_row_count =
(test_data_total_row_count + num_pieces - 1) / num_pieces;
std::string from_sql_type_name = fmt::format("datetimev2({})", Scale);
for (size_t piece = 0; piece < num_pieces; ++piece) {
size_t data_index = piece * regression_case_avg_row_count;
if (data_index >= test_data_total_row_count) {
break;
}
size_t regression_case_row_count = regression_case_avg_row_count;
if (data_index + regression_case_row_count > test_data_total_row_count) {
regression_case_row_count = test_data_total_row_count - data_index;
}
std::unique_ptr<std::ofstream> ofs_const_case_uptr,
ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string regression_case_name =
fmt::format("test_cast_to_{}_from_datetimev2_{}_part{}",
to_sql_type_name, Scale, piece);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_datetime",
false);
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
std::vector<std::pair<std::string, ToT>> piece_data(
regression_test_data_set.begin() + data_index,
regression_test_data_set.begin() + data_index +
regression_case_row_count);
gen_normal_regression_case(regression_case_name, from_sql_type_name, true,
to_sql_type_name, piece_data, table_index++,
test_data_index, ofs_case, ofs_expected_result,
ofs_const_case, ofs_const_expected_result, false);
// (*ofs_const_case) << "}";
(*ofs_case) << "}";
}
}
}
}
template <PrimitiveType ToPT>
void from_time_test_func() {
using ToT = typename PrimitiveTypeTraits<ToPT>::CppType;
InputTypeSet input_types = {{PrimitiveType::TYPE_TIMEV2, 6}};
using IntType = ToT;
static_assert(std::numeric_limits<ToT>::is_integer, "ToT must be an integer type");
std::vector<int64_t> hours = {0, 1, 10, 100, 838};
std::vector<int64_t> minutes = {0, 1, 10, 59};
std::vector<int64_t> seconds = {0, 1, 10, 59};
// constexpr TimeValue::TimeType max_time_value = std::min<TimeValue::TimeType>(std::numeric_limits<IntType>::max(), TimeValue::MAX_TIME);
std::string to_sql_type_name = get_sql_type_name(ToPT);
std::string dbg_str = fmt::format("test cast time to {}: ", to_sql_type_name);
// std::cout << dbg_str << std::endl;
std::vector<std::pair<std::string, ToT>> regression_test_data_set;
std::vector<std::string> regression_test_overflow_data_set;
auto test_func = [&](bool negative) {
DataSet data_set;
for (auto h : hours) {
for (auto m : minutes) {
for (auto s : seconds) {
auto time_val = doris::TimeValue::make_time(h, m, s, negative);
if (time_val > std::numeric_limits<IntType>::max() ||
time_val < std::numeric_limits<IntType>::min()) {
DataSet data_set_tmp;
data_set_tmp.push_back({{time_val}, Null()});
check_function_for_cast<DataTypeNumber<ToPT>, false>(
input_types, data_set_tmp, -1, -1, false);
check_function_for_cast<DataTypeNumber<ToPT>, true>(
input_types, data_set_tmp, -1, -1, false, true);
if (FLAGS_gen_regression_case) {
regression_test_overflow_data_set.emplace_back(
doris::TimeValue::to_string(time_val, 6));
}
continue;
}
auto expect_cast_result = static_cast<IntType>(time_val);
data_set.push_back({{time_val}, expect_cast_result});
// dbg_str +=
// fmt::format("({}, {})|", doris::TimeValue::to_string(time_val, 6),
// expect_cast_result);
if (FLAGS_gen_regression_case) {
regression_test_data_set.emplace_back(
doris::TimeValue::to_string(time_val, 6), expect_cast_result);
}
}
}
}
check_function_for_cast<DataTypeNumber<ToPT>, false>(input_types, data_set, -1, -1,
false);
check_function_for_cast<DataTypeNumber<ToPT>, true>(input_types, data_set, -1, -1,
false);
};
test_func(false);
test_func(true);
/*
if (FLAGS_gen_regression_case) {
std::string from_sql_type_name = "time";
{
int table_index = 0;
int test_data_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string regression_case_name = fmt::format(
"test_cast_to_{}_from_{}", to_sql_type_name, from_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_datetime", true,
false);
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_normal_regression_case(regression_case_name, from_sql_type_name, true,
to_sql_type_name, regression_test_data_set,
table_index++, test_data_index, ofs_case,
ofs_expected_result, ofs_const_case,
ofs_const_expected_result, true, false);
(*ofs_const_case) << "}";
}
{
int table_index = 0;
std::unique_ptr<std::ofstream> ofs_const_case_uptr, ofs_const_expected_result_uptr;
std::unique_ptr<std::ofstream> ofs_case_uptr, ofs_expected_result_uptr;
std::string regression_case_name = fmt::format(
"test_cast_to_{}_from_{}_overflow", to_sql_type_name, from_sql_type_name);
setup_regression_case_output(regression_case_name, ofs_const_case_uptr,
ofs_const_expected_result_uptr, ofs_case_uptr,
ofs_expected_result_uptr, "to_int/from_datetime", true,
false);
auto* ofs_const_case = ofs_const_case_uptr.get();
auto* ofs_const_expected_result = ofs_const_expected_result_uptr.get();
auto* ofs_case = ofs_case_uptr.get();
auto* ofs_expected_result = ofs_expected_result_uptr.get();
gen_overflow_and_invalid_regression_case(
regression_case_name, from_sql_type_name, true, to_sql_type_name,
regression_test_overflow_data_set, table_index++, ofs_case,
ofs_expected_result, ofs_const_case, ofs_const_expected_result, true);
(*ofs_const_case) << "}";
}
}
*/
}
};
/*
BNF:
<integer> ::= <whitespace>* <sign>? <decimal_digit>+ <whitespace>*
<sign> ::= "+" | "-"
<decimal_digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<whitespace> ::= " " | "\t" | "\n" | "\r" | "\f" | "\v"
*/
TEST_F(FunctionCastToIntTest, test_from_string) {
from_string_test_func<TYPE_TINYINT>();
from_string_test_func<TYPE_SMALLINT>();
from_string_test_func<TYPE_INT>();
from_string_test_func<TYPE_BIGINT>();
from_string_test_func<TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_string_with_fraction_part) {
from_string_with_fraction_part_test_func<TYPE_TINYINT>();
from_string_with_fraction_part_test_func<TYPE_SMALLINT>();
from_string_with_fraction_part_test_func<TYPE_INT>();
from_string_with_fraction_part_test_func<TYPE_BIGINT>();
from_string_with_fraction_part_test_func<TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_string_overflow) {
from_string_overflow_test_func<TYPE_TINYINT>();
from_string_overflow_test_func<TYPE_SMALLINT>();
from_string_overflow_test_func<TYPE_INT>();
from_string_overflow_test_func<TYPE_BIGINT>();
from_string_overflow_test_func<TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_string_invalid_input) {
from_string_invalid_test_func<TYPE_TINYINT>();
from_string_invalid_test_func<TYPE_SMALLINT>();
from_string_invalid_test_func<TYPE_INT>();
from_string_invalid_test_func<TYPE_BIGINT>();
from_string_invalid_test_func<TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_bool) {
InputTypeSet input_types = {PrimitiveType::TYPE_BOOLEAN};
// tinyint
{
DataSet data_set = {
{{UInt8 {0}}, Int8(0)},
{{UInt8 {1}}, Int8(1)},
};
check_function_for_cast<DataTypeInt8, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeInt8, true>(input_types, data_set, -1, -1);
}
// smallint
{
DataSet data_set = {
{{UInt8 {0}}, Int16(0)},
{{UInt8 {1}}, Int16(1)},
};
check_function_for_cast<DataTypeInt16, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeInt16, true>(input_types, data_set, -1, -1);
}
// int
{
DataSet data_set = {
{{UInt8 {0}}, Int32(0)},
{{UInt8 {1}}, Int32(1)},
};
check_function_for_cast<DataTypeInt32, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeInt32, true>(input_types, data_set, -1, -1);
}
// bigint
{
DataSet data_set = {
{{UInt8 {0}}, Int64(0)},
{{UInt8 {1}}, Int64(1)},
};
check_function_for_cast<DataTypeInt64, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeInt64, true>(input_types, data_set, -1, -1);
}
// largeint
{
DataSet data_set = {
{{UInt8 {0}}, Int128(0)},
{{UInt8 {1}}, Int128(1)},
};
check_function_for_cast<DataTypeInt128, false>(input_types, data_set, -1, -1);
check_function_for_cast<DataTypeInt128, true>(input_types, data_set, -1, -1);
}
}
TEST_F(FunctionCastToIntTest, test_from_narrow_to_wider_int) {
narrow_to_wider_int_test_func<TYPE_TINYINT, TYPE_TINYINT>();
narrow_to_wider_int_test_func<TYPE_TINYINT, TYPE_SMALLINT>();
narrow_to_wider_int_test_func<TYPE_TINYINT, TYPE_INT>();
narrow_to_wider_int_test_func<TYPE_TINYINT, TYPE_BIGINT>();
narrow_to_wider_int_test_func<TYPE_TINYINT, TYPE_LARGEINT>();
narrow_to_wider_int_test_func<TYPE_SMALLINT, TYPE_SMALLINT>();
narrow_to_wider_int_test_func<TYPE_SMALLINT, TYPE_INT>();
narrow_to_wider_int_test_func<TYPE_SMALLINT, TYPE_BIGINT>();
narrow_to_wider_int_test_func<TYPE_SMALLINT, TYPE_LARGEINT>();
narrow_to_wider_int_test_func<TYPE_INT, TYPE_INT>();
narrow_to_wider_int_test_func<TYPE_INT, TYPE_BIGINT>();
narrow_to_wider_int_test_func<TYPE_INT, TYPE_LARGEINT>();
narrow_to_wider_int_test_func<TYPE_BIGINT, TYPE_BIGINT>();
narrow_to_wider_int_test_func<TYPE_BIGINT, TYPE_LARGEINT>();
narrow_to_wider_int_test_func<TYPE_LARGEINT, TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_wider_to_narrow_int) {
wider_to_narrow_int_test_func<TYPE_SMALLINT, TYPE_TINYINT>();
wider_to_narrow_int_test_func<TYPE_INT, TYPE_SMALLINT>();
wider_to_narrow_int_test_func<TYPE_INT, TYPE_TINYINT>();
wider_to_narrow_int_test_func<TYPE_BIGINT, TYPE_INT>();
wider_to_narrow_int_test_func<TYPE_BIGINT, TYPE_SMALLINT>();
wider_to_narrow_int_test_func<TYPE_BIGINT, TYPE_TINYINT>();
wider_to_narrow_int_test_func<TYPE_LARGEINT, TYPE_BIGINT>();
wider_to_narrow_int_test_func<TYPE_LARGEINT, TYPE_INT>();
wider_to_narrow_int_test_func<TYPE_LARGEINT, TYPE_SMALLINT>();
wider_to_narrow_int_test_func<TYPE_LARGEINT, TYPE_TINYINT>();
}
TEST_F(FunctionCastToIntTest, test_from_wider_to_narrow_int_overflow) {
wider_to_narrow_int_overflow_test_func<TYPE_SMALLINT, TYPE_TINYINT>();
wider_to_narrow_int_overflow_test_func<TYPE_INT, TYPE_SMALLINT>();
wider_to_narrow_int_overflow_test_func<TYPE_INT, TYPE_TINYINT>();
wider_to_narrow_int_overflow_test_func<TYPE_BIGINT, TYPE_INT>();
wider_to_narrow_int_overflow_test_func<TYPE_BIGINT, TYPE_SMALLINT>();
wider_to_narrow_int_overflow_test_func<TYPE_BIGINT, TYPE_TINYINT>();
wider_to_narrow_int_overflow_test_func<TYPE_LARGEINT, TYPE_BIGINT>();
wider_to_narrow_int_overflow_test_func<TYPE_LARGEINT, TYPE_INT>();
wider_to_narrow_int_overflow_test_func<TYPE_LARGEINT, TYPE_SMALLINT>();
wider_to_narrow_int_overflow_test_func<TYPE_LARGEINT, TYPE_TINYINT>();
}
TEST_F(FunctionCastToIntTest, test_from_float_double) {
from_float_test_func<TYPE_FLOAT, TYPE_TINYINT>();
from_float_test_func<TYPE_FLOAT, TYPE_SMALLINT>();
from_float_test_func<TYPE_FLOAT, TYPE_INT>();
from_float_test_func<TYPE_FLOAT, TYPE_BIGINT>();
from_float_test_func<TYPE_FLOAT, TYPE_LARGEINT>();
from_float_test_func<TYPE_DOUBLE, TYPE_TINYINT>();
from_float_test_func<TYPE_DOUBLE, TYPE_SMALLINT>();
from_float_test_func<TYPE_DOUBLE, TYPE_INT>();
from_float_test_func<TYPE_DOUBLE, TYPE_BIGINT>();
from_float_test_func<TYPE_DOUBLE, TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_float_double_overflow) {
from_float_overflow_test_func<TYPE_FLOAT, TYPE_TINYINT>();
from_float_overflow_test_func<TYPE_FLOAT, TYPE_SMALLINT>();
from_float_overflow_test_func<TYPE_FLOAT, TYPE_INT>();
from_float_overflow_test_func<TYPE_FLOAT, TYPE_BIGINT>();
from_float_overflow_test_func<TYPE_FLOAT, TYPE_LARGEINT>();
from_float_overflow_test_func<TYPE_DOUBLE, TYPE_TINYINT>();
from_float_overflow_test_func<TYPE_DOUBLE, TYPE_SMALLINT>();
from_float_overflow_test_func<TYPE_DOUBLE, TYPE_INT>();
from_float_overflow_test_func<TYPE_DOUBLE, TYPE_BIGINT>();
from_float_overflow_test_func<TYPE_DOUBLE, TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_decimal) {
from_decimal_to_int_test_func<Decimal32, TYPE_TINYINT>();
from_decimal_to_int_test_func<Decimal64, TYPE_TINYINT>();
from_decimal_to_int_test_func<Decimal128V3, TYPE_TINYINT>();
from_decimal_to_int_test_func<Decimal256, TYPE_TINYINT>();
from_decimal_to_int_test_func<Decimal128V2, TYPE_TINYINT>();
from_decimal_to_int_test_func<Decimal32, TYPE_SMALLINT>();
from_decimal_to_int_test_func<Decimal64, TYPE_SMALLINT>();
from_decimal_to_int_test_func<Decimal128V3, TYPE_SMALLINT>();
from_decimal_to_int_test_func<Decimal256, TYPE_SMALLINT>();
from_decimal_to_int_test_func<Decimal128V2, TYPE_SMALLINT>();
from_decimal_to_int_test_func<Decimal32, TYPE_INT>();
from_decimal_to_int_test_func<Decimal64, TYPE_INT>();
from_decimal_to_int_test_func<Decimal128V3, TYPE_INT>();
from_decimal_to_int_test_func<Decimal256, TYPE_INT>();
from_decimal_to_int_test_func<Decimal128V2, TYPE_INT>();
from_decimal_to_int_test_func<Decimal32, TYPE_BIGINT>();
from_decimal_to_int_test_func<Decimal64, TYPE_BIGINT>();
from_decimal_to_int_test_func<Decimal128V3, TYPE_BIGINT>();
from_decimal_to_int_test_func<Decimal256, TYPE_BIGINT>();
from_decimal_to_int_test_func<Decimal128V2, TYPE_BIGINT>();
from_decimal_to_int_test_func<Decimal32, TYPE_LARGEINT>();
from_decimal_to_int_test_func<Decimal64, TYPE_LARGEINT>();
from_decimal_to_int_test_func<Decimal128V3, TYPE_LARGEINT>();
from_decimal_to_int_test_func<Decimal256, TYPE_LARGEINT>();
from_decimal_to_int_test_func<Decimal128V2, TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, DISABLE_test_from_decimal_overflow) {
GTEST_SKIP();
from_decimal_to_int_overflow_test_func<Decimal32, TYPE_TINYINT>();
from_decimal_to_int_overflow_test_func<Decimal64, TYPE_TINYINT>();
from_decimal_to_int_overflow_test_func<Decimal128V3, TYPE_TINYINT>();
from_decimal_to_int_overflow_test_func<Decimal256, TYPE_TINYINT>();
from_decimal_to_int_overflow_test_func<Decimal128V2, TYPE_TINYINT>();
from_decimal_to_int_overflow_test_func<Decimal32, TYPE_SMALLINT>();
from_decimal_to_int_overflow_test_func<Decimal64, TYPE_SMALLINT>();
from_decimal_to_int_overflow_test_func<Decimal128V3, TYPE_SMALLINT>();
from_decimal_to_int_overflow_test_func<Decimal256, TYPE_SMALLINT>();
from_decimal_to_int_overflow_test_func<Decimal128V2, TYPE_SMALLINT>();
from_decimal_to_int_overflow_test_func<Decimal32, TYPE_INT>();
from_decimal_to_int_overflow_test_func<Decimal64, TYPE_INT>();
from_decimal_to_int_overflow_test_func<Decimal128V3, TYPE_INT>();
from_decimal_to_int_overflow_test_func<Decimal256, TYPE_INT>();
from_decimal_to_int_overflow_test_func<Decimal128V2, TYPE_INT>();
from_decimal_to_int_overflow_test_func<Decimal32, TYPE_BIGINT>();
from_decimal_to_int_overflow_test_func<Decimal64, TYPE_BIGINT>();
from_decimal_to_int_overflow_test_func<Decimal128V3, TYPE_BIGINT>();
from_decimal_to_int_overflow_test_func<Decimal256, TYPE_BIGINT>();
from_decimal_to_int_overflow_test_func<Decimal128V2, TYPE_BIGINT>();
from_decimal_to_int_overflow_test_func<Decimal32, TYPE_LARGEINT>();
from_decimal_to_int_overflow_test_func<Decimal64, TYPE_LARGEINT>();
from_decimal_to_int_overflow_test_func<Decimal128V3, TYPE_LARGEINT>();
from_decimal_to_int_overflow_test_func<Decimal256, TYPE_LARGEINT>();
from_decimal_to_int_overflow_test_func<Decimal128V2, TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_date) {
from_date_test_func<TYPE_TINYINT>();
from_date_test_func<TYPE_SMALLINT>();
from_date_test_func<TYPE_INT>();
from_date_test_func<TYPE_BIGINT>();
from_date_test_func<TYPE_LARGEINT>();
}
TEST_F(FunctionCastToIntTest, test_from_datetime) {
from_datetime_test_func<TYPE_TINYINT>(0);
from_datetime_test_func<TYPE_TINYINT>(1);
from_datetime_test_func<TYPE_TINYINT>(3);
from_datetime_test_func<TYPE_TINYINT>(6);
from_datetime_test_func<TYPE_SMALLINT>(0);
from_datetime_test_func<TYPE_SMALLINT>(1);
from_datetime_test_func<TYPE_SMALLINT>(3);
from_datetime_test_func<TYPE_SMALLINT>(6);
from_datetime_test_func<TYPE_INT>(0);
from_datetime_test_func<TYPE_INT>(1);
from_datetime_test_func<TYPE_INT>(3);
from_datetime_test_func<TYPE_INT>(6);
from_datetime_test_func<TYPE_BIGINT>(0);
from_datetime_test_func<TYPE_BIGINT>(1);
from_datetime_test_func<TYPE_BIGINT>(3);
from_datetime_test_func<TYPE_BIGINT>(6);
from_datetime_test_func<TYPE_LARGEINT>(0);
from_datetime_test_func<TYPE_LARGEINT>(1);
from_datetime_test_func<TYPE_LARGEINT>(3);
from_datetime_test_func<TYPE_LARGEINT>(6);
}
TEST_F(FunctionCastToIntTest, test_from_time) {
from_time_test_func<TYPE_TINYINT>();
from_time_test_func<TYPE_SMALLINT>();
from_time_test_func<TYPE_INT>();
from_time_test_func<TYPE_BIGINT>();
from_time_test_func<TYPE_LARGEINT>();
}
} // namespace doris::vectorized