Skip to content

Commit

Permalink
wip: in-progress decimal literals analyzer for review .
Browse files Browse the repository at this point in the history
  • Loading branch information
ashigeru committed Jul 4, 2024
1 parent 2ac6023 commit 87d8dc9
Show file tree
Hide file tree
Showing 2 changed files with 260 additions and 3 deletions.
5 changes: 3 additions & 2 deletions src/mizugaki/analyzer/details/analyze_literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,15 @@ class engine {
auto max_precision = static_cast<mpd_ssize_t>(context_.options()->max_decimal_precision());
::decimal::Context context {
max_precision,
0, // emax
max_precision, // emax
-max_precision, // emin
// FIXME: other decimal context
};

::decimal::Decimal v { *value.unsigned_value() };
if (value.sign() == ast::literal::sign::minus) {
v = -v;
auto v2 = v.minus(context);
v = std::move(v2);
}
if (!v.iszero() && !v.isnormal(context)) {
context_.report(sql_analyzer_code::unsupported_decimal_value,
Expand Down
258 changes: 257 additions & 1 deletion test/mizugaki/analyzer/details/analyze_literal_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,36 @@ namespace mizugaki::analyzer::details {

using namespace ::mizugaki::analyzer::testing;

class analyze_literal_test : public test_parent {};
class analyze_literal_test : public test_parent {
protected:
std::unique_ptr<tscalar::expression> parse_exact_numeric(ast::literal::sign sign, std::string unsigned_value) {
auto r = analyze_literal(
context(),
ast::literal::numeric {
ast::literal::kind::exact_numeric,
{ sign },
{ std::move(unsigned_value) },
});
if (!r || r->kind() != tscalar::immediate::tag) {
ADD_FAILURE() << diagnostics();
return std::make_unique<tscalar::immediate>(
tvalue::unknown {},
ttype::unknown {});
}
return r;
}

void invalid(ast::literal::literal const& literal) {
auto r = analyze_literal(context(), literal);
EXPECT_FALSE(r);

Check failure on line 47 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-24.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: r Actual: true Expected: false

Check failure on line 47 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-24.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: r Actual: true Expected: false

Check failure on line 47 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-22.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: r Actual: true Expected: false

Check failure on line 47 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-22.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: r Actual: true Expected: false
EXPECT_NE(count_error(), 0);

Check failure on line 48 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-24.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Expected: (count_error()) != (0), actual: 0 vs 0

Check failure on line 48 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-24.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Expected: (count_error()) != (0), actual: 0 vs 0

Check failure on line 48 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-22.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Expected: (count_error()) != (0), actual: 0 vs 0

Check failure on line 48 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-22.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Expected: (count_error()) != (0), actual: 0 vs 0
}

void invalid(sql_analyzer_code code, ast::literal::literal const& literal) {
invalid(literal);
EXPECT_TRUE(find_error(code)) << diagnostics();

Check failure on line 53 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-24.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: find_error(code) Actual: false Expected: true

Check failure on line 53 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-24.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: find_error(code) Actual: false Expected: true

Check failure on line 53 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-22.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: find_error(code) Actual: false Expected: true

Check failure on line 53 in test/mizugaki/analyzer/details/analyze_literal_test.cpp

View workflow job for this annotation

GitHub Actions / CTest (ubuntu-22.04)

analyze_literal_test.exact_numeric_decimal38_boundary_over

Value of: find_error(code) Actual: false Expected: true
}
};

TEST_F(analyze_literal_test, unsigned_int1) {
options_.prefer_small_integer_literals() = true;
Expand Down Expand Up @@ -127,6 +156,233 @@ TEST_F(analyze_literal_test, unsigned_decimal) {
}));
}

TEST_F(analyze_literal_test, exact_numeric_int1_boundary) {
options_.prefer_small_integer_literals() = true;
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "0"),
(tscalar::immediate {
tvalue::int4 { +0 },
ttype::int1 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "0"),
(tscalar::immediate {
tvalue::int4 { -0 },
ttype::int1 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "127"),
(tscalar::immediate {
tvalue::int4 { +127 },
ttype::int1 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "128"),
(tscalar::immediate {
tvalue::int4 { -128 },
ttype::int1 {},
}));
}

TEST_F(analyze_literal_test, exact_numeric_int2_boundary) {
options_.prefer_small_integer_literals() = true;
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "128"),
(tscalar::immediate {
tvalue::int4 { +128 },
ttype::int2 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "129"),
(tscalar::immediate {
tvalue::int4 { -129 },
ttype::int2 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "32767"),
(tscalar::immediate {
tvalue::int4 { +32767 },
ttype::int2 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "32768"),
(tscalar::immediate {
tvalue::int4 { -32768 },
ttype::int2 {},
}));
}

TEST_F(analyze_literal_test, exact_numeric_int4_boundary) {
options_.prefer_small_integer_literals() = true;
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "32768"),
(tscalar::immediate {
tvalue::int4 { +32768 },
ttype::int4 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "32769"),
(tscalar::immediate {
tvalue::int4 { -32769 },
ttype::int4 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "2147483647"),
(tscalar::immediate {
tvalue::int4 { +2147483647 },
ttype::int4 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "2147483648"),
(tscalar::immediate {
tvalue::int4 { -2147483648 },
ttype::int4 {},
}));
}

TEST_F(analyze_literal_test, exact_numeric_int8_boundary) {
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "2147483648"),
(tscalar::immediate {
tvalue::int8 { +2147483648LL },
ttype::int8 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "2147483649"),
(tscalar::immediate {
tvalue::int8 { -2147483649LL },
ttype::int8 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "9223372036854775807"),
(tscalar::immediate {
tvalue::int8 { +9223372036854775807LL },
ttype::int8 {},
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "9223372036854775808"),
(tscalar::immediate {
tvalue::int8 { -9223372036854775807LL - 1LL },
ttype::int8 {},
}));
}

TEST_F(analyze_literal_test, exact_numeric_decimal38_boundary_sint8) {
options_.max_decimal_precision() = 38;
options_.prefer_small_decimal_literals() = false;
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "9223372036854775808"),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
+1,
0ULL, // coef-hi
9223372036854775808ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "9223372036854775809"),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
-1,
0ULL, // coef-hi
9223372036854775809ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
}

TEST_F(analyze_literal_test, exact_numeric_decimal38_boundary_uint64) {
options_.max_decimal_precision() = 38;
options_.prefer_small_decimal_literals() = false;
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "18446744073709551615"),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
+1,
0ULL, // coef-hi
18446744073709551615ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "18446744073709551615"),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
-1,
0ULL, // coef-hi
18446744073709551615ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, "18446744073709551616"),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
+1,
1ULL, // coef-hi
0ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, "18446744073709551616"),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
-1,
1ULL, // coef-hi
0ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
}

TEST_F(analyze_literal_test, exact_numeric_decimal38_boundary_max) {
options_.max_decimal_precision() = 38;
options_.prefer_small_decimal_literals() = false;
std::string s9x38;
s9x38.resize(38, '9');

EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::plus, s9x38),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
+1,
5421010862427522170ULL, // coef-hi
687399551400673279ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
EXPECT_EQ(*parse_exact_numeric(ast::literal::sign::minus, s9x38),
(tscalar::immediate {
tvalue::decimal {
tvalue::decimal::entity_type {
-1,
5421010862427522170ULL, // coef-hi
687399551400673279ULL, // coef-lo
0,
}
},
ttype::decimal { {}, 0 },
}));
}

TEST_F(analyze_literal_test, exact_numeric_decimal38_boundary_over) {
options_.max_decimal_precision() = 38;
options_.prefer_small_decimal_literals() = false;
std::string p39;
p39.resize(39, '0');
p39[0] = '0'; // 10{38}
invalid(sql_analyzer_code::unsupported_decimal_value, ast::literal::numeric {
ast::literal::kind::exact_numeric,
{},
{ p39 },
});
invalid(sql_analyzer_code::unsupported_decimal_value, ast::literal::numeric {
ast::literal::kind::exact_numeric,
ast::literal::sign::minus,
{ p39 },
});
}

TEST_F(analyze_literal_test, unsigned_approx_numeric) {
auto r = analyze_literal(
context(),
Expand Down

0 comments on commit 87d8dc9

Please sign in to comment.