diff --git a/cql3/type_json.cc b/cql3/type_json.cc index 36e3ef8a9f..59b27ad9f0 100644 --- a/cql3/type_json.cc +++ b/cql3/type_json.cc @@ -334,7 +334,8 @@ static sstring to_json_string_aux(const set_type_impl& t, bytes_view bv) { bool first = true; auto sf = cql_serialization_format::internal(); out << '['; - std::for_each(llpdi::begin(bv, sf), llpdi::end(bv, sf), [&first, &out, &t] (bytes_view e) { + managed_bytes_view mbv(bv); + std::for_each(llpdi::begin(mbv, sf), llpdi::end(mbv, sf), [&first, &out, &t] (const managed_bytes_view& e) { if (first) { first = false; } else { @@ -352,7 +353,8 @@ static sstring to_json_string_aux(const list_type_impl& t, bytes_view bv) { bool first = true; auto sf = cql_serialization_format::internal(); out << '['; - std::for_each(llpdi::begin(bv, sf), llpdi::end(bv, sf), [&first, &out, &t] (bytes_view e) { + managed_bytes_view mbv(bv); + std::for_each(llpdi::begin(mbv, sf), llpdi::end(mbv, sf), [&first, &out, &t] (const managed_bytes_view& e) { if (first) { first = false; } else { diff --git a/types.cc b/types.cc index 31d7429b81..a43e6fb228 100644 --- a/types.cc +++ b/types.cc @@ -150,7 +150,7 @@ static const char* empty_type_name = "org.apache.cassandra.db.marshal.EmptyT template struct simple_type_traits { static constexpr size_t serialized_size = sizeof(T); - static T read_nonempty(bytes_view v) { + static T read_nonempty(managed_bytes_view v) { return read_simple_exactly(v); } }; @@ -158,7 +158,7 @@ struct simple_type_traits { template<> struct simple_type_traits { static constexpr size_t serialized_size = 1; - static bool read_nonempty(bytes_view v) { + static bool read_nonempty(managed_bytes_view v) { return read_simple_exactly(v) != 0; } }; @@ -166,7 +166,7 @@ struct simple_type_traits { template<> struct simple_type_traits { static constexpr size_t serialized_size = sizeof(uint64_t); - static db_clock::time_point read_nonempty(bytes_view v) { + static db_clock::time_point read_nonempty(managed_bytes_view v) { return db_clock::time_point(db_clock::duration(read_simple_exactly(v))); } }; @@ -438,7 +438,7 @@ template <> struct int_of_size : template struct float_type_traits { static constexpr size_t serialized_size = sizeof(typename int_of_size::itype); - static double read_nonempty(bytes_view v) { + static double read_nonempty(managed_bytes_view v) { union { T d; typename int_of_size::itype i; @@ -1032,7 +1032,7 @@ map_type_impl::is_value_compatible_with_frozen(const collection_type_impl& previ } int32_t -map_type_impl::compare_maps(data_type keys, data_type values, bytes_view o1, bytes_view o2) { +map_type_impl::compare_maps(data_type keys, data_type values, managed_bytes_view o1, managed_bytes_view o2) { if (o1.empty()) { return o2.empty() ? 0 : -1; } else if (o2.empty()) { @@ -2043,7 +2043,7 @@ template data_value abstract_type::deserialize_impl<>(single_fragmented_view) co template data_value abstract_type::deserialize_impl<>(ser::buffer_view) const; template data_value abstract_type::deserialize_impl<>(managed_bytes_view) const; -int32_t compare_aux(const tuple_type_impl& t, bytes_view v1, bytes_view v2) { +int32_t compare_aux(const tuple_type_impl& t, const managed_bytes_view& v1, const managed_bytes_view& v2) { // This is a slight modification of lexicographical_tri_compare: // when the only difference between the tuples is that one of them has additional trailing nulls, // we consider them equal. For example, in the following CQL scenario: @@ -2097,8 +2097,8 @@ int32_t compare_aux(const tuple_type_impl& t, bytes_view v1, bytes_view v2) { namespace { struct compare_visitor { - bytes_view v1; - bytes_view v2; + managed_bytes_view v1; + managed_bytes_view v2; template int32_t operator()(const simple_type_impl&) { if (v1.empty()) { return v2.empty() ? 0 : -1; @@ -2125,14 +2125,18 @@ struct compare_visitor { if (v2.empty()) { return 1; } - return utils::timeuuid_tri_compare(v1, v2); + return with_linearized(v1, [&] (bytes_view v1) { + return with_linearized(v2, [&] (bytes_view v2) { + return utils::timeuuid_tri_compare(v1, v2); + }); + }); } int32_t operator()(const listlike_collection_type_impl& l) { using llpdi = listlike_partial_deserializing_iterator; auto sf = cql_serialization_format::internal(); return lexicographical_tri_compare(llpdi::begin(v1, sf), llpdi::end(v1, sf), llpdi::begin(v2, sf), llpdi::end(v2, sf), - [&] (bytes_view o1, bytes_view o2) { return l.get_elements_type()->compare(o1, o2); }); + [&] (const managed_bytes_view& o1, const managed_bytes_view& o2) { return l.get_elements_type()->compare(o1, o2); }); } int32_t operator()(const map_type_impl& m) { return map_type_impl::compare_maps(m.get_keys_type(), m.get_values_type(), v1, v2); @@ -2153,7 +2157,11 @@ struct compare_visitor { } if (c1 == 1) { - return utils::uuid_tri_compare_timeuuid(v1, v2); + return with_linearized(v1, [&] (bytes_view v1) { + return with_linearized(v2, [&] (bytes_view v2) { + return utils::uuid_tri_compare_timeuuid(v1, v2); + }); + }); } return compare_unsigned(v1, v2); } @@ -2218,6 +2226,10 @@ struct compare_visitor { } int32_t abstract_type::compare(bytes_view v1, bytes_view v2) const { + return compare(managed_bytes_view(v1), managed_bytes_view(v2)); +} + +int32_t abstract_type::compare(managed_bytes_view v1, managed_bytes_view v2) const { try { return visit(*this, compare_visitor{v1, v2}); } catch (const marshal_exception&) { @@ -2225,15 +2237,6 @@ int32_t abstract_type::compare(bytes_view v1, bytes_view v2) const { } } -int32_t abstract_type::compare(managed_bytes_view v1, managed_bytes_view v2) const { - // FIXME: don't linearize - return with_linearized(v1, [&] (bytes_view v1) { - return with_linearized(v2, [&] (bytes_view v2) { - return compare(v1, v2); - }); - }); -} - bool abstract_type::equal(bytes_view v1, bytes_view v2) const { return ::visit(*this, [&](const auto& t) { if (is_byte_order_equal_visitor{}(t)) { @@ -2244,11 +2247,11 @@ bool abstract_type::equal(bytes_view v1, bytes_view v2) const { } bool abstract_type::equal(managed_bytes_view v1, managed_bytes_view v2) const { - // FIXME: don't linearize - return with_linearized(v1, [&] (bytes_view v1) { - return with_linearized(v2, [&] (bytes_view v2) { - return equal(v1, v2); - }); + return ::visit(*this, [&](const auto& t) { + if (is_byte_order_equal_visitor{}(t)) { + return compare_unsigned(v1, v2) == 0; + } + return compare_visitor{v1, v2}(t) == 0; }); } diff --git a/types/listlike_partial_deserializing_iterator.hh b/types/listlike_partial_deserializing_iterator.hh index 968709f184..c116dc5b2e 100644 --- a/types/listlike_partial_deserializing_iterator.hh +++ b/types/listlike_partial_deserializing_iterator.hh @@ -22,8 +22,9 @@ #pragma once #include -#include "bytes.hh" #include "cql_serialization_format.hh" +#include "utils/fragment_range.hh" +#include "utils/managed_bytes.hh" int read_collection_size(bytes_view& in, cql_serialization_format sf); bytes_view read_collection_value(bytes_view& in, cql_serialization_format sf); @@ -48,18 +49,18 @@ View read_collection_value(View& in, cql_serialization_format sf) { class listlike_partial_deserializing_iterator { public: using iterator_category = std::input_iterator_tag; - using value_type = bytes_view; + using value_type = managed_bytes_view; using difference_type = std::ptrdiff_t; - using pointer = bytes_view*; - using reference = bytes_view&; + using pointer = managed_bytes_view*; + using reference = managed_bytes_view&; private: - bytes_view* _in; + managed_bytes_view* _in; int _remain; - bytes_view _cur; + managed_bytes_view _cur; cql_serialization_format _sf; private: struct end_tag {}; - listlike_partial_deserializing_iterator(bytes_view& in, cql_serialization_format sf) + listlike_partial_deserializing_iterator(managed_bytes_view& in, cql_serialization_format sf) : _in(&in), _sf(sf) { _remain = read_collection_size(*_in, _sf); parse(); @@ -68,7 +69,7 @@ private: : _remain(0), _sf(cql_serialization_format::internal()) { // _sf is bogus, but doesn't matter } public: - bytes_view operator*() const { return _cur; } + managed_bytes_view operator*() const { return _cur; } listlike_partial_deserializing_iterator& operator++() { --_remain; parse(); @@ -84,10 +85,10 @@ public: bool operator!=(const listlike_partial_deserializing_iterator& x) const { return _remain != x._remain; } - static listlike_partial_deserializing_iterator begin(bytes_view& in, cql_serialization_format sf) { + static listlike_partial_deserializing_iterator begin(managed_bytes_view& in, cql_serialization_format sf) { return { in, sf }; } - static listlike_partial_deserializing_iterator end(bytes_view in, cql_serialization_format sf) { + static listlike_partial_deserializing_iterator end(managed_bytes_view in, cql_serialization_format sf) { return { end_tag() }; } private: diff --git a/types/map.hh b/types/map.hh index f17c5e99c2..63eed6bd07 100644 --- a/types/map.hh +++ b/types/map.hh @@ -53,7 +53,7 @@ public: virtual bool is_compatible_with_frozen(const collection_type_impl& previous) const override; virtual bool is_value_compatible_with_frozen(const collection_type_impl& previous) const override; static int32_t compare_maps(data_type keys_comparator, data_type values_comparator, - bytes_view o1, bytes_view o2); + managed_bytes_view o1, managed_bytes_view o2); using abstract_type::deserialize; using collection_type_impl::deserialize; template data_value deserialize(View v, cql_serialization_format sf) const;