Merge "Simplify and explain from_varint_to_integer #5031" from Rafael

"
This is the second version of the patch series. The previous one was just the second patch, this one adds more tests an another patch to make it easier to test that the new code has the same behavior as the old one.
"

* 'espindola/overflow-is-intentional' of https://github.com/espindola/scylla:
  types: Simplify and explain from_varint_to_integer
  Add more cast tests
This commit is contained in:
Avi Kivity
2019-09-29 11:27:55 +03:00
2 changed files with 32 additions and 3 deletions

View File

@@ -167,6 +167,31 @@ SEASTAR_TEST_CASE(test_varint_to_bigint) {
});
}
SEASTAR_TEST_CASE(test_varint_to_int) {
return do_with_cql_env_thread([&](auto& e) {
e.execute_cql("CREATE TABLE test (key text primary key, value varint)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k1', 2147483647)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k2', 2147483648)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k3', 4294967295)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k4', 4294967296)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k5', 4294967297)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k6', -1)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k7', -2147483648)").get();
e.execute_cql("INSERT INTO test (key, value) VALUES ('k8', -2147483649)").get();
auto v = e.execute_cql("SELECT key,CAST(value as int) from test").get0();
assert_that(v).is_rows().with_rows_ignore_order({
{{utf8_type->decompose("k1")}, {int32_type->decompose(std::numeric_limits<int32_t>::max())}},
{{utf8_type->decompose("k2")}, {int32_type->decompose(std::numeric_limits<int32_t>::min())}},
{{utf8_type->decompose("k3")}, {int32_type->decompose(int32_t(-1))}},
{{utf8_type->decompose("k4")}, {int32_type->decompose(int32_t(0))}},
{{utf8_type->decompose("k5")}, {int32_type->decompose(int32_t(1))}},
{{utf8_type->decompose("k6")}, {int32_type->decompose(int32_t(-1))}},
{{utf8_type->decompose("k7")}, {int32_type->decompose(std::numeric_limits<int32_t>::min())}},
{{utf8_type->decompose("k8")}, {int32_type->decompose(std::numeric_limits<int32_t>::max())}},
});
});
}
SEASTAR_TEST_CASE(test_numeric_casts_in_selection_clause) {
return do_with_cql_env_thread([&] (auto& e) {
e.execute_cql("CREATE TABLE test (a tinyint primary key,"

View File

@@ -3531,9 +3531,13 @@ static boost::multiprecision::cpp_int from_decimal_to_cppint(const data_value& f
template <typename ToType>
static ToType from_varint_to_integer(const boost::multiprecision::cpp_int& varint) {
bool negative = varint < 0;
uint64_t v = negative ? static_cast<uint64_t>(-varint) : static_cast<uint64_t>(varint);
return static_cast<ToType>(negative ? -v : v);
// The behavior CQL expects on overflow is for values to wrap
// around. For cpp_int conversion functions, the behavior is to
// return the largest or smallest number that the target type can
// represent. To implement one with the other, we first mask the
// low 64 bits, convert to a uint64_t, and then let c++ convert,
// with possible overflow, to ToType.
return static_cast<uint64_t>(~static_cast<uint64_t>(0) & varint);
}
template<typename ToType>