diff --git a/compound.hh b/compound.hh index 72565c64d1..d3079af72c 100644 --- a/compound.hh +++ b/compound.hh @@ -159,7 +159,7 @@ public: } return ::serialize_value(*this, values); } - bytes serialize_value_deep(const std::vector& values) { + bytes serialize_value_deep(const std::vector& values) { // TODO: Optimize std::vector partial; partial.reserve(values.size()); diff --git a/cql3/attributes.cc b/cql3/attributes.cc index ad857a000a..246cfeaf18 100644 --- a/cql3/attributes.cc +++ b/cql3/attributes.cc @@ -80,7 +80,7 @@ int64_t attributes::get_timestamp(int64_t now, const query_options& options) { } catch (marshal_exception e) { throw exceptions::invalid_request_exception("Invalid timestamp value"); } - return boost::any_cast(data_type_for()->deserialize(*tval)); + return value_cast(data_type_for()->deserialize(*tval)); } int32_t attributes::get_time_to_live(const query_options& options) { @@ -99,7 +99,7 @@ int32_t attributes::get_time_to_live(const query_options& options) { throw exceptions::invalid_request_exception("Invalid TTL value"); } - auto ttl = boost::any_cast(data_type_for()->deserialize(*tval)); + auto ttl = value_cast(data_type_for()->deserialize(*tval)); if (ttl < 0) { throw exceptions::invalid_request_exception("A TTL must be greater or equal to 0"); } diff --git a/cql3/functions/aggregate_fcts.hh b/cql3/functions/aggregate_fcts.hh index 40aa11eca8..9fbc08c6af 100644 --- a/cql3/functions/aggregate_fcts.hh +++ b/cql3/functions/aggregate_fcts.hh @@ -90,7 +90,7 @@ public: if (!values[0]) { return; } - _sum += boost::any_cast(data_type_for()->deserialize(*values[0])); + _sum += value_cast(data_type_for()->deserialize(*values[0])); } }; @@ -132,7 +132,7 @@ public: return; } ++_count; - _sum += boost::any_cast(data_type_for()->deserialize(*values[0])); + _sum += value_cast(data_type_for()->deserialize(*values[0])); } }; @@ -169,7 +169,7 @@ public: if (!values[0]) { return; } - auto val = boost::any_cast(data_type_for()->deserialize(*values[0])); + auto val = value_cast(data_type_for()->deserialize(*values[0])); if (!_max) { _max = val; } else { @@ -216,7 +216,7 @@ public: if (!values[0]) { return; } - auto val = boost::any_cast(data_type_for()->deserialize(*values[0])); + auto val = value_cast(data_type_for()->deserialize(*values[0])); if (!_min) { _min = val; } else { diff --git a/cql3/functions/time_uuid_fcts.hh b/cql3/functions/time_uuid_fcts.hh index bbc7d032a1..a8103ac8f9 100644 --- a/cql3/functions/time_uuid_fcts.hh +++ b/cql3/functions/time_uuid_fcts.hh @@ -71,10 +71,10 @@ make_min_timeuuid_fct() { return {}; } auto ts_obj = timestamp_type->deserialize(*bb); - if (ts_obj.empty()) { + if (ts_obj.is_null()) { return {}; } - auto ts = boost::any_cast(ts_obj); + auto ts = value_cast(ts_obj); auto uuid = utils::UUID_gen::min_time_UUID(ts.time_since_epoch().count()); return {timeuuid_type->decompose(uuid)}; }); @@ -91,10 +91,10 @@ make_max_timeuuid_fct() { return {}; } auto ts_obj = timestamp_type->deserialize(*bb); - if (ts_obj.empty()) { + if (ts_obj.is_null()) { return {}; } - auto ts = boost::any_cast(ts_obj); + auto ts = value_cast(ts_obj); auto uuid = utils::UUID_gen::max_time_UUID(ts.time_since_epoch().count()); return {timeuuid_type->decompose(uuid)}; }); diff --git a/cql3/functions/uuid_fcts.hh b/cql3/functions/uuid_fcts.hh index d9792a56d7..da0ba783d9 100644 --- a/cql3/functions/uuid_fcts.hh +++ b/cql3/functions/uuid_fcts.hh @@ -54,7 +54,7 @@ shared_ptr make_uuid_fct() { return make_native_scalar_function("uuid", uuid_type, {}, [] (serialization_format sf, const std::vector& parameters) -> bytes_opt { - return {uuid_type->decompose(boost::any(utils::make_random_uuid()))}; + return {uuid_type->decompose(utils::make_random_uuid())}; }); } diff --git a/cql3/lists.cc b/cql3/lists.cc index 845b8240fc..375c322c91 100644 --- a/cql3/lists.cc +++ b/cql3/lists.cc @@ -113,12 +113,12 @@ lists::value::from_serialized(bytes_view v, list_type type, serialization_format // Collections have this small hack that validate cannot be called on a serialized object, // but compose does the validation (so we're fine). // FIXME: deserializeForNativeProtocol()?! - auto l = boost::any_cast(type->deserialize(v, sf)); + auto l = value_cast(type->deserialize(v, sf)); std::vector elements; elements.reserve(l.size()); for (auto&& element : l) { // elements can be null in lists that represent a set of IN values - elements.push_back(element.empty() ? bytes_opt() : bytes_opt(type->get_elements_type()->decompose(element))); + elements.push_back(element.is_null() ? bytes_opt() : bytes_opt(type->get_elements_type()->decompose(element))); } return value(std::move(elements)); } catch (marshal_exception& e) { diff --git a/cql3/maps.cc b/cql3/maps.cc index be698998a6..0f43a204ec 100644 --- a/cql3/maps.cc +++ b/cql3/maps.cc @@ -161,7 +161,7 @@ maps::value::from_serialized(bytes_view value, map_type type, serialization_form // Collections have this small hack that validate cannot be called on a serialized object, // but compose does the validation (so we're fine). // FIXME: deserialize_for_native_protocol?! - auto m = boost::any_cast(type->deserialize(value, sf)); + auto m = value_cast(type->deserialize(value, sf)); std::map map(type->get_keys_type()->as_less_comparator()); for (auto&& e : m) { map.emplace(type->get_keys_type()->decompose(e.first), diff --git a/cql3/query_processor.cc b/cql3/query_processor.cc index 1e5357f205..267077ecaf 100644 --- a/cql3/query_processor.cc +++ b/cql3/query_processor.cc @@ -302,7 +302,7 @@ query_processor::parse_statement(const sstring_view& query) query_options query_processor::make_internal_options( ::shared_ptr p, - const std::initializer_list& values) { + const std::initializer_list& values) { if (p->bound_names.size() != values.size()) { throw std::invalid_argument(sprint("Invalid number of values. Expecting %d but got %d", p->bound_names.size(), values.size())); } @@ -310,9 +310,9 @@ query_options query_processor::make_internal_options( std::vector bound_values; for (auto& v : values) { auto& n = *ni++; - if (v.type() == typeid(bytes)) { - bound_values.push_back({boost::any_cast(v)}); - } else if (v.empty()) { + if (v.type() == bytes_type) { + bound_values.push_back({value_cast(v)}); + } else if (v.is_null()) { bound_values.push_back({}); } else { bound_values.push_back({n->type->decompose(v)}); @@ -335,7 +335,7 @@ query_options query_processor::make_internal_options( future<::shared_ptr> query_processor::execute_internal( const std::experimental::string_view& query_string, - const std::initializer_list& values) { + const std::initializer_list& values) { auto p = prepare_internal(query_string); auto opts = make_internal_options(p, values); return do_with(std::move(opts), diff --git a/cql3/query_processor.hh b/cql3/query_processor.hh index ea7f8270cb..af5410a545 100644 --- a/cql3/query_processor.hh +++ b/cql3/query_processor.hh @@ -323,12 +323,12 @@ public: #endif private: ::shared_ptr prepare_internal(const std::experimental::string_view& query); - query_options make_internal_options(::shared_ptr, const std::initializer_list&); + query_options make_internal_options(::shared_ptr, const std::initializer_list&); public: future<::shared_ptr> execute_internal( const std::experimental::string_view& query_string, - const std::initializer_list& = { }); + const std::initializer_list& = { }); /* * This function provides a timestamp that is guaranteed to be higher than any timestamp diff --git a/cql3/sets.cc b/cql3/sets.cc index f531b0bac1..a940331173 100644 --- a/cql3/sets.cc +++ b/cql3/sets.cc @@ -125,7 +125,7 @@ sets::value::from_serialized(bytes_view v, set_type type, serialization_format s // Collections have this small hack that validate cannot be called on a serialized object, // but compose does the validation (so we're fine). // FIXME: deserializeForNativeProtocol?! - auto s = boost::any_cast(type->deserialize(v, sf)); + auto s = value_cast(type->deserialize(v, sf)); std::set elements(type->get_elements_type()->as_less_comparator()); for (auto&& element : s) { elements.insert(elements.end(), type->get_elements_type()->decompose(element)); diff --git a/cql3/statements/select_statement.cc b/cql3/statements/select_statement.cc index b7012e235a..165d3caad4 100644 --- a/cql3/statements/select_statement.cc +++ b/cql3/statements/select_statement.cc @@ -160,7 +160,7 @@ int32_t select_statement::get_limit(const query_options& options) const { try { int32_type->validate(*val); - auto l = boost::any_cast(int32_type->deserialize(*val)); + auto l = value_cast(int32_type->deserialize(*val)); if (l <= 0) { throw exceptions::invalid_request_exception("LIMIT must be strictly positive"); } diff --git a/cql3/tuples.hh b/cql3/tuples.hh index cf606b74bd..de226b663a 100644 --- a/cql3/tuples.hh +++ b/cql3/tuples.hh @@ -259,7 +259,7 @@ public: try { // Collections have this small hack that validate cannot be called on a serialized object, // but the deserialization does the validation (so we're fine). - auto l = boost::any_cast(type->deserialize(value, options.get_serialization_format())); + auto l = value_cast(type->deserialize(value, options.get_serialization_format())); auto ttype = dynamic_pointer_cast(type->get_elements_type()); assert(ttype); diff --git a/cql3/untyped_result_set.hh b/cql3/untyped_result_set.hh index 3bbe5079ed..768ba34f72 100644 --- a/cql3/untyped_result_set.hh +++ b/cql3/untyped_result_set.hh @@ -66,7 +66,7 @@ public: } template T get_as(const sstring& name) const { - return boost::any_cast(data_type_for()->deserialize(get_blob(name))); + return value_cast(data_type_for()->deserialize(get_blob(name))); } // this could maybe be done as an overload of get_as (or something), but that just // muddles things for no real gain. Let user (us) attempt to know what he is doing instead. @@ -75,12 +75,12 @@ public: data_type_for(), data_type valtype = data_type_for()) const { auto vec = - boost::any_cast( + value_cast( map_type_impl::get_instance(keytype, valtype, false)->deserialize( get_blob(name))); std::transform(vec.begin(), vec.end(), out, [](auto& p) { - return std::pair(boost::any_cast(p.first), boost::any_cast(p.second)); + return std::pair(value_cast(p.first), value_cast(p.second)); }); } template diff --git a/db/config.cc b/db/config.cc index ce0d117803..e09ce03af7 100644 --- a/db/config.cc +++ b/db/config.cc @@ -31,6 +31,7 @@ #include "core/fstream.hh" #include "core/do_with.hh" #include "log.hh" +#include static logging::logger logger("config"); diff --git a/db/query_context.hh b/db/query_context.hh index 73b13530a7..8c4386bceb 100644 --- a/db/query_context.hh +++ b/db/query_context.hh @@ -42,7 +42,7 @@ struct query_context { future<::shared_ptr> execute_cql(sstring text, sstring cf, Args&&... args) { // FIXME: Would be better not to use sprint here. sstring req = sprint(text, cf); - return this->_qp.local().execute_internal(req, { boost::any(std::forward(args))... }); + return this->_qp.local().execute_internal(req, { data_value(std::forward(args))... }); } database& db() { return _db.local(); diff --git a/db/schema_tables.cc b/db/schema_tables.cc index 4f59b8fa57..ab830bc4a3 100644 --- a/db/schema_tables.cc +++ b/db/schema_tables.cc @@ -329,7 +329,7 @@ future calculate_schema_digest(distributed& std::vector results; for (auto&& p : rs->partitions()) { auto mut = p.mut().unfreeze(s); - auto partition_key = boost::any_cast(utf8_type->deserialize(mut.key().get_component(*s, 0))); + auto partition_key = value_cast(utf8_type->deserialize(mut.key().get_component(*s, 0))); if (partition_key == system_keyspace::NAME) { continue; } @@ -368,7 +368,7 @@ future> convert_schema_to_mutations(distributed results; for (auto&& p : rs->partitions()) { auto mut = p.mut().unfreeze(s); - auto partition_key = boost::any_cast(utf8_type->deserialize(mut.key().get_component(*s, 0))); + auto partition_key = value_cast(utf8_type->deserialize(mut.key().get_component(*s, 0))); if (partition_key == system_keyspace::NAME) { continue; } @@ -468,7 +468,7 @@ future<> do_merge_schema(distributed& proxy, std::vector std::set keyspaces; std::set column_families; for (auto&& mutation : mutations) { - keyspaces.emplace(boost::any_cast(utf8_type->deserialize(mutation.key().get_component(*s, 0)))); + keyspaces.emplace(value_cast(utf8_type->deserialize(mutation.key().get_component(*s, 0)))); column_families.emplace(mutation.column_family_id()); } diff --git a/db/system_keyspace.cc b/db/system_keyspace.cc index 7ab1c04adf..9024e51a31 100644 --- a/db/system_keyspace.cc +++ b/db/system_keyspace.cc @@ -540,10 +540,11 @@ future<> save_truncation_records(const column_family& cf, db_clock::time_point t out.write(truncated_at.time_since_epoch().count()); map_type_impl::native_type tmp; - tmp.emplace_back(boost::any{ cf.schema()->id() }, boost::any{ buf }); + tmp.emplace_back(cf.schema()->id(), buf); + auto map_type = map_type_impl::get_instance(uuid_type, bytes_type, true); sstring req = sprint("UPDATE system.%s SET truncated_at = truncated_at + ? WHERE key = '%s'", LOCAL, LOCAL); - return qctx->qp().execute_internal(req, {tmp}).then([](auto rs) { + return qctx->qp().execute_internal(req, {make_map_value(map_type, tmp)}).then([](auto rs) { truncation_records = {}; return force_blocking_flush(LOCAL); }); @@ -633,7 +634,7 @@ future get_truncated_at(utils::UUID cf_id) { set_type_impl::native_type prepare_tokens(std::unordered_set& tokens) { set_type_impl::native_type tset; for (auto& t: tokens) { - tset.push_back(boost::any(dht::global_partitioner().to_sstring(t))); + tset.push_back(dht::global_partitioner().to_sstring(t)); } return tset; } @@ -641,7 +642,7 @@ set_type_impl::native_type prepare_tokens(std::unordered_set& tokens std::unordered_set decode_tokens(set_type_impl::native_type& tokens) { std::unordered_set tset; for (auto& t: tokens) { - auto str = boost::any_cast(t); + auto str = value_cast(t); assert(str == dht::global_partitioner().to_sstring(dht::global_partitioner().from_sstring(str))); tset.insert(dht::global_partitioner().from_sstring(str)); } @@ -658,7 +659,8 @@ future<> update_tokens(gms::inet_address ep, std::unordered_set toke } sstring req = "INSERT INTO system.%s (peer, tokens) VALUES (?, ?)"; - return execute_cql(req, PEERS, ep.addr(), prepare_tokens(tokens)).discard_result().then([] { + auto set_type = set_type_impl::get_instance(utf8_type, true); + return execute_cql(req, PEERS, ep.addr(), make_set_value(set_type, prepare_tokens(tokens))).discard_result().then([] { return force_blocking_flush(PEERS); }); } @@ -689,7 +691,7 @@ future>> lo auto blob = row.get_blob("tokens"); auto cdef = peers()->get_column_definition("tokens"); auto deserialized = cdef->type->deserialize(blob); - auto tokens = boost::any_cast(deserialized); + auto tokens = value_cast(deserialized); ret->emplace(peer, decode_tokens(tokens)); } @@ -808,7 +810,8 @@ future<> update_tokens(std::unordered_set tokens) { } sstring req = "INSERT INTO system.%s (key, tokens) VALUES (?, ?)"; - return execute_cql(req, LOCAL, sstring(LOCAL), prepare_tokens(tokens)).discard_result().then([] { + auto set_type = set_type_impl::get_instance(utf8_type, true); + return execute_cql(req, LOCAL, sstring(LOCAL), make_set_value(set_type, prepare_tokens(tokens))).discard_result().then([] { return force_blocking_flush(LOCAL); }); } @@ -862,7 +865,7 @@ future> get_saved_tokens() { auto blob = msg->one().get_blob("tokens"); auto cdef = local()->get_column_definition("tokens"); auto deserialized = cdef->type->deserialize(blob); - auto tokens = boost::any_cast(deserialized); + auto tokens = value_cast(deserialized); return make_ready_future>(decode_tokens(tokens)); }); diff --git a/keys.hh b/keys.hh index 7854328e19..25919a9828 100644 --- a/keys.hh +++ b/keys.hh @@ -152,7 +152,7 @@ public: return TopLevel::from_bytes(get_compound_type(s)->serialize_optionals(v)); } - static TopLevel from_deeply_exploded(const schema& s, const std::vector& v) { + static TopLevel from_deeply_exploded(const schema& s, const std::vector& v) { return TopLevel::from_bytes(get_compound_type(s)->serialize_value_deep(v)); } diff --git a/mutation.cc b/mutation.cc index 7560459a76..8715f9768e 100644 --- a/mutation.cc +++ b/mutation.cc @@ -49,7 +49,7 @@ void mutation::set_static_cell(const column_definition& def, atomic_cell_or_coll partition().static_row().apply(def, std::move(value)); } -void mutation::set_static_cell(const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl) { +void mutation::set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl) { auto column_def = schema()->get_column_definition(name); if (!column_def) { throw std::runtime_error(sprint("no column definition found for '%s'", name)); @@ -65,7 +65,7 @@ void mutation::set_clustered_cell(const exploded_clustering_prefix& prefix, cons row.apply(def, std::move(value)); } -void mutation::set_clustered_cell(const clustering_key& key, const bytes& name, const boost::any& value, +void mutation::set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl) { auto column_def = schema()->get_column_definition(name); if (!column_def) { @@ -79,7 +79,7 @@ void mutation::set_clustered_cell(const clustering_key& key, const column_defini row.apply(def, std::move(value)); } -void mutation::set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const boost::any& value, +void mutation::set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl) { auto column_def = schema()->get_column_definition(name); if (!column_def) { diff --git a/mutation.hh b/mutation.hh index 0e9dd730c0..b04d994eb8 100644 --- a/mutation.hh +++ b/mutation.hh @@ -64,11 +64,11 @@ public: mutation& operator=(mutation&& x) = default; void set_static_cell(const column_definition& def, atomic_cell_or_collection&& value); - void set_static_cell(const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {}); + void set_static_cell(const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {}); void set_clustered_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value); - void set_clustered_cell(const clustering_key& key, const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {}); + void set_clustered_cell(const clustering_key& key, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {}); void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection&& value); - void set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const boost::any& value, api::timestamp_type timestamp, ttl_opt ttl = {}); + void set_cell(const exploded_clustering_prefix& prefix, const bytes& name, const data_value& value, api::timestamp_type timestamp, ttl_opt ttl = {}); void set_cell(const exploded_clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection&& value); std::experimental::optional get_cell(const clustering_key& rkey, const column_definition& def) const; const partition_key& key() const { return _ptr->_dk._key; }; diff --git a/query-result-set.cc b/query-result-set.cc index 675ed12985..3e2c94b332 100644 --- a/query-result-set.cc +++ b/query-result-set.cc @@ -51,7 +51,7 @@ private: std::ostream& operator<<(std::ostream& out, const result_set_row& row) { for (auto&& cell : row._cells) { auto&& type = cell.second.type(); - auto&& value = cell.second.value(); + auto&& value = cell.second; out << cell.first << "=\"" << type->to_string(type->decompose(value)) << "\" "; } return out; diff --git a/query-result-set.hh b/query-result-set.hh index 7c6bd897e9..48f701076c 100644 --- a/query-result-set.hh +++ b/query-result-set.hh @@ -30,8 +30,6 @@ #include #include -#include - namespace query { class no_such_column : public std::runtime_error { @@ -70,11 +68,11 @@ public: template std::experimental::optional get(const sstring& column_name) const throw (no_such_column) { - auto&& value = get_data_value(column_name).value(); - if (value.empty()) { + auto&& value = get_data_value(column_name); + if (value.is_null()) { return std::experimental::nullopt; } - return std::experimental::optional{boost::any_cast(value)}; + return std::experimental::optional{value_cast(value)}; } template T get_nonnull(const sstring& column_name) const throw (no_such_column, null_column_value) { diff --git a/sstables/key.cc b/sstables/key.cc index aee1cff9f8..a5f65cc501 100644 --- a/sstables/key.cc +++ b/sstables/key.cc @@ -53,11 +53,11 @@ public: _it++; } - inline size_t serialized_size(const boost::any& value) { + inline size_t serialized_size(const data_value& value) { return (*_it)->serialized_size(value); } - inline void serialize(const boost::any& value, bytes::iterator& out) { + inline void serialize(const data_value& value, bytes::iterator& out) { (*_it)->serialize(value, out); } }; @@ -121,7 +121,7 @@ bytes from_components(Iterator begin, Iterator end, Serializer&& serializer, boo return b; } -key key::from_deeply_exploded(const schema& s, const std::vector& v) { +key key::from_deeply_exploded(const schema& s, const std::vector& v) { auto &pt = s.partition_key_type()->types(); bool composite = pt.size() > 1; return from_components(v.begin(), v.end(), internal_serializer(pt), composite); diff --git a/sstables/key.hh b/sstables/key.hh index e3fb40fb38..9a71ff8c08 100644 --- a/sstables/key.hh +++ b/sstables/key.hh @@ -22,7 +22,6 @@ #pragma once #include "bytes.hh" #include "schema.hh" -#include #include "core/future.hh" class partition_key; @@ -91,7 +90,7 @@ public: key(bytes&& b) : _kind(kind::regular), _bytes(std::move(b)) {} key(kind k) : _kind(k) {} static key from_bytes(bytes b) { return key(std::move(b)); } - static key from_deeply_exploded(const schema& s, const std::vector& v); + static key from_deeply_exploded(const schema& s, const std::vector& v); static key from_exploded(const schema& s, const std::vector& v); static key from_exploded(const schema& s, std::vector&& v); // Unfortunately, the _bytes field for the partition_key are not public. We can't move. diff --git a/tests/cql_query_test.cc b/tests/cql_query_test.cc index 0753513571..bb73db111e 100644 --- a/tests/cql_query_test.cc +++ b/tests/cql_query_test.cc @@ -566,7 +566,7 @@ SEASTAR_TEST_CASE(test_partition_range_queries_with_bounds) { BOOST_REQUIRE(row[0]); BOOST_REQUIRE(row[1]); keys.push_back(*row[0]); - tokens.push_back(boost::any_cast(long_type->deserialize(*row[1]))); + tokens.push_back(value_cast(long_type->deserialize(*row[1]))); } BOOST_REQUIRE(keys.size() == 5); @@ -705,35 +705,39 @@ SEASTAR_TEST_CASE(test_deletion_scenarios) { SEASTAR_TEST_CASE(test_map_insert_update) { return do_with_cql_env([] (auto& e) { - return e.create_table([](auto ks_name) { + auto make_my_map_type = [] { return map_type_impl::get_instance(int32_type, int32_type, true); }; + auto my_map_type = make_my_map_type(); + return e.create_table([make_my_map_type] (auto ks_name) { // CQL: create table cf (p1 varchar primary key, map1 map); - auto my_map_type = map_type_impl::get_instance(int32_type, int32_type, true); return schema({}, ks_name, "cf", - {{"p1", utf8_type}}, {}, {{"map1", my_map_type}}, {}, utf8_type); + {{"p1", utf8_type}}, {}, {{"map1", make_my_map_type()}}, {}, utf8_type); }).then([&e] { return e.execute_cql("insert into cf (p1, map1) values ('key1', { 1001: 2001 });").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{1001, 2001}})); + "map1", make_map_value(my_map_type, map_type_impl::native_type({{1001, 2001}}))); }).then([&e] { return e.execute_cql("update cf set map1[1002] = 2002 where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{1001, 2001}, - {1002, 2002}})); + "map1", make_map_value(my_map_type, + map_type_impl::native_type({{1001, 2001}, + {1002, 2002}}))); }).then([&e] { // overwrite an element return e.execute_cql("update cf set map1[1001] = 3001 where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{1001, 3001}, - {1002, 2002}})); + "map1", make_map_value(my_map_type, + map_type_impl::native_type({{1001, 3001}, + {1002, 2002}}))); }).then([&e] { // overwrite whole map return e.execute_cql("update cf set map1 = {1003: 4003} where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{1003, 4003}})); + "map1", make_map_value(my_map_type, + map_type_impl::native_type({{1003, 4003}}))); }).then([&e] { // overwrite whole map, but bad syntax return e.execute_cql("update cf set map1 = {1003, 4003} where p1 = 'key1';"); @@ -744,25 +748,26 @@ SEASTAR_TEST_CASE(test_map_insert_update) { // overwrite whole map return e.execute_cql( "update cf set map1 = {1001: 5001, 1002: 5002, 1003: 5003} where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{1001, 5001}, + "map1", make_map_value(my_map_type, + map_type_impl::native_type({{1001, 5001}, {1002, 5002}, - {1003, 5003}})); + {1003, 5003}}))); }).then([&e] { // discard some keys return e.execute_cql("update cf set map1 = map1 - {1001, 1003, 1005} where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{{1002, 5002}}})); - }).then([&e] { - return e.execute_cql("select * from cf where p1 = 'key1';").then([](auto msg) { - auto my_map_type = map_type_impl::get_instance(int32_type, int32_type, true); + "map1", make_map_value(my_map_type, + map_type_impl::native_type({{{1002, 5002}}}))); + }).then([&e, my_map_type] { + return e.execute_cql("select * from cf where p1 = 'key1';").then([my_map_type](auto msg) { assert_that(msg).is_rows() .with_size(1) .with_row({ {utf8_type->decompose(sstring("key1"))}, - {my_map_type->decompose(map_type_impl::native_type{{{1002, 5002}}})}, + {my_map_type->decompose(make_map_value(my_map_type, map_type_impl::native_type{{{1002, 5002}}}))}, }); }); }).then([&e] { @@ -771,133 +776,134 @@ SEASTAR_TEST_CASE(test_map_insert_update) { }).then([&e] { // delete a key return e.execute_cql("delete map1[1002] from cf where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({{{1009, 5009}}})); + "map1", make_map_value(my_map_type, + map_type_impl::native_type({{{1009, 5009}}}))); }).then([&e] { return e.execute_cql("insert into cf (p1, map1) values ('key1', null);").discard_result(); - }).then([&e] { + }).then([&e, my_map_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "map1", map_type_impl::native_type({})); + "map1", make_map_value(my_map_type, map_type_impl::native_type({}))); }); }); } SEASTAR_TEST_CASE(test_set_insert_update) { return do_with_cql_env([] (auto&e) { - return e.create_table([](auto ks_name) { + auto make_my_set_type = [] { return set_type_impl::get_instance(int32_type, true); }; + auto my_set_type = make_my_set_type(); + return e.create_table([make_my_set_type](auto ks_name) { // CQL: create table cf (p1 varchar primary key, set1 set); - auto my_set_type = set_type_impl::get_instance(int32_type, true); return schema({}, ks_name, "cf", - {{"p1", utf8_type}}, {}, {{"set1", my_set_type}}, {}, utf8_type); + {{"p1", utf8_type}}, {}, {{"set1", make_my_set_type()}}, {}, utf8_type); }).then([&e] { return e.execute_cql("insert into cf (p1, set1) values ('key1', { 1001 });").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({1001})); + "set1", make_set_value(my_set_type, set_type_impl::native_type({1001}))); }).then([&e] { return e.execute_cql("update cf set set1 = set1 + { 1002 } where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({1001, 1002})); + "set1", make_set_value(my_set_type, set_type_impl::native_type({1001, 1002}))); }).then([&e] { // overwrite an element return e.execute_cql("update cf set set1 = set1 + { 1001 } where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({1001, 1002})); + "set1", make_set_value(my_set_type, set_type_impl::native_type({1001, 1002}))); }).then([&e] { // overwrite entire set return e.execute_cql("update cf set set1 = { 1007, 1019 } where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({1007, 1019})); + "set1", make_set_value(my_set_type, set_type_impl::native_type({1007, 1019}))); }).then([&e] { // discard keys return e.execute_cql("update cf set set1 = set1 - { 1007, 1008 } where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({1019})); - }).then([&e] { - return e.execute_cql("select * from cf where p1 = 'key1';").then([](auto msg) { - auto my_set_type = set_type_impl::get_instance(int32_type, true); + "set1", make_set_value(my_set_type, set_type_impl::native_type({1019}))); + }).then([&e, my_set_type] { + return e.execute_cql("select * from cf where p1 = 'key1';").then([my_set_type](auto msg) { assert_that(msg).is_rows() .with_size(1) .with_row({ {utf8_type->decompose(sstring("key1"))}, - {my_set_type->decompose(set_type_impl::native_type{{1019}})}, + {my_set_type->decompose(make_set_value(my_set_type, set_type_impl::native_type{{1019}}))}, }); }); }).then([&e] { return e.execute_cql("update cf set set1 = set1 + { 1009 } where p1 = 'key1';").discard_result(); }).then([&e] { return e.execute_cql("delete set1[1019] from cf where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({1009})); + "set1", make_set_value(my_set_type, set_type_impl::native_type({1009}))); }).then([&e] { return e.execute_cql("insert into cf (p1, set1) values ('key1', null);").discard_result(); - }).then([&e] { + }).then([&e, my_set_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "set1", set_type_impl::native_type({})); + "set1", make_set_value(my_set_type, set_type_impl::native_type({}))); }); }); } SEASTAR_TEST_CASE(test_list_insert_update) { return do_with_cql_env([] (auto& e) { + auto my_list_type = list_type_impl::get_instance(int32_type, true); return e.execute_cql("create table cf (p1 varchar primary key, list1 list);").discard_result().then([&e] { return e.execute_cql("insert into cf (p1, list1) values ('key1', [ 1001 ]);").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({boost::any(1001)})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({1001}))); }).then([&e] { return e.execute_cql("update cf set list1 = [ 1002, 1003 ] where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({boost::any(1002), boost::any(1003)})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({1002, 1003}))); }).then([&e] { return e.execute_cql("update cf set list1[1] = 2003 where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({boost::any(1002), boost::any(2003)})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({1002, 2003}))); }).then([&e] { return e.execute_cql("update cf set list1 = list1 - [1002, 2004] where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({2003})); - }).then([&e] { - return e.execute_cql("select * from cf where p1 = 'key1';").then([] (auto msg) { - auto my_list_type = list_type_impl::get_instance(int32_type, true); + "list1", make_list_value(my_list_type, list_type_impl::native_type({2003}))); + }).then([&e, my_list_type] { + return e.execute_cql("select * from cf where p1 = 'key1';").then([my_list_type] (auto msg) { assert_that(msg).is_rows() .with_size(1) .with_row({ {utf8_type->decompose(sstring("key1"))}, - {my_list_type->decompose(list_type_impl::native_type{{2003}})}, + {my_list_type->decompose(make_list_value(my_list_type, list_type_impl::native_type{{2003}}))}, }); }); }).then([&e] { return e.execute_cql("update cf set list1 = [2008, 2009, 2010] where p1 = 'key1';").discard_result(); }).then([&e] { return e.execute_cql("delete list1[1] from cf where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({2008, 2010})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({2008, 2010}))); }).then([&e] { return e.execute_cql("update cf set list1 = list1 + [2012, 2019] where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({2008, 2010, 2012, 2019})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({2008, 2010, 2012, 2019}))); }).then([&e] { return e.execute_cql("update cf set list1 = [2001, 2002] + list1 where p1 = 'key1';").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({2001, 2002, 2008, 2010, 2012, 2019})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({2001, 2002, 2008, 2010, 2012, 2019}))); }).then([&e] { return e.execute_cql("insert into cf (p1, list1) values ('key1', null);").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.require_column_has_value("cf", {sstring("key1")}, {}, - "list1", list_type_impl::native_type({})); + "list1", make_list_value(my_list_type, list_type_impl::native_type({}))); }); }); } @@ -1028,7 +1034,7 @@ SEASTAR_TEST_CASE(test_tuples) { }).then([&e, tt] (shared_ptr msg) { assert_that(msg).is_rows() .with_rows({{ - {tt->decompose(tuple_type_impl::native_type({int32_t(1001), int64_t(2001), sstring("abc1")}))}, + {tt->decompose(make_tuple_value(tt, tuple_type_impl::native_type({int32_t(1001), int64_t(2001), sstring("abc1")})))}, }}); return e.execute_cql("create table cf2 (p1 int PRIMARY KEY, r1 tuple)").discard_result(); }).then([&e] { @@ -1037,7 +1043,7 @@ SEASTAR_TEST_CASE(test_tuples) { return e.execute_cql("select * from cf2 where p1 = 1;"); }).then([&e, tt] (auto msg) { assert_that(msg).is_rows().with_rows({ - { int32_type->decompose(int32_t(1)), tt->decompose(tuple_type_impl::native_type({int32_t(1), int64_t(2), sstring("abc")})) } + { int32_type->decompose(int32_t(1)), tt->decompose(make_tuple_value(tt, tuple_type_impl::native_type({int32_t(1), int64_t(2), sstring("abc")}))) } }); }); }); @@ -1090,9 +1096,10 @@ SEASTAR_TEST_CASE(test_user_type) { return e.execute_cql("select t from cf where id = 2;"); }).then([&e, make_user_type] (shared_ptr msg) { auto ut = make_user_type(); - auto ut_val = user_type_impl::native_type({boost::any(int32_t(2001)), - boost::any(int64_t(3001)), - boost::any(sstring("abc4"))}); + auto ut_val = make_user_value(ut, + user_type_impl::native_type({int32_t(2001), + int64_t(3001), + sstring("abc4")})); assert_that(msg).is_rows() .with_rows({ {ut->decompose(ut_val)}, @@ -1220,10 +1227,11 @@ SEASTAR_TEST_CASE(test_table_compression) { SEASTAR_TEST_CASE(test_ttl) { return do_with_cql_env([] (cql_test_env& e) { - return e.create_table([] (auto ks_name) { - auto my_list_type = list_type_impl::get_instance(utf8_type, true); + auto make_my_list_type = [] { return list_type_impl::get_instance(utf8_type, true); }; + auto my_list_type = make_my_list_type(); + return e.create_table([make_my_list_type] (auto ks_name) { return schema({}, ks_name, "cf", - {{"p1", utf8_type}}, {}, {{"r1", utf8_type}, {"r2", utf8_type}, {"r3", my_list_type}}, {}, utf8_type); + {{"p1", utf8_type}}, {}, {{"r1", utf8_type}, {"r2", utf8_type}, {"r3", make_my_list_type()}}, {}, utf8_type); }).then([&e] { return e.execute_cql( "update cf using ttl 1000 set r1 = 'value1_1', r3 = ['a', 'b', 'c'] where p1 = 'key1';").discard_result(); @@ -1236,18 +1244,18 @@ SEASTAR_TEST_CASE(test_ttl) { return e.execute_cql("update cf using ttl 1 set r1 = 'value1_2' where p1 = 'key2';").discard_result(); }).then([&e] { return e.execute_cql("insert into cf (p1, r2) values ('key2', 'value2_2');").discard_result(); - }).then([&e] { + }).then([&e, my_list_type] { return e.execute_cql("select r1 from cf;").then([](auto msg) { assert_that(msg).is_rows().with_size(3) .with_row({utf8_type->decompose(sstring("value1_1"))}) .with_row({utf8_type->decompose(sstring("value1_2"))}) .with_row({utf8_type->decompose(sstring("value1_3"))}); }); - }).then([&e] { - return e.execute_cql("select r3 from cf where p1 = 'key1';").then([] (auto msg) { + }).then([&e, my_list_type] { + return e.execute_cql("select r3 from cf where p1 = 'key1';").then([my_list_type] (auto msg) { auto my_list_type = list_type_impl::get_instance(utf8_type, true); assert_that(msg).is_rows().with_rows({ - {my_list_type->decompose(list_type_impl::native_type{{sstring("a"), sstring("b"), sstring("c")}})} + {my_list_type->decompose(make_list_value(my_list_type, list_type_impl::native_type{{sstring("a"), sstring("b"), sstring("c")}}))} }); }); }).then([&e] { @@ -1269,11 +1277,11 @@ SEASTAR_TEST_CASE(test_ttl) { .with_row({ {} }) .with_row({ utf8_type->decompose(sstring("value1_1")) }); }); - }).then([&e] { + }).then([&e, my_list_type] { return e.execute_cql("select r3 from cf where p1 = 'key1';").then([] (auto msg) { auto my_list_type = list_type_impl::get_instance(utf8_type, true); assert_that(msg).is_rows().with_rows({ - {my_list_type->decompose(list_type_impl::native_type{{sstring("a"), sstring("c")}})} + {my_list_type->decompose(make_list_value(my_list_type, list_type_impl::native_type{{sstring("a"), sstring("c")}}))} }); }); }).then([&e] { diff --git a/tests/cql_test_env.cc b/tests/cql_test_env.cc index 24289b8127..e56c0d4dd4 100644 --- a/tests/cql_test_env.cc +++ b/tests/cql_test_env.cc @@ -212,27 +212,29 @@ public: } virtual future<> require_column_has_value(const sstring& table_name, - std::vector pk, - std::vector ck, + std::vector pk, + std::vector ck, const sstring& column_name, - boost::any expected) override { + data_value expected) override { auto& db = _db->local(); auto& cf = db.find_column_family(ks_name, table_name); auto schema = cf.schema(); auto pkey = partition_key::from_deeply_exploded(*schema, pk); + auto ckey = clustering_key::from_deeply_exploded(*schema, ck); + auto exp = expected.type()->decompose(expected); auto dk = dht::global_partitioner().decorate_key(*schema, pkey); auto shard = db.shard_of(dk._token); return _db->invoke_on(shard, [pkey = std::move(pkey), - ck = std::move(ck), + ckey = std::move(ckey), ks_name = std::move(ks_name), column_name = std::move(column_name), - expected = std::move(expected), + exp = std::move(exp), table_name = std::move(table_name)] (database& db) mutable { auto& cf = db.find_column_family(ks_name, table_name); auto schema = cf.schema(); - return cf.find_partition_slow(pkey).then([schema, ck, column_name, expected] (column_family::const_mutation_partition_ptr p) { + return cf.find_partition_slow(pkey).then([schema, ckey, column_name, exp] (column_family::const_mutation_partition_ptr p) { assert(p != nullptr); - auto row = p->find_row(clustering_key::from_deeply_exploded(*schema, ck)); + auto row = p->find_row(ckey); assert(row != nullptr); auto col_def = schema->get_column_definition(utf8_type->decompose(column_name)); assert(col_def != nullptr); @@ -251,7 +253,7 @@ public: actual = type->to_value(type->deserialize_mutation_form(c), serialization_format::internal()); } - assert(col_def->type->equal(actual, col_def->type->decompose(expected))); + assert(col_def->type->equal(actual, exp)); }); }); } diff --git a/tests/cql_test_env.hh b/tests/cql_test_env.hh index fa51e983bc..2e1024f29d 100644 --- a/tests/cql_test_env.hh +++ b/tests/cql_test_env.hh @@ -62,10 +62,10 @@ public: virtual future<> require_column_has_value( const sstring& table_name, - std::vector pk, - std::vector ck, + std::vector pk, + std::vector ck, const sstring& column_name, - boost::any expected) = 0; + data_value expected) = 0; virtual future<> stop() = 0; diff --git a/tests/mutation_test.cc b/tests/mutation_test.cc index b74feb9eb7..e5aacdae66 100644 --- a/tests/mutation_test.cc +++ b/tests/mutation_test.cc @@ -106,10 +106,10 @@ SEASTAR_TEST_CASE(test_multi_level_row_tombstones) { mutation m(partition_key::from_exploded(*s, {to_bytes("key1")}), s); - auto make_prefix = [s] (const std::vector& v) { + auto make_prefix = [s] (const std::vector& v) { return clustering_key_prefix::from_deeply_exploded(*s, v); }; - auto make_key = [s] (const std::vector& v) { + auto make_key = [s] (const std::vector& v) { return clustering_key::from_deeply_exploded(*s, v); }; @@ -423,12 +423,12 @@ SEASTAR_TEST_CASE(test_multiple_memtables_multiple_partitions) { return do_with(std::move(result), [&cf, s, &r1_col, shadow] (auto& result) { return cf.for_all_partitions_slow([&, s] (const dht::decorated_key& pk, const mutation_partition& mp) { - auto p1 = boost::any_cast(int32_type->deserialize(pk._key.explode(*s)[0])); + auto p1 = value_cast(int32_type->deserialize(pk._key.explode(*s)[0])); for (const rows_entry& re : mp.range(*s, query::range())) { - auto c1 = boost::any_cast(int32_type->deserialize(re.key().explode(*s)[0])); + auto c1 = value_cast(int32_type->deserialize(re.key().explode(*s)[0])); auto cell = re.row().cells().find_cell(r1_col.id); if (cell) { - result[p1][c1] = boost::any_cast(int32_type->deserialize(cell->as_atomic_cell().value())); + result[p1][c1] = value_cast(int32_type->deserialize(cell->as_atomic_cell().value())); } } return true; @@ -601,7 +601,7 @@ SEASTAR_TEST_CASE(test_partition_with_live_data_in_static_row_is_present_in_the_ assert_that(query::result_set::from_raw_result(s, slice, m.query(slice))) .has_only(a_row() .with_column("pk", bytes("key1")) - .with_column("v", {})); + .with_column("v", data_value::make_null(bytes_type))); }); } @@ -626,7 +626,7 @@ SEASTAR_TEST_CASE(test_query_result_with_one_regular_column_missing) { .with_column("pk", bytes("key1")) .with_column("ck", bytes("ck:A")) .with_column("v1", bytes("v1:value")) - .with_column("v2", {})); + .with_column("v2", data_value::make_null(bytes_type))); }); } diff --git a/tests/perf/perf_sstable.hh b/tests/perf/perf_sstable.hh index 8f85a1bc6d..728d850dab 100644 --- a/tests/perf/perf_sstable.hh +++ b/tests/perf/perf_sstable.hh @@ -103,7 +103,7 @@ public: void fill_memtable() { for (unsigned i = 0; i < _cfg.partitions; i++) { - auto key = partition_key::from_deeply_exploded(*s, { boost::any(random_key()) }); + auto key = partition_key::from_deeply_exploded(*s, { random_key() }); auto mut = mutation(key, s); for (auto& cdef: s->regular_columns()) { mut.set_clustered_cell(clustering_key::make_empty(*s), cdef, atomic_cell::make_live(0, utf8_type->decompose(random_column()))); diff --git a/tests/result_set_assertions.cc b/tests/result_set_assertions.cc index b1fcaf802d..3bad23409f 100644 --- a/tests/result_set_assertions.cc +++ b/tests/result_set_assertions.cc @@ -39,12 +39,12 @@ row_assertion::matches(const query::result_set_row& row) const { auto ss_name = to_sstring(name); if (!row.has(ss_name)) { - if (!value.empty()) { + if (!value.is_null()) { return false; } } else { const data_value& val = row.get_data_value(ss_name); - if (val != data_value(boost::any(value), val.type())) { + if (val != value) { return false; } } @@ -61,7 +61,7 @@ row_assertion::describe(schema_ptr schema) const { if (!def) { BOOST_FAIL(sprint("Schema is missing column definition for '%s'", name)); } - if (value.empty()) { + if (value.is_null()) { return sprint("%s=null", to_sstring(name)); } else { return sprint("%s=\"%s\"", to_sstring(name), def->type->to_string(def->type->decompose(value))); diff --git a/tests/result_set_assertions.hh b/tests/result_set_assertions.hh index a2a838a325..f016c13827 100644 --- a/tests/result_set_assertions.hh +++ b/tests/result_set_assertions.hh @@ -35,9 +35,9 @@ // class row_assertion { - std::map _expected_values; + std::map _expected_values; public: - row_assertion& with_column(bytes name, boost::any value) { + row_assertion& with_column(bytes name, data_value value) { _expected_values.emplace(name, value); return *this; } diff --git a/tests/sstable_datafile_test.cc b/tests/sstable_datafile_test.cc index 06fb835d94..11371e48a6 100644 --- a/tests/sstable_datafile_test.cc +++ b/tests/sstable_datafile_test.cc @@ -919,7 +919,7 @@ SEASTAR_TEST_CASE(datafile_generation_16) { mutation m(key, s); auto c_key = clustering_key::make_empty(*s); - m.set_clustered_cell(c_key, to_bytes("col2"), boost::any(i), api::max_timestamp); + m.set_clustered_cell(c_key, to_bytes("col2"), i, api::max_timestamp); mtp->apply(std::move(m)); } @@ -1340,7 +1340,7 @@ SEASTAR_TEST_CASE(datafile_generation_37) { auto clustering = clustering_key::from_clustering_prefix(*s, exploded); auto row = mp.clustered_row(clustering); - match_live_cell(row.cells(), *s, "cl2", boost::any(to_bytes("cl2"))); + match_live_cell(row.cells(), *s, "cl2", to_bytes("cl2")); return make_ready_future<>(); }); }); @@ -1375,7 +1375,7 @@ SEASTAR_TEST_CASE(datafile_generation_38) { auto clustering = clustering_key::from_clustering_prefix(*s, exploded); auto row = mp.clustered_row(clustering); - match_live_cell(row.cells(), *s, "cl3", boost::any(to_bytes("cl3"))); + match_live_cell(row.cells(), *s, "cl3", to_bytes("cl3")); return make_ready_future<>(); }); }); @@ -1408,8 +1408,8 @@ SEASTAR_TEST_CASE(datafile_generation_39) { return sstp->read_row(s, key).then([sstp, s] (auto mutation) { auto& mp = mutation->partition(); auto row = mp.clustered_row(clustering_key::make_empty(*s)); - match_live_cell(row.cells(), *s, "cl1", boost::any(to_bytes("cl1"))); - match_live_cell(row.cells(), *s, "cl2", boost::any(to_bytes("cl2"))); + match_live_cell(row.cells(), *s, "cl1", to_bytes("cl1")); + match_live_cell(row.cells(), *s, "cl2", to_bytes("cl2")); return make_ready_future<>(); }); }); diff --git a/tests/sstable_mutation_test.cc b/tests/sstable_mutation_test.cc index 9444b5c18d..5a653d6b49 100644 --- a/tests/sstable_mutation_test.cc +++ b/tests/sstable_mutation_test.cc @@ -49,7 +49,7 @@ SEASTAR_TEST_CASE(nonexistent_key) { }); } -future<> test_no_clustered(bytes&& key, std::unordered_map &&map) { +future<> test_no_clustered(bytes&& key, std::unordered_map &&map) { return reusable_sst("tests/sstables/uncompressed", 1).then([k = std::move(key), map = std::move(map)] (auto sstp) mutable { return do_with(sstables::key(std::move(k)), [sstp, map = std::move(map)] (auto& key) { auto s = uncompressed_schema(); @@ -72,19 +72,19 @@ future<> test_no_clustered(bytes&& key, std::unordered_map && } SEASTAR_TEST_CASE(uncompressed_1) { - return test_no_clustered("vinna", {{ "col1", boost::any(to_sstring("daughter")) }, { "col2", boost::any(3) }}); + return test_no_clustered("vinna", {{ "col1", to_sstring("daughter") }, { "col2", 3 }}); } SEASTAR_TEST_CASE(uncompressed_2) { - return test_no_clustered("gustaf", {{ "col1", boost::any(to_sstring("son")) }, { "col2", boost::any(0) }}); + return test_no_clustered("gustaf", {{ "col1", to_sstring("son") }, { "col2", 0 }}); } SEASTAR_TEST_CASE(uncompressed_3) { - return test_no_clustered("isak", {{ "col1", boost::any(to_sstring("son")) }, { "col2", boost::any(1) }}); + return test_no_clustered("isak", {{ "col1", to_sstring("son") }, { "col2", 1 }}); } SEASTAR_TEST_CASE(uncompressed_4) { - return test_no_clustered("finna", {{ "col1", boost::any(to_sstring("daughter")) }, { "col2", boost::any(2) }}); + return test_no_clustered("finna", {{ "col1", to_sstring("daughter") }, { "col2", 2 }}); } /* @@ -138,10 +138,10 @@ SEASTAR_TEST_CASE(complex_sst1_k1) { auto s = complex_schema(); auto sr = mutation.partition().static_row(); - match_live_cell(sr, *s, "static_obj", boost::any(to_bytes("static_value"))); + match_live_cell(sr, *s, "static_obj", to_bytes("static_value")); auto row1 = clustered_row(mutation, *s, {"cl1.1", "cl2.1"}); - match_live_cell(row1.cells(), *s, "reg", boost::any(to_bytes("v1"))); + match_live_cell(row1.cells(), *s, "reg", to_bytes("v1")); match_absent(row1.cells(), *s, "reg_list"); match_absent(row1.cells(), *s, "reg_map"); match_absent(row1.cells(), *s, "reg_fset"); @@ -150,7 +150,7 @@ SEASTAR_TEST_CASE(complex_sst1_k1) { match_collection_element(reg_set.cells[1], to_bytes("2"), bytes_opt{}); auto row2 = clustered_row(mutation, *s, {"cl1.2", "cl2.2"}); - match_live_cell(row2.cells(), *s, "reg", boost::any(to_bytes("v2"))); + match_live_cell(row2.cells(), *s, "reg", to_bytes("v2")); match_absent(row2.cells(), *s, "reg_set"); match_absent(row2.cells(), *s, "reg_map"); match_absent(row2.cells(), *s, "reg_fset"); @@ -167,7 +167,7 @@ SEASTAR_TEST_CASE(complex_sst1_k2) { auto s = complex_schema(); auto sr = mutation.partition().static_row(); - match_live_cell(sr, *s, "static_obj", boost::any(to_bytes("static_value"))); + match_live_cell(sr, *s, "static_obj", to_bytes("static_value")); auto static_set = match_collection(sr, *s, "static_collection", tombstone(deletion_time{1431451390, 1431451390225257l})); match_collection_element(static_set.cells[0], to_bytes("1"), bytes_opt{}); match_collection_element(static_set.cells[1], to_bytes("2"), bytes_opt{}); @@ -175,7 +175,7 @@ SEASTAR_TEST_CASE(complex_sst1_k2) { match_collection_element(static_set.cells[3], to_bytes("4"), bytes_opt{}); auto row1 = clustered_row(mutation, *s, {"kcl1.1", "kcl2.1"}); - match_live_cell(row1.cells(), *s, "reg", boost::any(to_bytes("v3"))); + match_live_cell(row1.cells(), *s, "reg", to_bytes("v3")); match_absent(row1.cells(), *s, "reg_list"); match_absent(row1.cells(), *s, "reg_set"); match_absent(row1.cells(), *s, "reg_fset"); @@ -184,7 +184,7 @@ SEASTAR_TEST_CASE(complex_sst1_k2) { match_collection_element(reg_map.cells[1], to_bytes("4"), to_bytes("2")); auto row2 = clustered_row(mutation, *s, {"kcl1.2", "kcl2.2"}); - match_live_cell(row2.cells(), *s, "reg", boost::any(to_bytes("v4"))); + match_live_cell(row2.cells(), *s, "reg", to_bytes("v4")); match_absent(row2.cells(), *s, "reg_set"); match_absent(row2.cells(), *s, "reg_map"); match_absent(row2.cells(), *s, "reg_list"); @@ -245,11 +245,11 @@ SEASTAR_TEST_CASE(complex_sst2_k3) { auto s = complex_schema(); auto sr = mutation.partition().static_row(); - match_expiring_cell(sr, *s, "static_obj", boost::any(to_bytes("static_value_3")), 1431451394597062l, 1431537794); + match_expiring_cell(sr, *s, "static_obj", to_bytes("static_value_3"), 1431451394597062l, 1431537794); auto row1 = clustered_row(mutation, *s, {"tcl1.1", "tcl2.1"}); BOOST_REQUIRE(row1.created_at() == 1431451394597062l); - match_expiring_cell(row1.cells(), *s, "reg", boost::any(to_bytes("v5")), 1431451394597062l, 1431537794); + match_expiring_cell(row1.cells(), *s, "reg", to_bytes("v5"), 1431451394597062l, 1431537794); match_absent(row1.cells(), *s, "reg_list"); match_absent(row1.cells(), *s, "reg_set"); match_absent(row1.cells(), *s, "reg_map"); @@ -283,7 +283,7 @@ SEASTAR_TEST_CASE(complex_sst3_k2) { auto s = complex_schema(); auto sr = mutation.partition().static_row(); - match_live_cell(sr, *s, "static_obj", boost::any(to_bytes("final_static"))); + match_live_cell(sr, *s, "static_obj", to_bytes("final_static")); auto row = clustered_row(mutation, *s, {"kcl1.1", "kcl2.1"}); auto reg_map = match_collection(row.cells(), *s, "reg_map", tombstone(deletion_time{0, api::missing_timestamp})); @@ -385,8 +385,8 @@ SEASTAR_TEST_CASE(compact_storage_sparse_read) { return sstp->read_row(s, key).then([sstp, s, &key] (auto mutation) { auto& mp = mutation->partition(); auto row = mp.clustered_row(clustering_key::make_empty(*s)); - match_live_cell(row.cells(), *s, "cl1", boost::any(to_bytes("cl1"))); - match_live_cell(row.cells(), *s, "cl2", boost::any(to_bytes("cl2"))); + match_live_cell(row.cells(), *s, "cl1", to_bytes("cl1")); + match_live_cell(row.cells(), *s, "cl2", to_bytes("cl2")); return make_ready_future<>(); }); }); @@ -404,7 +404,7 @@ SEASTAR_TEST_CASE(compact_storage_simple_dense_read) { auto clustering = clustering_key::from_clustering_prefix(*s, exploded); auto row = mp.clustered_row(clustering); - match_live_cell(row.cells(), *s, "cl2", boost::any(to_bytes("cl2"))); + match_live_cell(row.cells(), *s, "cl2", to_bytes("cl2")); return make_ready_future<>(); }); }); @@ -422,7 +422,7 @@ SEASTAR_TEST_CASE(compact_storage_dense_read) { auto clustering = clustering_key::from_clustering_prefix(*s, exploded); auto row = mp.clustered_row(clustering); - match_live_cell(row.cells(), *s, "cl3", boost::any(to_bytes("cl3"))); + match_live_cell(row.cells(), *s, "cl3", to_bytes("cl3")); return make_ready_future<>(); }); }); @@ -452,7 +452,7 @@ SEASTAR_TEST_CASE(broken_ranges_collection) { return repeat([s, reader] { return (*reader)().then([s, reader] (mutation_opt mut) { auto key_equal = [s, &mut] (sstring ip) { - return mut->key().representation() == partition_key::from_deeply_exploded(*s, { boost::any(net::ipv4_address(ip)) }).representation(); + return mut->key().representation() == partition_key::from_deeply_exploded(*s, { net::ipv4_address(ip) }).representation(); }; if (!mut) { diff --git a/tests/sstable_test.cc b/tests/sstable_test.cc index d6ac238090..ea158b3ed8 100644 --- a/tests/sstable_test.cc +++ b/tests/sstable_test.cc @@ -669,16 +669,17 @@ SEASTAR_TEST_CASE(find_key_map) { return reusable_sst("tests/sstables/map_pk", 1).then([] (auto sstp) { schema_ptr s = map_schema(); auto& summary = sstables::test(sstp)._summary(); - std::vector kk; + std::vector kk; auto b1 = to_bytes("2"); auto b2 = to_bytes("2"); - auto map_element = std::make_pair(boost::any(b1), boost::any(b2)); - std::vector> map; + auto map_type = map_type_impl::get_instance(bytes_type, bytes_type, true); + auto map_element = std::make_pair(b1, b2); + std::vector> map; map.push_back(map_element); - kk.push_back(map); + kk.push_back(make_map_value(map_type, map)); auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); @@ -689,16 +690,17 @@ SEASTAR_TEST_CASE(find_key_set) { return reusable_sst("tests/sstables/set_pk", 1).then([] (auto sstp) { schema_ptr s = set_schema(); auto& summary = sstables::test(sstp)._summary(); - std::vector kk; + std::vector kk; - std::vector set; + std::vector set; bytes b1("1"); bytes b2("2"); - set.push_back(boost::any(b1)); - set.push_back(boost::any(b2)); - kk.push_back(set); + set.push_back(b1); + set.push_back(b2); + auto set_type = set_type_impl::get_instance(bytes_type, true); + kk.push_back(make_set_value(set_type, set)); auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); @@ -709,16 +711,17 @@ SEASTAR_TEST_CASE(find_key_list) { return reusable_sst("tests/sstables/list_pk", 1).then([] (auto sstp) { schema_ptr s = set_schema(); auto& summary = sstables::test(sstp)._summary(); - std::vector kk; + std::vector kk; - std::vector list; + std::vector list; bytes b1("1"); bytes b2("2"); - list.push_back(boost::any(b1)); - list.push_back(boost::any(b2)); + list.push_back(b1); + list.push_back(b2); - kk.push_back(list); + auto list_type = list_type_impl::get_instance(bytes_type, true); + kk.push_back(make_list_value(list_type, list)); auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); @@ -730,13 +733,13 @@ SEASTAR_TEST_CASE(find_key_composite) { return reusable_sst("tests/sstables/composite", 1).then([] (auto sstp) { schema_ptr s = composite_schema(); auto& summary = sstables::test(sstp)._summary(); - std::vector kk; + std::vector kk; auto b1 = bytes("HCG8Ee7ENWqfCXipk4-Ygi2hzrbfHC8pTtH3tEmV3d9p2w8gJPuMN_-wp1ejLRf4kNEPEgtgdHXa6NoFE7qUig=="); auto b2 = bytes("VJizqYxC35YpLaPEJNt_4vhbmKJxAg54xbiF1UkL_9KQkqghVvq34rZ6Lm8eRTi7JNJCXcH6-WtNUSFJXCOfdg=="); - kk.push_back(boost::any(b1)); - kk.push_back(boost::any(b2)); + kk.push_back(b1); + kk.push_back(b2); auto key = sstables::key::from_deeply_exploded(*s, kk); BOOST_REQUIRE(sstables::test(sstp).binary_search(summary.entries, key) == 0); @@ -771,13 +774,13 @@ SEASTAR_TEST_CASE(not_find_key_composite_bucket0) { return reusable_sst("tests/sstables/composite", 1).then([] (auto sstp) { schema_ptr s = composite_schema(); auto& summary = sstables::test(sstp)._summary(); - std::vector kk; + std::vector kk; auto b1 = bytes("ZEunFCoqAidHOrPiU3U6UAvUU01IYGvT3kYtYItJ1ODTk7FOsEAD-dqmzmFNfTDYvngzkZwKrLxthB7ItLZ4HQ=="); auto b2 = bytes("K-GpWx-QtyzLb12z5oNS0C03d3OzNyBKdYJh1XjHiC53KudoqdoFutHUMFLe6H9Emqv_fhwIJEKEb5Csn72f9A=="); - kk.push_back(boost::any(b1)); - kk.push_back(boost::any(b2)); + kk.push_back(b1); + kk.push_back(b2); auto key = sstables::key::from_deeply_exploded(*s, kk); // (result + 1) * -1 -1 = 0 diff --git a/tests/sstable_test.hh b/tests/sstable_test.hh index 4b744977c9..3ce22fa690 100644 --- a/tests/sstable_test.hh +++ b/tests/sstable_test.hh @@ -436,7 +436,7 @@ inline bool check_status_and_done(const atomic_cell &c, status expected) { } template -inline void match(const row& row, const schema& s, bytes col, const boost::any& value, int64_t timestamp = 0, int32_t expiration = 0) { +inline void match(const row& row, const schema& s, bytes col, const data_value& value, int64_t timestamp = 0, int32_t expiration = 0) { auto cdef = s.get_column_definition(col); BOOST_CHECK_NO_THROW(row.cell_at(cdef->id)); @@ -455,16 +455,16 @@ inline void match(const row& row, const schema& s, bytes col, const boost::any& } } -inline void match_live_cell(const row& row, const schema& s, bytes col, const boost::any& value) { +inline void match_live_cell(const row& row, const schema& s, bytes col, const data_value& value) { match(row, s, col, value); } -inline void match_expiring_cell(const row& row, const schema& s, bytes col, const boost::any& value, int64_t timestamp, int32_t expiration) { +inline void match_expiring_cell(const row& row, const schema& s, bytes col, const data_value& value, int64_t timestamp, int32_t expiration) { match(row, s, col, value); } inline void match_dead_cell(const row& row, const schema& s, bytes col) { - match(row, s, col, boost::any({})); + match(row, s, col, 0); // value will be ignored } inline void match_absent(const row& row, const schema& s, bytes col) { diff --git a/tests/types_test.cc b/tests/types_test.cc index 131907d6ac..7083a09e3b 100644 --- a/tests/types_test.cc +++ b/tests/types_test.cc @@ -212,18 +212,18 @@ BOOST_AUTO_TEST_CASE(test_varint) { BOOST_REQUIRE(varint_type->equal(varint_type->from_string("1"), varint_type->decompose(boost::multiprecision::cpp_int(1)))); BOOST_REQUIRE(varint_type->equal(varint_type->from_string("0"), varint_type->decompose(boost::multiprecision::cpp_int(0)))); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(varint_type->from_string("-1"))), + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(varint_type->from_string("-1"))), boost::multiprecision::cpp_int(-1)); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(varint_type->from_string("255"))), + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(varint_type->from_string("255"))), boost::multiprecision::cpp_int(255)); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(varint_type->from_string("1"))), + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(varint_type->from_string("1"))), boost::multiprecision::cpp_int(1)); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(varint_type->from_string("0"))), + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(varint_type->from_string("0"))), boost::multiprecision::cpp_int(0)); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(varint_type->from_string("-123"))), + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(varint_type->from_string("-123"))), boost::multiprecision::cpp_int(-123)); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(varint_type->from_string("123"))), + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(varint_type->from_string("123"))), boost::multiprecision::cpp_int(123)); BOOST_REQUIRE(varint_type->equal(from_hex("000000"), from_hex("00"))); @@ -235,8 +235,8 @@ BOOST_AUTO_TEST_CASE(test_varint) { BOOST_REQUIRE(varint_type->equal(from_hex("00ff"), varint_type->decompose(boost::multiprecision::cpp_int(255)))); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(from_hex("ff"))), boost::multiprecision::cpp_int(-1)); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(from_hex("00ff"))), boost::multiprecision::cpp_int(255)); + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(from_hex("ff"))), boost::multiprecision::cpp_int(-1)); + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(from_hex("00ff"))), boost::multiprecision::cpp_int(255)); BOOST_REQUIRE(!varint_type->equal(from_hex("00ff"), varint_type->decompose(boost::multiprecision::cpp_int(-1)))); BOOST_REQUIRE(!varint_type->equal(from_hex("ff"), varint_type->decompose(boost::multiprecision::cpp_int(255)))); @@ -244,49 +244,49 @@ BOOST_AUTO_TEST_CASE(test_varint) { BOOST_REQUIRE(varint_type->equal(from_hex("00deadbeef"), varint_type->decompose(boost::multiprecision::cpp_int("0xdeadbeef")))); BOOST_REQUIRE(varint_type->equal(from_hex("00ffffffffffffffffffffffffffffffff"), varint_type->decompose(boost::multiprecision::cpp_int("340282366920938463463374607431768211455")))); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(from_hex("00deadbeef"))), boost::multiprecision::cpp_int("0xdeadbeef")); - BOOST_CHECK_EQUAL(boost::any_cast(varint_type->deserialize(from_hex("00ffffffffffffffffffffffffffffffff"))), boost::multiprecision::cpp_int("340282366920938463463374607431768211455")); + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(from_hex("00deadbeef"))), boost::multiprecision::cpp_int("0xdeadbeef")); + BOOST_CHECK_EQUAL(value_cast(varint_type->deserialize(from_hex("00ffffffffffffffffffffffffffffffff"))), boost::multiprecision::cpp_int("340282366920938463463374607431768211455")); test_parsing_fails(varint_type, "1A"); } BOOST_AUTO_TEST_CASE(test_decimal) { - auto bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("-1"))); + auto bd = value_cast(decimal_type->deserialize(decimal_type->from_string("-1"))); BOOST_CHECK_EQUAL(bd.scale(), 0); BOOST_CHECK_EQUAL(bd.unscaled_value(), -1); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "-1"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("-1.00"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("-1.00"))); BOOST_CHECK_EQUAL(bd.scale(), 2); BOOST_CHECK_EQUAL(bd.unscaled_value(), -100); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "-1"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("123"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("123"))); BOOST_CHECK_EQUAL(bd.scale(), 0); BOOST_CHECK_EQUAL(bd.unscaled_value(), 123); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "123"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("1.23e3"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("1.23e3"))); BOOST_CHECK_EQUAL(bd.scale(), -1); BOOST_CHECK_EQUAL(bd.unscaled_value(), 123); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "1230"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("1.23e+3"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("1.23e+3"))); BOOST_CHECK_EQUAL(bd.scale(), -1); BOOST_CHECK_EQUAL(bd.unscaled_value(), 123); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "1230"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("1.23"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("1.23"))); BOOST_CHECK_EQUAL(bd.scale(), 2); BOOST_CHECK_EQUAL(bd.unscaled_value(), 123); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "1.23"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("0.123"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("0.123"))); BOOST_CHECK_EQUAL(bd.scale(), 3); BOOST_CHECK_EQUAL(bd.unscaled_value(), 123); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "0.123"); - bd = boost::any_cast(decimal_type->deserialize(decimal_type->from_string("0.00123"))); + bd = value_cast(decimal_type->deserialize(decimal_type->from_string("0.00123"))); BOOST_CHECK_EQUAL(bd.scale(), 5); BOOST_CHECK_EQUAL(bd.unscaled_value(), 123); BOOST_CHECK_EQUAL(decimal_type->to_string(decimal_type->decompose(bd)), "0.00123"); @@ -328,21 +328,11 @@ BOOST_AUTO_TEST_CASE(test_compound_type_compare) { template std::experimental::optional -extract(boost::any a) { - if (a.empty()) { +extract(data_value a) { + if (a.is_null()) { return std::experimental::nullopt; } else { - return std::experimental::make_optional(boost::any_cast(a)); - } -} - -template -boost::any -unextract(std::experimental::optional v) { - if (v) { - return boost::any(*v); - } else { - return boost::any(); + return std::experimental::make_optional(value_cast(a)); } } @@ -357,13 +347,13 @@ BOOST_AUTO_TEST_CASE(test_tuple) { return std::make_tuple(extract(v[0]), extract(v[1]), extract(v[2])); }; auto c_to_native = [] (std::tuple, opt, opt> v) { - return native_type({unextract(std::get<0>(v)), unextract(std::get<1>(v)), unextract(std::get<2>(v))}); + return native_type({std::get<0>(v), std::get<1>(v), std::get<2>(v)}); }; auto native_to_bytes = [t] (native_type v) { - return t->decompose(v); + return t->decompose(make_tuple_value(t, v)); }; auto bytes_to_native = [t] (bytes v) { - return boost::any_cast(t->deserialize(v)); + return value_cast(t->deserialize(v)); }; auto c_to_bytes = [=] (c_type v) { return native_to_bytes(c_to_native(v)); @@ -531,19 +521,19 @@ BOOST_AUTO_TEST_CASE(test_create_reverse_collection_type) { BOOST_REQUIRE(ri->is_collection()); BOOST_REQUIRE(ri->is_multi_cell()); - std::vector first_set; + std::vector first_set; bytes b1("1"); bytes b2("2"); - first_set.push_back(boost::any(b1)); - first_set.push_back(boost::any(b2)); + first_set.push_back(b1); + first_set.push_back(b2); - std::vector second_set; + std::vector second_set; bytes b3("2"); - second_set.push_back(boost::any(b1)); - second_set.push_back(boost::any(b3)); + second_set.push_back(b1); + second_set.push_back(b3); - auto bv1 = my_set_type->decompose(first_set); - auto bv2 = my_set_type->decompose(second_set); + auto bv1 = my_set_type->decompose(make_set_value(my_set_type, first_set)); + auto bv2 = my_set_type->decompose(make_set_value(my_set_type, second_set)); auto straight_comp = my_set_type->compare(bytes_view(bv1), bytes_view(bv2)); auto reverse_comp = ri->compare(bytes_view(bv2), bytes_view(bv2)); diff --git a/transport/server.cc b/transport/server.cc index cb9b3fc208..4a95242ce6 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -196,8 +196,8 @@ public: void write_string_list(std::vector string_list); void write_bytes(bytes b); void write_short_bytes(bytes b); - void write_option(std::pair opt); - void write_option_list(std::vector> opt_list); + void write_option(std::pair opt); + void write_option_list(std::vector> opt_list); void write_inet(ipv4_addr inet); void write_consistency(db::consistency_level c); void write_string_map(std::map string_map); @@ -1261,13 +1261,13 @@ void cql_server::response::write_short_bytes(bytes b) _body.insert(_body.end(), b.begin(), b.end()); } -void cql_server::response::write_option(std::pair opt) +void cql_server::response::write_option(std::pair opt) { // FIXME assert(0); } -void cql_server::response::write_option_list(std::vector> opt_list) +void cql_server::response::write_option_list(std::vector> opt_list) { // FIXME assert(0); diff --git a/types.cc b/types.cc index a64e48bf19..de2cd086a9 100644 --- a/types.cc +++ b/types.cc @@ -79,8 +79,8 @@ struct simple_type_traits { }; template -struct simple_type_impl : abstract_type { - simple_type_impl(sstring name) : abstract_type(std::move(name)) {} +struct simple_type_impl : concrete_type { + simple_type_impl(sstring name) : concrete_type(std::move(name)) {} virtual int32_t compare(bytes_view v1, bytes_view v2) const override { if (v1.empty()) { return v2.empty() ? 0 : -1; @@ -106,26 +106,28 @@ struct simple_type_impl : abstract_type { template struct integer_type_impl : simple_type_impl { integer_type_impl(sstring name) : simple_type_impl(name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto v = boost::any_cast(value); + auto v = this->from_value(value); auto u = net::hton(v); out = std::copy_n(reinterpret_cast(&u), sizeof(u), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } - auto v = boost::any_cast(value); + auto v = this->from_value(value); return sizeof(v); } - virtual boost::any deserialize(bytes_view v) const override { - if (v.empty()) { - return {}; + virtual data_value deserialize(bytes_view v) const override { + auto x = read_simple_opt(v); + if (!x) { + return this->make_null(); + } else { + return this->make_value(*x); } - return read_simple_opt(v); } T compose_value(const bytes& b) const { if (b.size() != sizeof(T)) { @@ -182,29 +184,29 @@ struct long_type_impl : integer_type_impl { } }; -struct string_type_impl : public abstract_type { +struct string_type_impl : public concrete_type { string_type_impl(sstring name) - : abstract_type(name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + : concrete_type(name) {} + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto& v = boost::any_cast(value); + auto& v = from_value(value); out = std::copy(v.begin(), v.end(), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } - auto& v = boost::any_cast(value); + auto& v = from_value(value); return v.size(); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } // FIXME: validation? - return boost::any(sstring(reinterpret_cast(v.begin()), v.size())); + return make_value(std::make_unique(reinterpret_cast(v.begin()), v.size())); } virtual bool less(bytes_view v1, bytes_view v2) const override { return less_unsigned(v1, v2); @@ -252,29 +254,30 @@ struct utf8_type_impl final : public string_type_impl { virtual ::shared_ptr as_cql3_type() const override { return cql3::cql3_type::text; } + using concrete_type::from_value; }; -struct bytes_type_impl final : public abstract_type { - bytes_type_impl() : abstract_type(bytes_type_name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { +struct bytes_type_impl final : public concrete_type { + bytes_type_impl() : concrete_type(bytes_type_name) {} + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto& v = boost::any_cast(value); + auto& v = from_value(value); out = std::copy(v.begin(), v.end(), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } - auto& v = boost::any_cast(value); + auto& v = from_value(value); return v.size(); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } - return boost::any(bytes(v.begin(), v.end())); + return make_value(std::make_unique(v.begin(), v.end())); } virtual bool less(bytes_view v1, bytes_view v2) const override { return less_unsigned(v1, v2); @@ -307,14 +310,14 @@ struct boolean_type_impl : public simple_type_impl { void serialize_value(bool value, bytes::iterator& out) const { *out++ = char(value); } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - serialize_value(boost::any_cast(value), out); + serialize_value(from_value(value), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return 1; @@ -322,14 +325,14 @@ struct boolean_type_impl : public simple_type_impl { size_t serialized_size(bool value) const { return 1; } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } if (v.size() != 1) { throw marshal_exception(); } - return boost::any(*v.begin() != 0); + return make_value(*v.begin() != 0); } virtual void validate(bytes_view v) const override { if (v.size() != 0 && v.size() != 1) { @@ -361,29 +364,29 @@ struct boolean_type_impl : public simple_type_impl { } }; -struct date_type_impl : public abstract_type { - date_type_impl() : abstract_type("date") {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { +struct date_type_impl : public concrete_type { + date_type_impl() : concrete_type("date") {} + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto v = boost::any_cast(value); + auto& v = from_value(value); int64_t i = v.time_since_epoch().count(); i = net::hton(uint64_t(i)); out = std::copy_n(reinterpret_cast(&i), sizeof(i), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return 8; } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } auto tmp = read_simple_exactly(v); - return boost::any(db_clock::time_point(db_clock::duration(tmp))); + return make_value(db_clock::time_point(db_clock::duration(tmp))); } virtual bool less(bytes_view b1, bytes_view b2) const override { return compare_unsigned(b1, b2); @@ -408,35 +411,35 @@ struct date_type_impl : public abstract_type { } }; -struct timeuuid_type_impl : public abstract_type { - timeuuid_type_impl() : abstract_type(timeuuid_type_name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { +struct timeuuid_type_impl : public concrete_type { + timeuuid_type_impl() : concrete_type(timeuuid_type_name) {} + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto& uuid = boost::any_cast(value); + auto& uuid = from_value(value); out = std::copy_n(uuid.to_bytes().begin(), sizeof(uuid), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return 16; } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } uint64_t msb, lsb; if (v.empty()) { - return {}; + return make_null(); } msb = read_simple(v); lsb = read_simple(v); if (!v.empty()) { throw marshal_exception(); } - return boost::any(utils::UUID(msb, lsb)); + return make_value(utils::UUID(msb, lsb)); } virtual bool less(bytes_view b1, bytes_view b2) const override { if (b1.empty()) { @@ -485,10 +488,10 @@ struct timeuuid_type_impl : public abstract_type { } virtual sstring to_string(const bytes& b) const override { auto v = deserialize(b); - if (v.empty()) { + if (v.is_null()) { return ""; } - return boost::any_cast(v).to_sstring(); + return from_value(v).to_sstring(); } virtual ::shared_ptr as_cql3_type() const override { return cql3::cql3_type::timeuuid; @@ -513,26 +516,26 @@ private: struct timestamp_type_impl : simple_type_impl { timestamp_type_impl() : simple_type_impl(timestamp_type_name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - uint64_t v = boost::any_cast(value).time_since_epoch().count(); + uint64_t v = from_value(value).time_since_epoch().count(); v = net::hton(v); out = std::copy_n(reinterpret_cast(&v), sizeof(v), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return 8; } - virtual boost::any deserialize(bytes_view in) const override { + virtual data_value deserialize(bytes_view in) const override { if (in.empty()) { - return {}; + return make_null(); } auto v = read_simple_exactly(in); - return boost::any(db_clock::time_point(db_clock::duration(v))); + return make_value(db_clock::time_point(db_clock::duration(v))); } // FIXME: isCompatibleWith(timestampuuid) virtual void validate(bytes_view v) const override { @@ -636,31 +639,31 @@ struct timestamp_type_impl : simple_type_impl { } }; -struct uuid_type_impl : abstract_type { - uuid_type_impl() : abstract_type(uuid_type_name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { +struct uuid_type_impl : concrete_type { + uuid_type_impl() : concrete_type(uuid_type_name) {} + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto& uuid = boost::any_cast(value); + auto& uuid = from_value(value); out = std::copy_n(uuid.to_bytes().begin(), sizeof(uuid), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return 16; } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } auto msb = read_simple(v); auto lsb = read_simple(v); if (!v.empty()) { throw marshal_exception(); } - return boost::any(utils::UUID(msb, lsb)); + return make_value(utils::UUID(msb, lsb)); } virtual bool less(bytes_view b1, bytes_view b2) const override { if (b1.size() < 16) { @@ -711,10 +714,10 @@ struct uuid_type_impl : abstract_type { } virtual sstring to_string(const bytes& b) const override { auto v = deserialize(b); - if (v.empty()) { + if (v.is_null()) { return ""; } - return boost::any_cast(v).to_sstring(); + return from_value(v).to_sstring(); } virtual ::shared_ptr as_cql3_type() const override { return cql3::cql3_type::uuid; @@ -724,26 +727,26 @@ struct uuid_type_impl : abstract_type { } }; -struct inet_addr_type_impl : abstract_type { - inet_addr_type_impl() : abstract_type(inet_addr_type_name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { +struct inet_addr_type_impl : concrete_type { + inet_addr_type_impl() : concrete_type(inet_addr_type_name) {} + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } // FIXME: support ipv6 - auto& ipv4 = boost::any_cast(value); + auto& ipv4 = from_value(value); uint32_t u = htonl(ipv4.ip); out = std::copy_n(reinterpret_cast(&u), sizeof(u), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return 4; } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } if (v.size() == 16) { throw std::runtime_error("IPv6 addresses not supported"); @@ -752,7 +755,7 @@ struct inet_addr_type_impl : abstract_type { if (!v.empty()) { throw marshal_exception(); } - return boost::any(net::ipv4_address(ip)); + return make_value(net::ipv4_address(ip)); } virtual bool less(bytes_view v1, bytes_view v2) const override { return less_unsigned(v1, v2); @@ -784,15 +787,15 @@ struct inet_addr_type_impl : abstract_type { } bytes b(bytes::initialized_later(), sizeof(uint32_t)); auto out = b.begin(); - serialize(boost::any(ipv4), out); + serialize(&ipv4, out); return b; } virtual sstring to_string(const bytes& b) const override { auto v = deserialize(b); - if (v.empty()) { + if (v.is_null()) { return ""; } - boost::asio::ip::address_v4 ipv4(boost::any_cast(v).ip); + boost::asio::ip::address_v4 ipv4(from_value(v).ip); return ipv4.to_string(); } virtual ::shared_ptr as_cql3_type() const override { @@ -832,11 +835,11 @@ template<> struct simple_type_traits : public float_type_traits template struct floating_type_impl : public simple_type_impl { floating_type_impl(sstring name) : simple_type_impl(std::move(name)) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - T d = boost::any_cast(value); + T d = this->from_value(value); if (std::isnan(d)) { // Java's Double.doubleToLongBits() documentation specifies that // any nan must be serialized to the same specific value @@ -850,16 +853,16 @@ struct floating_type_impl : public simple_type_impl { auto u = net::hton(x.i); out = std::copy_n(reinterpret_cast(&u), sizeof(u), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } return sizeof(T); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return this->make_null(); } union { T d; @@ -869,7 +872,7 @@ struct floating_type_impl : public simple_type_impl { if (!v.empty()) { throw marshal_exception(); } - return boost::any(x.d); + return this->make_value(x.d); } virtual int32_t compare(bytes_view v1, bytes_view v2) const override { if (v1.empty()) { @@ -910,7 +913,8 @@ struct floating_type_impl : public simple_type_impl { auto d = boost::lexical_cast(s.begin(), s.size()); bytes b(bytes::initialized_later(), sizeof(T)); auto out = b.begin(); - serialize(boost::any(d), out); + auto val = this->make_value(d); + serialize(this->get_value_ptr(val), out); return b; } catch(const boost::bad_lexical_cast& e) { @@ -919,10 +923,10 @@ struct floating_type_impl : public simple_type_impl { } virtual sstring to_string(const bytes& b) const override { auto v = deserialize(b); - if (v.empty()) { + if (v.is_null()) { return ""; } - return to_sstring(boost::any_cast(v)); + return to_sstring(this->from_value(v)); } }; @@ -941,14 +945,14 @@ struct float_type_impl : floating_type_impl { }; -class varint_type_impl : public abstract_type { +class varint_type_impl : public concrete_type { public: - varint_type_impl() : abstract_type{varint_type_name} { } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + varint_type_impl() : concrete_type{varint_type_name} { } + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto num = boost::any_cast(value); + auto& num = from_value(value); boost::multiprecision::cpp_int pnum = boost::multiprecision::abs(num); std::vector b; @@ -967,11 +971,11 @@ public: } std::copy(b.crbegin(), b.crend(), out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } - auto num = boost::any_cast(value); + auto& num = from_value(value); if (!num) { return 1; } @@ -984,8 +988,8 @@ public: if (v2.empty()) { return 1; } - auto a = boost::any_cast(deserialize(v1)); - auto b = boost::any_cast(deserialize(v2)); + auto a = from_value(deserialize(v1)); + auto b = from_value(deserialize(v2)); return a == b ? 0 : a < b ? -1 : 1; } virtual bool less(bytes_view v1, bytes_view v2) const override { @@ -995,9 +999,9 @@ public: bytes b(v.begin(), v.end()); return std::hash()(to_string(b)); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } auto negative = v.front() < 0; boost::multiprecision::cpp_int num; @@ -1011,14 +1015,14 @@ public: if (negative) { num += 1; } - return negative ? -num : num; + return make_value(negative ? -num : num); } virtual sstring to_string(const bytes& b) const override { auto v = deserialize(b); - if (v.empty()) { + if (v.is_null()) { return ""; } - return boost::any_cast(v).str(); + return from_value(v).str(); } virtual bytes from_string(sstring_view text) const override { if (text.empty()) { @@ -1027,9 +1031,9 @@ public: try { std::string str(text.begin(), text.end()); boost::multiprecision::cpp_int num(str); - bytes b(bytes::initialized_later(), serialized_size(num)); + bytes b(bytes::initialized_later(), serialized_size(&num)); auto out = b.begin(); - serialize(boost::any(num), out); + serialize(&num, out); return b; } catch (...) { throw marshal_exception(sprint("unable to make int from '%s'", text)); @@ -1038,26 +1042,29 @@ public: virtual ::shared_ptr as_cql3_type() const override { return cql3::cql3_type::varint; } + friend class decimal_type_impl; }; -class decimal_type_impl : public abstract_type { +class decimal_type_impl : public concrete_type { public: - decimal_type_impl() : abstract_type{decimal_type_name} { } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { - if (value.empty()) { + decimal_type_impl() : concrete_type{decimal_type_name} { } + virtual void serialize(const void* value, bytes::iterator& out) const override { + if (!value) { return; } - auto bd = boost::any_cast(value); + auto bd = from_value(value); auto u = net::hton(bd.scale()); out = std::copy_n(reinterpret_cast(&u), sizeof(int32_t), out); - varint_type->serialize(bd.unscaled_value(), out); + auto&& unscaled_value = bd.unscaled_value(); + varint_type->serialize(&unscaled_value, out); } - virtual size_t serialized_size(const boost::any& value) const override { - if (value.empty()) { + virtual size_t serialized_size(const void* value) const override { + if (!value) { return 0; } - auto bd = boost::any_cast(value); - return sizeof(int32_t) + varint_type->serialized_size(bd.unscaled_value()); + auto& bd = from_value(value); + auto&& unscaled_value = bd.unscaled_value(); + return sizeof(int32_t) + varint_type->serialized_size(&unscaled_value); } virtual int32_t compare(bytes_view v1, bytes_view v2) const override { if (v1.empty()) { @@ -1066,8 +1073,8 @@ public: if (v2.empty()) { return 1; } - auto a = boost::any_cast(deserialize(v1)); - auto b = boost::any_cast(deserialize(v2)); + auto a = from_value(deserialize(v1)); + auto b = from_value(deserialize(v2)); return a.compare(b); } @@ -1078,20 +1085,21 @@ public: bytes b(v.begin(), v.end()); return std::hash()(to_string(b)); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { - return {}; + return make_null(); } auto scale = read_simple(v); auto unscaled = varint_type->deserialize(v); - return big_decimal(scale, boost::any_cast(unscaled)); + auto real_varint_type = static_cast(varint_type.get()); // yuck + return make_value(big_decimal(scale, real_varint_type->from_value(unscaled))); } virtual sstring to_string(const bytes& b) const override { auto v = deserialize(b); - if (v.empty()) { + if (v.is_null()) { return ""; } - return boost::any_cast(v).to_string(); + return from_value(v).to_string(); } virtual bytes from_string(sstring_view text) const override { if (text.empty()) { @@ -1099,9 +1107,9 @@ public: } try { big_decimal bd(text); - bytes b(bytes::initialized_later(), serialized_size(bd)); + bytes b(bytes::initialized_later(), serialized_size(&bd)); auto out = b.begin(); - serialize(boost::any(bd), out); + serialize(&bd, out); return b; } catch (...) { throw marshal_exception(sprint("unable to make BigDecimal from '%s'", text)); @@ -1115,10 +1123,10 @@ public: class counter_type_impl : public abstract_type { public: counter_type_impl() : abstract_type{counter_type_name} { } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { + virtual void serialize(const void* value, bytes::iterator& out) const override { fail(unimplemented::cause::COUNTERS); } - virtual size_t serialized_size(const boost::any& value) const override { + virtual size_t serialized_size(const void* value) const override { fail(unimplemented::cause::COUNTERS); } virtual int32_t compare(bytes_view v1, bytes_view v2) const override { @@ -1130,7 +1138,7 @@ public: virtual size_t hash(bytes_view v) const override { fail(unimplemented::cause::COUNTERS); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { fail(unimplemented::cause::COUNTERS); } virtual sstring to_string(const bytes& b) const override { @@ -1143,15 +1151,39 @@ public: return true; } virtual ::shared_ptr as_cql3_type() const override { - return cql3::cql3_type::counter; + fail(unimplemented::cause::COUNTERS); + } + virtual size_t native_value_size() const override { + fail(unimplemented::cause::COUNTERS); + } + virtual size_t native_value_alignment() const override { + fail(unimplemented::cause::COUNTERS); + } + virtual void native_value_copy(const void* from, void* to) const override { + fail(unimplemented::cause::COUNTERS); + } + virtual void native_value_move(const void* from, void* to) const override { + fail(unimplemented::cause::COUNTERS); + } + virtual void native_value_destroy(void* object) const override { + fail(unimplemented::cause::COUNTERS); + } + virtual void native_value_delete(void* object) const override { + fail(unimplemented::cause::COUNTERS); + } + virtual void* native_value_clone(const void* object) const override { + fail(unimplemented::cause::COUNTERS); + } + virtual const std::type_info& native_typeid() const { + fail(unimplemented::cause::COUNTERS); } }; struct empty_type_impl : abstract_type { empty_type_impl() : abstract_type(empty_type_name) {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { + virtual void serialize(const void* value, bytes::iterator& out) const override { } - virtual size_t serialized_size(const boost::any& value) const override { + virtual size_t serialized_size(const void* value) const override { return 0; } @@ -1161,8 +1193,8 @@ struct empty_type_impl : abstract_type { virtual size_t hash(bytes_view v) const override { return 0; } - virtual boost::any deserialize(bytes_view v) const override { - return {}; + virtual data_value deserialize(bytes_view v) const override { + return data_value::make_null(shared_from_this()); } virtual sstring to_string(const bytes& b) const override { // FIXME: @@ -1176,6 +1208,38 @@ struct empty_type_impl : abstract_type { // Can't happen abort(); } + virtual size_t native_value_size() const override { + // Can't happen + abort(); + } + virtual size_t native_value_alignment() const override { + // Can't happen + abort(); + } + virtual void native_value_copy(const void* from, void* to) const override { + // Can't happen + abort(); + } + virtual void native_value_move(const void* from, void* to) const override { + // Can't happen + abort(); + } + virtual void native_value_destroy(void* object) const override { + // Can't happen + abort(); + } + virtual void native_value_delete(void* object) const override { + // Can't happen + abort(); + } + virtual void* native_value_clone(const void* object) const override { + // Can't happen + abort(); + } + virtual const std::type_info& native_typeid() const { + // Can't happen + abort(); + } }; @@ -1317,8 +1381,8 @@ void write_collection_value(bytes::iterator& out, serialization_format sf, bytes out = std::copy_n(val_bytes.begin(), val_bytes.size(), out); } -void write_collection_value(bytes::iterator& out, serialization_format sf, data_type type, const boost::any& value) { - size_t val_len = type->serialized_size(value); +void write_collection_value(bytes::iterator& out, serialization_format sf, data_type type, const data_value& value) { + size_t val_len = type->serialized_size(type->get_value_ptr(value)); if (sf.using_32_bits_for_collections()) { serialize_int32(out, val_len); @@ -1326,7 +1390,7 @@ void write_collection_value(bytes::iterator& out, serialization_format sf, data_ serialize_int16(out, val_len); } - type->serialize(value, out); + type->serialize(type->get_value_ptr(value), out); } map_type @@ -1335,7 +1399,7 @@ map_type_impl::get_instance(data_type keys, data_type values, bool is_multi_cell } map_type_impl::map_type_impl(data_type keys, data_type values, bool is_multi_cell) - : collection_type_impl("org.apache.cassandra.db.marshal.MapType(" + keys->name() + "," + values->name() + ")", kind::map) + : concrete_type("org.apache.cassandra.db.marshal.MapType(" + keys->name() + "," + values->name() + ")", kind::map) , _keys(std::move(keys)) , _values(std::move(values)) , _is_multi_cell(is_multi_cell) { @@ -1406,26 +1470,26 @@ map_type_impl::compare_maps(data_type keys, data_type values, bytes_view o1, byt } void -map_type_impl::serialize(const boost::any& value, bytes::iterator& out) const { +map_type_impl::serialize(const void* value, bytes::iterator& out) const { return serialize(value, out, serialization_format::internal()); } size_t -map_type_impl::serialized_size(const boost::any& value) const { - auto& m = boost::any_cast(value); +map_type_impl::serialized_size(const void* value) const { + auto& m = from_value(value); size_t len = collection_size_len(serialization_format::internal()); size_t psz = collection_value_len(serialization_format::internal()); for (auto&& kv : m) { - len += psz + _keys->serialized_size(kv.first); - len += psz + _values->serialized_size(kv.second); + len += psz + _keys->serialized_size(get_value_ptr(kv.first)); + len += psz + _values->serialized_size(get_value_ptr(kv.second)); } return len; } void -map_type_impl::serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const { - auto& m = boost::any_cast(value); +map_type_impl::serialize(const void* value, bytes::iterator& out, serialization_format sf) const { + auto& m = from_value(value); write_collection_size(out, m.size(), sf); for (auto&& kv : m) { write_collection_value(out, sf, _keys, kv.first); @@ -1433,15 +1497,15 @@ map_type_impl::serialize(const boost::any& value, bytes::iterator& out, serializ } } -boost::any +data_value map_type_impl::deserialize(bytes_view v) const { return deserialize(v, serialization_format::internal()); } -boost::any +data_value map_type_impl::deserialize(bytes_view in, serialization_format sf) const { if (in.empty()) { - return {}; + return make_null(); } native_type m; auto size = read_collection_size(in, sf); @@ -1452,7 +1516,7 @@ map_type_impl::deserialize(bytes_view in, serialization_format sf) const { auto v = _values->deserialize(vb); m.insert(m.end(), std::make_pair(std::move(k), std::move(v))); } - return { std::move(m) }; + return make_value(std::move(m)); } sstring @@ -1720,9 +1784,9 @@ collection_type_impl::reserialize(serialization_format from, serialization_forma return std::experimental::nullopt; } auto val = deserialize(*v, from); - bytes ret(bytes::initialized_later(), serialized_size(v)); // FIXME: serialized_size want @to + bytes ret(bytes::initialized_later(), serialized_size(get_value_ptr(val))); // FIXME: serialized_size want @to auto out = ret.begin(); - serialize(std::move(val), out, to); + serialize(get_value_ptr(val), out, to); return ret; } @@ -1783,7 +1847,7 @@ set_type_impl::get_instance(data_type elements, bool is_multi_cell) { } set_type_impl::set_type_impl(data_type elements, bool is_multi_cell) - : collection_type_impl("org.apache.cassandra.db.marshal.SetType(" + elements->name() + ")", kind::set) + : concrete_type("org.apache.cassandra.db.marshal.SetType(" + elements->name() + ")", kind::set) , _elements(std::move(elements)) , _is_multi_cell(is_multi_cell) { } @@ -1829,17 +1893,17 @@ set_type_impl::less(bytes_view o1, bytes_view o2) const { } void -set_type_impl::serialize(const boost::any& value, bytes::iterator& out) const { +set_type_impl::serialize(const void* value, bytes::iterator& out) const { return serialize(value, out, serialization_format::internal()); } size_t -set_type_impl::serialized_size(const boost::any& value) const { - auto& s = boost::any_cast(value); +set_type_impl::serialized_size(const void* value) const { + auto& s = from_value(value); size_t len = collection_size_len(serialization_format::internal()); size_t psz = collection_value_len(serialization_format::internal()); for (auto&& e : s) { - len += psz + _elements->serialized_size(e); + len += psz + _elements->serialized_size(_elements->get_value_ptr(e)); } return len; } @@ -1847,35 +1911,35 @@ set_type_impl::serialized_size(const boost::any& value) const { void -set_type_impl::serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const { - auto& s = boost::any_cast(value); +set_type_impl::serialize(const void* value, bytes::iterator& out, serialization_format sf) const { + auto& s = from_value(value); write_collection_size(out, s.size(), sf); for (auto&& e : s) { write_collection_value(out, sf, _elements, e); } } -boost::any +data_value set_type_impl::deserialize(bytes_view in) const { return deserialize(in, serialization_format::internal()); } -boost::any +data_value set_type_impl::deserialize(bytes_view in, serialization_format sf) const { if (in.empty()) { - return {}; + return make_null(); } auto nr = read_collection_size(in, sf); native_type s; s.reserve(nr); for (int i = 0; i != nr; ++i) { auto e = _elements->deserialize(read_collection_value(in, sf)); - if (e.empty()) { + if (e.is_null()) { throw marshal_exception(); } s.push_back(std::move(e)); } - return { s }; + return make_value(std::move(s)); } sstring @@ -1943,7 +2007,7 @@ list_type_impl::get_instance(data_type elements, bool is_multi_cell) { } list_type_impl::list_type_impl(data_type elements, bool is_multi_cell) - : collection_type_impl("org.apache.cassandra.db.marshal.ListType(" + elements->name() + ")", kind::list) + : concrete_type("org.apache.cassandra.db.marshal.ListType(" + elements->name() + ")", kind::list) , _elements(std::move(elements)) , _is_multi_cell(is_multi_cell) { } @@ -1995,13 +2059,13 @@ list_type_impl::less(bytes_view o1, bytes_view o2) const { } void -list_type_impl::serialize(const boost::any& value, bytes::iterator& out) const { +list_type_impl::serialize(const void* value, bytes::iterator& out) const { return serialize(value, out, serialization_format::internal()); } void -list_type_impl::serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const { - auto& s = boost::any_cast(value); +list_type_impl::serialize(const void* value, bytes::iterator& out, serialization_format sf) const { + auto& s = from_value(value); write_collection_size(out, s.size(), sf); for (auto&& e : s) { write_collection_value(out, sf, _elements, e); @@ -2009,37 +2073,37 @@ list_type_impl::serialize(const boost::any& value, bytes::iterator& out, seriali } size_t -list_type_impl::serialized_size(const boost::any& value) const { - auto& s = boost::any_cast(value); +list_type_impl::serialized_size(const void* value) const { + auto& s = from_value(value); size_t len = collection_size_len(serialization_format::internal()); size_t psz = collection_value_len(serialization_format::internal()); for (auto&& e : s) { - len += psz + _elements->serialized_size(e); + len += psz + _elements->serialized_size(_elements->get_value_ptr(e)); } return len; } -boost::any +data_value list_type_impl::deserialize(bytes_view in) const { return deserialize(in, serialization_format::internal()); } -boost::any +data_value list_type_impl::deserialize(bytes_view in, serialization_format sf) const { if (in.empty()) { - return {}; + return make_null(); } auto nr = read_collection_size(in, sf); native_type s; s.reserve(nr); for (int i = 0; i != nr; ++i) { auto e = _elements->deserialize(read_collection_value(in, sf)); - if (e.empty()) { + if (e.is_null()) { throw marshal_exception(); } s.push_back(std::move(e)); } - return { s }; + return make_value(std::move(s)); } sstring @@ -2096,14 +2160,14 @@ list_type_impl::cql3_type_name() const { } tuple_type_impl::tuple_type_impl(sstring name, std::vector types) - : abstract_type(std::move(name)), _types(std::move(types)) { + : concrete_type(std::move(name)), _types(std::move(types)) { for (auto& t : _types) { t = t->freeze(); } } tuple_type_impl::tuple_type_impl(std::vector types) - : abstract_type(make_name(types)), _types(std::move(types)) { + : concrete_type(make_name(types)), _types(std::move(types)) { for (auto& t : _types) { t = t->freeze(); } @@ -2128,47 +2192,53 @@ tuple_type_impl::less(bytes_view v1, bytes_view v2) const { } size_t -tuple_type_impl::serialized_size(const boost::any& value) const { +tuple_type_impl::serialized_size(const void* value) const { size_t size = 0; - if (value.empty()) { + if (!value) { return size; } - auto& v = boost::any_cast(value); + auto& v = from_value(value); auto find_serialized_size = [] (auto&& t_v) { const data_type& t = boost::get<0>(t_v); - const boost::any& v = boost::get<1>(t_v); - return 4 + (v.empty() ? 0 : t->serialized_size(v)); + const data_value& v = boost::get<1>(t_v); + if (!v.is_null() && t != v.type()) { + throw std::runtime_error("tuple element type mismatch"); + } + return 4 + (v.is_null() ? 0 : t->serialized_size(t->get_value_ptr(v))); }; return boost::accumulate(boost::combine(_types, v) | boost::adaptors::transformed(find_serialized_size), 0); } void -tuple_type_impl::serialize(const boost::any& value, bytes::iterator& out) const { - if (value.empty()) { +tuple_type_impl::serialize(const void* value, bytes::iterator& out) const { + if (!value) { return; } - auto& v = boost::any_cast(value); + auto& v = from_value(value); auto do_serialize = [&out] (auto&& t_v) { const data_type& t = boost::get<0>(t_v); - const boost::any& v = boost::get<1>(t_v); - if (v.empty()) { + const data_value& v = boost::get<1>(t_v); + if (!v.is_null() && t != v.type()) { + throw std::runtime_error("tuple element type mismatch"); + } + if (v.is_null()) { write(out, int32_t(-1)); } else { - write(out, int32_t(t->serialized_size(v))); - t->serialize(v, out); + write(out, int32_t(t->serialized_size(t->get_value_ptr(v)))); + t->serialize(t->get_value_ptr(v), out); } }; boost::range::for_each(boost::combine(_types, v), do_serialize); } -boost::any +data_value tuple_type_impl::deserialize(bytes_view v) const { native_type ret; ret.reserve(_types.size()); auto ti = _types.begin(); auto vi = tuple_deserializing_iterator::start(v); while (ti != _types.end() && vi != tuple_deserializing_iterator::finish(v)) { - boost::any obj; + data_value obj = data_value::make_null(*ti); if (*vi) { obj = (*ti)->deserialize(**vi); } @@ -2176,8 +2246,10 @@ tuple_type_impl::deserialize(bytes_view v) const { ++ti; ++vi; } - ret.resize(_types.size()); - return { ret }; + while (ti != _types.end()) { + ret.push_back(data_value::make_null(*ti++)); + } + return make_value(std::move(ret)); } std::vector @@ -2251,7 +2323,8 @@ tuple_type_impl::make_name(const std::vector& types) { sstring user_type_impl::get_name_as_string() const { - return boost::any_cast(utf8_type->deserialize(_name)); + auto real_utf8_type = static_cast(utf8_type.get()); + return real_utf8_type->from_value(utf8_type->deserialize(_name)); } shared_ptr @@ -2272,6 +2345,46 @@ user_type_impl::make_name(sstring keyspace, bytes name, std::vector field return os.str(); } +size_t +reversed_type_impl::native_value_size() const { + return _underlying_type->native_value_size(); +} + +size_t +reversed_type_impl::native_value_alignment() const { + return _underlying_type->native_value_alignment(); +} + +void +reversed_type_impl::native_value_copy(const void* from, void* to) const { + return _underlying_type->native_value_copy(from, to); +} + +void +reversed_type_impl::native_value_move(const void* from, void* to) const { + return _underlying_type->native_value_move(from, to); +} + +void +reversed_type_impl::native_value_destroy(void* object) const { + return _underlying_type->native_value_destroy(object); +} + +void* +reversed_type_impl::native_value_clone(const void* object) const { + return _underlying_type->native_value_clone(object); +} + +void +reversed_type_impl::native_value_delete(void* object) const { + return _underlying_type->native_value_delete(object); +} + +const std::type_info& +reversed_type_impl::native_typeid() const { + return _underlying_type->native_typeid(); +} + thread_local const shared_ptr int32_type(make_shared()); thread_local const shared_ptr long_type(make_shared()); thread_local const shared_ptr ascii_type(make_shared()); @@ -2316,3 +2429,82 @@ data_type abstract_type::parse_type(const sstring& name) } return it->second; } + +data_value::~data_value() { + if (_value) { + _type->native_value_delete(_value); + } +} + +data_value::data_value(const data_value& v) : _value(nullptr), _type(v._type) { + if (v._value) { + _value = _type->native_value_clone(v._value); + } +} + +data_value& +data_value::operator=(data_value&& x) { + auto tmp = std::move(x); + std::swap(tmp._value, this->_value); + std::swap(tmp._type, this->_type); + return *this; +} + +data_value::data_value(bytes v) : data_value(make_new(bytes_type, v)) { +} + +data_value::data_value(sstring v) : data_value(make_new(utf8_type, v)) { +} + +data_value::data_value(int32_t v) : data_value(make_new(int32_type, v)) { +} + +data_value::data_value(int64_t v) : data_value(make_new(long_type, v)) { +} + +data_value::data_value(utils::UUID v) : data_value(make_new(uuid_type, v)) { +} + +data_value::data_value(float v) : data_value(make_new(float_type, v)) { +} + +data_value::data_value(double v) : data_value(make_new(double_type, v)) { +} + +data_value::data_value(net::ipv4_address v) : data_value(make_new(inet_addr_type, v)) { +} + +data_value::data_value(db_clock::time_point v) : data_value(make_new(date_type, v)) { +} + +data_value::data_value(boost::multiprecision::cpp_int v) : data_value(make_new(varint_type, v)) { +} + +data_value::data_value(big_decimal v) : data_value(make_new(decimal_type, v)) { +} + +data_value +make_list_value(data_type type, list_type_impl::native_type value) { + return data_value::make_new(std::move(type), std::move(value)); +} + +data_value +make_set_value(data_type type, set_type_impl::native_type value) { + return data_value::make_new(std::move(type), std::move(value)); +} + +data_value +make_map_value(data_type type, map_type_impl::native_type value) { + return data_value::make_new(std::move(type), std::move(value)); +} + +data_value +make_tuple_value(data_type type, tuple_type_impl::native_type value) { + return data_value::make_new(std::move(type), std::move(value)); +} + +data_value +make_user_value(data_type type, user_type_impl::native_type value) { + return data_value::make_new(std::move(type), std::move(value)); +} + diff --git a/types.hh b/types.hh index 0705eb5c9e..a2544dcf3c 100644 --- a/types.hh +++ b/types.hh @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include #include @@ -43,8 +42,10 @@ #include #include #include "net/ip.hh" +#include // FIXME: remove somehow class tuple_type_impl; +class big_decimal; namespace cql3 { @@ -188,25 +189,71 @@ inline int32_t compare_unsigned(bytes_view v1, bytes_view v2) { } class abstract_type; +class data_value; using data_type = shared_ptr; +template +const T& value_cast(const data_value& value); + +template +T&& value_cast(data_value&& value); + class data_value { - boost::any _value; + void* _value; // FIXME: use "small value optimization" for small types data_type _type; +private: + data_value(void* value, data_type type) : _value(value), _type(std::move(type)) {} + template + static data_value make_new(data_type type, T&& value); public: - data_value(boost::any&& value, data_type type) - : _value{std::move(value)} - , _type{type} - { } - const boost::any& value() const { - return _value; + ~data_value(); + data_value(const data_value&); + data_value(data_value&& x) noexcept : _value(x._value), _type(std::move(x._type)) { + x._value = nullptr; } - data_type type() const { + // common conversions from C++ types to database types + // note: somewhat dangerous, consider a factory function instead + data_value(bytes); + data_value(sstring); + data_value(int32_t); + data_value(int64_t); + data_value(utils::UUID); + data_value(float); + data_value(double); + data_value(net::ipv4_address); + data_value(db_clock::time_point); + data_value(boost::multiprecision::cpp_int); + data_value(big_decimal); + template + data_value(std::experimental::optional); + + data_value& operator=(const data_value&); + data_value& operator=(data_value&&); + const data_type& type() const { return _type; } + bool is_null() const { // may return false negatives for strings etc. + return !_value; + } friend inline bool operator==(const data_value& x, const data_value& y); friend inline bool operator!=(const data_value& x, const data_value& y); + friend class abstract_type; + static data_value make_null(data_type type) { + return data_value(nullptr, std::move(type)); + } + template + static data_value make(data_type type, std::unique_ptr value) { + return data_value(value.release(), std::move(type)); + } + friend class empty_type_impl; + template friend const T& value_cast(const data_value&); + template friend T&& value_cast(data_value&&); + friend data_value make_tuple_value(data_type, std::vector); + friend data_value make_set_value(data_type, std::vector); + friend data_value make_list_value(data_type, std::vector); + friend data_value make_map_value(data_type, std::vector>); + friend data_value make_user_value(data_type, std::vector); }; class serialized_compare; @@ -216,8 +263,14 @@ class abstract_type : public enable_shared_from_this { public: abstract_type(sstring name) : _name(name) {} virtual ~abstract_type() {} - virtual void serialize(const boost::any& value, bytes::iterator& out) const = 0; - virtual size_t serialized_size(const boost::any& value) const = 0; + virtual void serialize(const void* value, bytes::iterator& out) const = 0; + void serialize(const data_value& value, bytes::iterator& out) const { + return serialize(get_value_ptr(value), out); + } + virtual size_t serialized_size(const void* value) const = 0; + size_t serialized_size(const data_value& value) const { + return serialized_size(get_value_ptr(value)); + } virtual bool less(bytes_view v1, bytes_view v2) const = 0; // returns a callable that can be called with two byte_views, and calls this->less() on them. serialized_compare as_less_comparator() const ; @@ -238,9 +291,9 @@ public: return 0; } } - virtual boost::any deserialize(bytes_view v) const = 0; + virtual data_value deserialize(bytes_view v) const = 0; data_value deserialize_value(bytes_view v) const { - return data_value{deserialize(v), shared_from_this()}; + return deserialize(v); }; virtual void validate(bytes_view v) const { // FIXME @@ -287,10 +340,13 @@ protected: return is_compatible_with(other); } public: - bytes decompose(const boost::any& value) const { - bytes b(bytes::initialized_later(), serialized_size(value)); + bytes decompose(const data_value& value) const { + if (!value._value) { + return {}; + } + bytes b(bytes::initialized_later(), serialized_size(value._value)); auto i = b.begin(); - serialize(value, i); + serialize(value._value, i); return b; } sstring name() const { @@ -324,11 +380,112 @@ public: virtual ::shared_ptr as_cql3_type() const = 0; virtual shared_ptr freeze() const { return shared_from_this(); } friend class list_type_impl; +protected: + // native_value_* methods are virualized versions of native_type's + // sizeof/alignof/copy-ctor/move-ctor etc. + virtual size_t native_value_size() const = 0; + virtual size_t native_value_alignment() const = 0; + virtual void native_value_copy(const void* from, void* to) const = 0; + virtual void native_value_move(const void* from, void* to) const = 0; + virtual void* native_value_clone(const void* from) const = 0; + virtual void native_value_destroy(void* object) const = 0; + virtual void native_value_delete(void* object) const = 0; + virtual const std::type_info& native_typeid() const = 0; + // abstract_type is a friend of data_value, but derived classes are not. + static const void* get_value_ptr(const data_value& v) { + return v._value; + } + friend void write_collection_value(bytes::iterator& out, serialization_format sf, data_type type, const data_value& value); + friend class tuple_type_impl; + friend class data_value; + friend class reversed_type_impl; + template friend const T& value_cast(const data_value& value); + template friend T&& value_cast(data_value&& value); +}; + +template +data_value +data_value::make_new(data_type type, T&& value) { + return data_value(type->native_value_clone(&value), type); +} + +template +const T& value_cast(const data_value& value) { + if (typeid(T) != value.type()->native_typeid()) { + throw std::bad_cast(); + } + if (value.is_null()) { + throw std::runtime_error("value is null"); + } + return *reinterpret_cast(value._value); +} + +template +T&& value_cast(data_value&& value) { + if (typeid(T) != value.type()->native_typeid()) { + throw std::bad_cast(); + } + if (value.is_null()) { + throw std::runtime_error("value is null"); + } + return std::move(*reinterpret_cast(value._value)); +} + +// CRTP: implements translation between a native_type (C++ type) to abstract_type +// AbstractType is parametrized because we want a +// abstract_type -> collection_type_impl -> map_type +// type hierarchy, and native_type is only known at the last step. +template +class concrete_type : public AbstractType { +public: + using native_type = NativeType; + using AbstractType::AbstractType; +protected: + virtual size_t native_value_size() const override { + return sizeof(native_type); + } + virtual size_t native_value_alignment() const override { + return alignof(native_type); + } + virtual void native_value_copy(const void* from, void* to) const override { + new (to) native_type(*reinterpret_cast(from)); + } + virtual void native_value_move(const void* from, void* to) const override { + new (to) native_type(std::move(*reinterpret_cast(from))); + } + virtual void native_value_destroy(void* object) const override { + reinterpret_cast(object)->~native_type(); + } + virtual void native_value_delete(void* object) const override { + delete reinterpret_cast(object); + } + virtual void* native_value_clone(const void* object) const override { + return new native_type(*reinterpret_cast(object)); + } + virtual const std::type_info& native_typeid() const override { + return typeid(native_type); + } +protected: + data_value make_value(std::unique_ptr value) const { + return data_value::make(this->shared_from_this(), std::move(value)); + } + data_value make_value(NativeType value) const { + return make_value(std::make_unique(std::move(value))); + } + data_value make_null() const { + return data_value::make_null(this->shared_from_this()); + } + const NativeType& from_value(const void* v) const { + return *reinterpret_cast(v); + } + const NativeType& from_value(const data_value& v) const { + return this->from_value(AbstractType::get_value_ptr(v)); + } }; inline bool operator==(const data_value& x, const data_value& y) { - return x._type->equals(y._type) && x._type->equal(x._type->decompose(x._value), y._type->decompose(y._value)); + return x._type->equals(y._type) && x._type->equal(x._type->decompose(x), y._type->decompose(y)); } inline bool operator!=(const data_value& x, const data_value& y) @@ -448,10 +605,10 @@ public: collection_mutation::one serialize_mutation_form_only_live(mutation_view mut, gc_clock::time_point now) const; collection_mutation::one merge(collection_mutation::view a, collection_mutation::view b) const; collection_mutation::one difference(collection_mutation::view a, collection_mutation::view b) const; - virtual void serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const = 0; - virtual boost::any deserialize(bytes_view v, serialization_format sf) const = 0; + virtual void serialize(const void* value, bytes::iterator& out, serialization_format sf) const = 0; + virtual data_value deserialize(bytes_view v, serialization_format sf) const = 0; data_value deserialize_value(bytes_view v, serialization_format sf) const { - return data_value{deserialize(v, sf), shared_from_this()}; + return deserialize(v, sf); } bytes_opt reserialize(serialization_format from, serialization_format to, bytes_view_opt v) const; }; @@ -563,13 +720,13 @@ public: return _underlying_type->is_multi_cell(); } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override { + virtual void serialize(const void* value, bytes::iterator& out) const override { _underlying_type->serialize(value, out); } - virtual size_t serialized_size(const boost::any& value) const { + virtual size_t serialized_size(const void* value) const override { return _underlying_type->serialized_size(value); } - virtual boost::any deserialize(bytes_view v) const override { + virtual data_value deserialize(bytes_view v) const override { return _underlying_type->deserialize(v); } @@ -590,10 +747,22 @@ public: static shared_ptr get_instance(data_type type) { return intern::get_instance(std::move(type)); } +protected: + virtual size_t native_value_size() const override; + virtual size_t native_value_alignment() const override; + virtual void native_value_copy(const void* from, void* to) const override; + virtual void native_value_move(const void* from, void* to) const override; + virtual void native_value_destroy(void* object) const override; + virtual void* native_value_clone(const void* object) const override; + virtual void native_value_delete(void* object) const override; + virtual const std::type_info& native_typeid() const override; }; using reversed_type = shared_ptr; -class map_type_impl final : public collection_type_impl { +template +using concrete_collection_type = concrete_type; + +class map_type_impl final : public concrete_collection_type>> { using map_type = shared_ptr; using intern = type_interning_helper; data_type _keys; @@ -603,9 +772,6 @@ class map_type_impl final : public collection_type_impl { protected: virtual sstring cql3_type_name() const override; public: - // type returned by deserialize() and expected by serialize - // does not support mutations/ttl/tombstone - purely for I/O. - using native_type = std::vector>; static shared_ptr get_instance(data_type keys, data_type values, bool is_multi_cell); map_type_impl(data_type keys, data_type values, bool is_multi_cell); data_type get_keys_type() const { return _keys; } @@ -620,11 +786,11 @@ public: static int32_t compare_maps(data_type keys_comparator, data_type values_comparator, bytes_view o1, bytes_view o2); virtual bool is_byte_order_comparable() const override { return false; } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override; - virtual void serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const override; - virtual size_t serialized_size(const boost::any& value) const; - virtual boost::any deserialize(bytes_view v) const override; - virtual boost::any deserialize(bytes_view v, serialization_format sf) const override; + virtual void serialize(const void* value, bytes::iterator& out) const override; + virtual void serialize(const void* value, bytes::iterator& out, serialization_format sf) const override; + virtual size_t serialized_size(const void* value) const; + virtual data_value deserialize(bytes_view v) const override; + virtual data_value deserialize(bytes_view v, serialization_format sf) const override; virtual sstring to_string(const bytes& b) const override; virtual size_t hash(bytes_view v) const override; virtual bytes from_string(sstring_view text) const override; @@ -636,7 +802,9 @@ public: using map_type = shared_ptr; -class set_type_impl final : public collection_type_impl { +data_value make_map_value(data_type tuple_type, map_type_impl::native_type value); + +class set_type_impl final : public concrete_collection_type> { using set_type = shared_ptr; using intern = type_interning_helper; data_type _elements; @@ -644,9 +812,6 @@ class set_type_impl final : public collection_type_impl { protected: virtual sstring cql3_type_name() const override; public: - // type returned by deserialize() and expected by serialize - // does not support mutations/ttl/tombstone - purely for I/O. - using native_type = std::vector; static set_type get_instance(data_type elements, bool is_multi_cell); set_type_impl(data_type elements, bool is_multi_cell); data_type get_elements_type() const { return _elements; } @@ -658,11 +823,11 @@ public: virtual bool is_value_compatible_with_frozen(const collection_type_impl& previous) const override; virtual bool less(bytes_view o1, bytes_view o2) const override; virtual bool is_byte_order_comparable() const override { return _elements->is_byte_order_comparable(); } - virtual void serialize(const boost::any& value, bytes::iterator& out) const override; - virtual void serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const override; - virtual size_t serialized_size(const boost::any& value) const override; - virtual boost::any deserialize(bytes_view v) const override; - virtual boost::any deserialize(bytes_view v, serialization_format sf) const override; + virtual void serialize(const void* value, bytes::iterator& out) const override; + virtual void serialize(const void* value, bytes::iterator& out, serialization_format sf) const override; + virtual size_t serialized_size(const void* value) const override; + virtual data_value deserialize(bytes_view v) const override; + virtual data_value deserialize(bytes_view v, serialization_format sf) const override; virtual sstring to_string(const bytes& b) const override; virtual size_t hash(bytes_view v) const override; virtual bytes from_string(sstring_view text) const override; @@ -670,12 +835,13 @@ public: virtual bytes to_value(mutation_view mut, serialization_format sf) const override; bytes serialize_partially_deserialized_form( const std::vector& v, serialization_format sf) const; - }; using set_type = shared_ptr; -class list_type_impl final : public collection_type_impl { +data_value make_set_value(data_type tuple_type, set_type_impl::native_type value); + +class list_type_impl final : public concrete_collection_type> { using list_type = shared_ptr; using intern = type_interning_helper; data_type _elements; @@ -683,9 +849,6 @@ class list_type_impl final : public collection_type_impl { protected: virtual sstring cql3_type_name() const override; public: - // type returned by deserialize() and expected by serialize - // does not support mutations/ttl/tombstone - purely for I/O. - using native_type = std::vector; static list_type get_instance(data_type elements, bool is_multi_cell); list_type_impl(data_type elements, bool is_multi_cell); data_type get_elements_type() const { return _elements; } @@ -697,11 +860,11 @@ public: virtual bool is_value_compatible_with_frozen(const collection_type_impl& previous) const override; virtual bool less(bytes_view o1, bytes_view o2) const override; // FIXME: origin doesn't override is_byte_order_comparable(). Why? - virtual void serialize(const boost::any& value, bytes::iterator& out) const override; - virtual void serialize(const boost::any& value, bytes::iterator& out, serialization_format sf) const override; - virtual size_t serialized_size(const boost::any& value) const override; - virtual boost::any deserialize(bytes_view v) const override; - virtual boost::any deserialize(bytes_view v, serialization_format sf) const override; + virtual void serialize(const void* value, bytes::iterator& out) const override; + virtual void serialize(const void* value, bytes::iterator& out, serialization_format sf) const override; + virtual size_t serialized_size(const void* value) const override; + virtual data_value deserialize(bytes_view v) const override; + virtual data_value deserialize(bytes_view v, serialization_format sf) const override; virtual sstring to_string(const bytes& b) const override; virtual size_t hash(bytes_view v) const override; virtual bytes from_string(sstring_view text) const override; @@ -711,6 +874,8 @@ public: using list_type = shared_ptr; +data_value make_list_value(data_type type, list_type_impl::native_type value); + inline size_t hash_value(const shared_ptr& x) { return std::hash()(x.get()); @@ -945,7 +1110,7 @@ read_simple_bytes(bytes_view& v, size_t n) { } template -boost::any read_simple_opt(bytes_view& v) { +std::experimental::optional read_simple_opt(bytes_view& v) { if (v.empty()) { return {}; } @@ -954,7 +1119,7 @@ boost::any read_simple_opt(bytes_view& v) { } auto p = v.begin(); v.remove_prefix(sizeof(T)); - return boost::any(net::ntoh(*reinterpret_cast*>(p))); + return { net::ntoh(*reinterpret_cast*>(p)) }; } inline sstring read_simple_short_string(bytes_view& v) { @@ -972,7 +1137,7 @@ size_t collection_size_len(serialization_format sf); size_t collection_value_len(serialization_format sf); void write_collection_size(bytes::iterator& out, int size, serialization_format sf); void write_collection_value(bytes::iterator& out, serialization_format sf, bytes_view val_bytes); -void write_collection_value(bytes::iterator& out, serialization_format sf, data_type type, const boost::any& value); +void write_collection_value(bytes::iterator& out, serialization_format sf, data_type type, const data_value& value); template bytes @@ -1050,7 +1215,7 @@ private: } }; -class tuple_type_impl : public abstract_type { +class tuple_type_impl : public concrete_type> { protected: std::vector _types; static boost::iterator_range make_range(bytes_view v) { @@ -1058,7 +1223,6 @@ protected: } tuple_type_impl(sstring name, std::vector types); public: - using native_type = std::vector; tuple_type_impl(std::vector types); static shared_ptr get_instance(std::vector types); data_type type(size_t i) const { @@ -1072,9 +1236,9 @@ public: } virtual int32_t compare(bytes_view v1, bytes_view v2) const override; virtual bool less(bytes_view v1, bytes_view v2) const override; - virtual size_t serialized_size(const boost::any& value) const override; - virtual void serialize(const boost::any& value, bytes::iterator& out) const override; - virtual boost::any deserialize(bytes_view v) const override; + virtual size_t serialized_size(const void* value) const override; + virtual void serialize(const void* value, bytes::iterator& out) const override; + virtual data_value deserialize(bytes_view v) const override; std::vector split(bytes_view v) const; template // also accepts bytes_view_opt static bytes build_value(RangeOf_bytes_opt&& range) { @@ -1106,6 +1270,8 @@ private: static sstring make_name(const std::vector& types); }; +data_value make_tuple_value(data_type tuple_type, tuple_type_impl::native_type value); + class user_type_impl : public tuple_type_impl { public: const sstring _keyspace; @@ -1113,6 +1279,7 @@ public: private: std::vector _field_names; public: + using native_type = std::vector; user_type_impl(sstring keyspace, bytes name, std::vector field_names, std::vector field_types) : tuple_type_impl(make_name(keyspace, name, field_names, field_types), field_types) , _keyspace(keyspace) @@ -1132,5 +1299,13 @@ private: static sstring make_name(sstring keyspace, bytes name, std::vector field_names, std::vector field_types); }; +data_value make_user_value(data_type tuple_type, user_type_impl::native_type value); + using user_type = shared_ptr; using tuple_type = shared_ptr; + +template +data_value::data_value(std::experimental::optional v) + : data_value(v ? data_value(*v) : data_value::make_null(data_type_for())) { +} +