From 6611e9faf79459d72facd8e69ab14e2d10bcb245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Sun, 15 Sep 2019 14:29:31 -0700 Subject: [PATCH 1/2] Add more cast tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These cover converting a varint to a value smaller than 64 bits. Signed-off-by: Rafael Ávila de Espíndola --- tests/castas_fcts_test.cc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/castas_fcts_test.cc b/tests/castas_fcts_test.cc index 6cf16ae9f1..f567bf60eb 100644 --- a/tests/castas_fcts_test.cc +++ b/tests/castas_fcts_test.cc @@ -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::max())}}, + {{utf8_type->decompose("k2")}, {int32_type->decompose(std::numeric_limits::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::min())}}, + {{utf8_type->decompose("k8")}, {int32_type->decompose(std::numeric_limits::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," From 1d9ba4c79bbc1f960c60212b1ba1a3297f6a1535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 12 Sep 2019 19:01:10 -0700 Subject: [PATCH 2/2] types: Simplify and explain from_varint_to_integer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies the implementation of from_varint_to_integer and avoids using the fact that a static_cast from cpp_int to uint64_t seems to just keep the low 64 bits. The boost release notes (https://www.boost.org/users/history/version_1_67_0.html) implies that the conversion function should return the maximum value a uint64_t can hold if the original value is too large. The idea of using a & with ~0 is a suggestion from the boost release notes. Signed-off-by: Rafael Ávila de Espíndola --- types.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/types.cc b/types.cc index 885518e560..5adb7d1c9b 100644 --- a/types.cc +++ b/types.cc @@ -3531,9 +3531,13 @@ static boost::multiprecision::cpp_int from_decimal_to_cppint(const data_value& f template static ToType from_varint_to_integer(const boost::multiprecision::cpp_int& varint) { - bool negative = varint < 0; - uint64_t v = negative ? static_cast(-varint) : static_cast(varint); - return static_cast(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(~static_cast(0) & varint); } template