Skip to content

Commit

Permalink
Merge pull request #32 from project-tsurugi/error-handling-type
Browse files Browse the repository at this point in the history
fix: better error handling around type analysis.
  • Loading branch information
kuron99 authored Jul 2, 2024
2 parents 5602404 + dd08480 commit 99e4c12
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 6 deletions.
6 changes: 3 additions & 3 deletions include/mizugaki/analyzer/sql_analyzer_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ enum class sql_analyzer_code {
// about types
/// @brief the flexible length or precision is not supported in this type.
flexible_length_is_not_supported,
/// @brief the type length or precision is too large.
type_length_is_too_large,
/// @brief the type length or precision is not valid.
invalid_type_length,
/// @brief the numeric scale is too large for the precision.
invalid_numeric_scale,

Expand Down Expand Up @@ -137,7 +137,7 @@ inline constexpr std::string_view to_string_view(sql_analyzer_code value) noexce
case kind::unsupported_string_value: return "unsupported_string_value"sv;

case kind::flexible_length_is_not_supported: return "flexible_length_is_not_supported"sv;
case kind::type_length_is_too_large: return "type_length_is_too_large"sv;
case kind::invalid_type_length: return "invalid_type_length"sv;
case kind::invalid_numeric_scale: return "invalid_numeric_scale"sv;

case kind::schema_not_found: return "schema_not_found"sv;
Expand Down
48 changes: 45 additions & 3 deletions src/mizugaki/analyzer/details/analyze_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ class engine {
}
} else if (auto len = type.length()) {
size = type.length().value().value();
if (size == 0) {
context_.report(
sql_analyzer_code::invalid_type_length,
"character type must not be empty",
type.length().value().region());
return {};
}
} else if (!type.is_varying()) {
size = 1;
}
Expand All @@ -119,6 +126,13 @@ class engine {
}
} else if (auto len = type.length()) {
size = type.length().value().value();
if (size == 0) {
context_.report(
sql_analyzer_code::invalid_type_length,
"bit type must not be empty",
type.length().value().region());
return {};
}
} else if (!type.is_varying()) {
size = 1;
}
Expand All @@ -145,6 +159,13 @@ class engine {
}
} else if (auto len = type.length()) {
size = type.length().value().value();
if (size == 0) {
context_.report(
sql_analyzer_code::invalid_type_length,
"binary type must not be empty",
type.length().value().region());
return {};
}
} else if (!type.is_varying()) {
size = 1;
}
Expand Down Expand Up @@ -175,9 +196,16 @@ class engine {
scale = **type.scale();
}
}
if (precision && precision == 0) {
context_.report(
sql_analyzer_code::invalid_type_length,
"decimal type precision must not be zero",
type.precision().value().region());
return {};
}
if (precision && precision > options().max_decimal_precision()) {
context_.report(
sql_analyzer_code::type_length_is_too_large,
sql_analyzer_code::invalid_type_length,
string_builder {}
<< "too large decimal precision: " << precision.value()
<< " (max precision is " << options().max_decimal_precision() << ")"
Expand Down Expand Up @@ -210,6 +238,13 @@ class engine {
if (type.is_flexible_precision() || !prec) {
return build(type, ttype::int8 {});
}
if (**prec == 0) {
context_.report(
sql_analyzer_code::invalid_type_length,
"integer type precision must not be zero",
type.precision().value().region());
return {};
}
if (**prec <= options().max_binary_integer1_precision()) {
return build(type, ttype::int1 {});
}
Expand All @@ -223,7 +258,7 @@ class engine {
return build(type, ttype::int8 {});
}
context_.report(
sql_analyzer_code::type_length_is_too_large,
sql_analyzer_code::invalid_type_length,
string_builder {}
<< "too large integer precision: " << **prec
<< " (max precision is " << options().max_binary_integer8_precision() << ")"
Expand All @@ -235,14 +270,21 @@ class engine {
if (type.is_flexible_precision() || !prec) {
return build(type, ttype::float8 {});
}
if (**prec == 0) {
context_.report(
sql_analyzer_code::invalid_type_length,
"float type precision must not be zero",
type.precision().value().region());
return {};
}
if (**prec <= options().max_binary_float4_precision()) {
return build(type, ttype::float4 {});
}
if (**prec <= options().max_binary_float8_precision()) {
return build(type, ttype::float8 {});
}
context_.report(
sql_analyzer_code::type_length_is_too_large,
sql_analyzer_code::invalid_type_length,
string_builder {}
<< "too large float precision: " << **prec
<< " (max precision is " << options().max_binary_float8_precision() << ")"
Expand Down
145 changes: 145 additions & 0 deletions test/mizugaki/analyzer/details/analyze_type_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ TEST_F(analyze_type_test, character_flexible) {
EXPECT_TRUE(find_error(error_code::flexible_length_is_not_supported));
}

TEST_F(analyze_type_test, character_length_zero) {
auto r = analyze_type(
context(),
ast::type::character_string {
ast::type::kind::character,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, character_varying) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -106,6 +117,17 @@ TEST_F(analyze_type_test, character_varying_flexible) {
EXPECT_EQ(*r, (ttype::character { ttype::varying, std::nullopt }));
}

TEST_F(analyze_type_test, character_varying_length_zero) {
auto r = analyze_type(
context(),
ast::type::character_string {
ast::type::kind::character_varying,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, bit) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -138,6 +160,17 @@ TEST_F(analyze_type_test, bit_flexible) {
EXPECT_TRUE(find_error(error_code::flexible_length_is_not_supported));
}

TEST_F(analyze_type_test, bit_length_zero) {
auto r = analyze_type(
context(),
ast::type::bit_string {
ast::type::kind::bit,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, bit_varying) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -170,6 +203,17 @@ TEST_F(analyze_type_test, bit_varying_flexible) {
EXPECT_EQ(*r, (ttype::bit { ttype::varying, std::nullopt }));
}

TEST_F(analyze_type_test, bit_varying_length_zero) {
auto r = analyze_type(
context(),
ast::type::bit_string {
ast::type::kind::bit_varying,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, octet) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -202,6 +246,17 @@ TEST_F(analyze_type_test, octet_flexible) {
EXPECT_TRUE(find_error(error_code::flexible_length_is_not_supported));
}

TEST_F(analyze_type_test, octet_length_zero) {
auto r = analyze_type(
context(),
ast::type::octet_string {
ast::type::kind::octet,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, octet_varying) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -234,6 +289,17 @@ TEST_F(analyze_type_test, octet_varying_flexible) {
EXPECT_EQ(*r, (ttype::octet { ttype::varying, std::nullopt }));
}

TEST_F(analyze_type_test, octet_varying_length_zero) {
auto r = analyze_type(
context(),
ast::type::octet_string {
ast::type::kind::octet_varying,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, numeric) {
options_.default_decimal_precision() = 20;
auto r = analyze_type(
Expand Down Expand Up @@ -315,6 +381,41 @@ TEST_F(analyze_type_test, decimal_flexible_with_scale) {
EXPECT_EQ(*r, (ttype::decimal { {}, 2, }));
}

TEST_F(analyze_type_test, decimal_precision_zero) {
auto r = analyze_type(
context(),
ast::type::decimal {
ast::type::kind::decimal,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, decimal_precision_too_large) {
options_.max_decimal_precision() = 20;
auto r = analyze_type(
context(),
ast::type::decimal {
ast::type::kind::decimal,
21,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, decimal_scale_too_large) {
auto r = analyze_type(
context(),
ast::type::decimal {
ast::type::kind::decimal,
10,
11,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_numeric_scale));
}

TEST_F(analyze_type_test, tiny_integer) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -440,6 +541,28 @@ TEST_F(analyze_type_test, integer_flexible) {
EXPECT_EQ(*r, (ttype::int8 {}));
}

TEST_F(analyze_type_test, binary_numeric_length_zero) {
auto r = analyze_type(
context(),
ast::type::binary_numeric {
ast::type::kind::binary_integer,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, binary_numeric_length_too_large) {
auto r = analyze_type(
context(),
ast::type::binary_numeric {
ast::type::kind::binary_integer,
options_.max_binary_integer8_precision() + 1,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, float_single) {
auto r = analyze_type(
context(),
Expand Down Expand Up @@ -473,6 +596,28 @@ TEST_F(analyze_type_test, float_flexible) {
EXPECT_EQ(*r, (ttype::float8 {}));
}

TEST_F(analyze_type_test, binary_float_length_zero) {
auto r = analyze_type(
context(),
ast::type::binary_numeric {
ast::type::kind::binary_float,
0,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, binary_float_length_too_large) {
auto r = analyze_type(
context(),
ast::type::binary_numeric {
ast::type::kind::binary_float,
options_.max_binary_float8_precision() + 1,
});
EXPECT_FALSE(r);
EXPECT_TRUE(find_error(sql_analyzer_code::invalid_type_length));
}

TEST_F(analyze_type_test, boolean) {
auto r = analyze_type(
context(),
Expand Down

0 comments on commit 99e4c12

Please sign in to comment.