mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-21 00:50:35 +00:00
Merge "Query result set comparison support"
Pekka says: "This series adds comparison operators for query result sets that are needed by schema merging code. The operators are implemented using a newly added "data_value" type that encodes the type of the value."
This commit is contained in:
@@ -29,7 +29,7 @@ void result_set_builder::accept_new_row(const clustering_key& key, const result_
|
||||
auto static_cells = deserialize(static_row, true);
|
||||
auto regular_cells = deserialize(row, false);
|
||||
|
||||
std::unordered_map<sstring, boost::any> cells;
|
||||
std::unordered_map<sstring, data_value> cells;
|
||||
cells.insert(_pkey_cells.begin(), _pkey_cells.end());
|
||||
cells.insert(ckey_cells.begin(), ckey_cells.end());
|
||||
cells.insert(static_cells.begin(), static_cells.end());
|
||||
@@ -42,7 +42,7 @@ void result_set_builder::accept_new_row(const query::result_row_view &static_row
|
||||
auto static_cells = deserialize(static_row, true);
|
||||
auto regular_cells = deserialize(row, false);
|
||||
|
||||
std::unordered_map<sstring, boost::any> cells;
|
||||
std::unordered_map<sstring, data_value> cells;
|
||||
cells.insert(_pkey_cells.begin(), _pkey_cells.end());
|
||||
cells.insert(static_cells.begin(), static_cells.end());
|
||||
cells.insert(regular_cells.begin(), regular_cells.end());
|
||||
@@ -54,34 +54,34 @@ void result_set_builder::accept_partition_end(const result_row_view& static_row)
|
||||
_pkey_cells.clear();
|
||||
}
|
||||
|
||||
std::unordered_map<sstring, boost::any>
|
||||
std::unordered_map<sstring, data_value>
|
||||
result_set_builder::deserialize(const partition_key& key)
|
||||
{
|
||||
std::unordered_map<sstring, boost::any> cells;
|
||||
std::unordered_map<sstring, data_value> cells;
|
||||
auto i = key.begin(*_schema);
|
||||
for (auto&& col : _schema->partition_key_columns()) {
|
||||
cells.emplace(col.name_as_text(), col.type->deserialize(*i));
|
||||
cells.emplace(col.name_as_text(), col.type->deserialize_value(*i));
|
||||
++i;
|
||||
}
|
||||
return cells;
|
||||
}
|
||||
|
||||
std::unordered_map<sstring, boost::any>
|
||||
std::unordered_map<sstring, data_value>
|
||||
result_set_builder::deserialize(const clustering_key& key)
|
||||
{
|
||||
std::unordered_map<sstring, boost::any> cells;
|
||||
std::unordered_map<sstring, data_value> cells;
|
||||
auto i = key.begin(*_schema);
|
||||
for (auto&& col : _schema->clustering_key_columns()) {
|
||||
cells.emplace(col.name_as_text(), col.type->deserialize(*i));
|
||||
cells.emplace(col.name_as_text(), col.type->deserialize_value(*i));
|
||||
++i;
|
||||
}
|
||||
return cells;
|
||||
}
|
||||
|
||||
std::unordered_map<sstring, boost::any>
|
||||
std::unordered_map<sstring, data_value>
|
||||
result_set_builder::deserialize(const result_row_view& row, bool is_static)
|
||||
{
|
||||
std::unordered_map<sstring, boost::any> cells;
|
||||
std::unordered_map<sstring, data_value> cells;
|
||||
auto i = row.iterator();
|
||||
auto columns = is_static ? _schema->static_columns() : _schema->regular_columns();
|
||||
for (auto &&col : columns) {
|
||||
@@ -89,14 +89,14 @@ result_set_builder::deserialize(const result_row_view& row, bool is_static)
|
||||
auto cell = i.next_atomic_cell();
|
||||
if (cell) {
|
||||
auto view = cell.value();
|
||||
cells.emplace(col.name_as_text(), col.type->deserialize(view.value()));
|
||||
cells.emplace(col.name_as_text(), col.type->deserialize_value(view.value()));
|
||||
}
|
||||
} else {
|
||||
auto cell = i.next_collection_cell();
|
||||
if (cell) {
|
||||
auto ctype = static_pointer_cast<const collection_type_impl>(col.type);
|
||||
auto view = cell.value();
|
||||
cells.emplace(col.name_as_text(), ctype->deserialize(view.data, serialization_format::internal()));
|
||||
cells.emplace(col.name_as_text(), ctype->deserialize_value(view.data, serialization_format::internal()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ public:
|
||||
// including regular column cells, partition keys, as well as static values.
|
||||
class result_set_row {
|
||||
schema_ptr _schema;
|
||||
std::unordered_map<sstring, boost::any> _cells;
|
||||
std::unordered_map<sstring, data_value> _cells;
|
||||
public:
|
||||
result_set_row(schema_ptr schema, std::unordered_map<sstring, boost::any>&& cells)
|
||||
result_set_row(schema_ptr schema, std::unordered_map<sstring, data_value>&& cells)
|
||||
: _schema{schema}
|
||||
, _cells{std::move(cells)}
|
||||
{ }
|
||||
@@ -43,10 +43,11 @@ public:
|
||||
if (it == _cells.end()) {
|
||||
throw no_such_column(column_name);
|
||||
}
|
||||
if (it->second.empty()) {
|
||||
auto&& value = it->second.value();
|
||||
if (value.empty()) {
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
return std::experimental::optional<T>{boost::any_cast<T>(it->second)};
|
||||
return std::experimental::optional<T>{boost::any_cast<T>(value)};
|
||||
}
|
||||
template<typename T>
|
||||
T get_nonnull(const sstring& column_name) const throw (no_such_column, null_column_value) {
|
||||
@@ -56,8 +57,18 @@ public:
|
||||
}
|
||||
throw null_column_value(column_name);
|
||||
}
|
||||
friend inline bool operator==(const result_set_row& x, const result_set_row& y);
|
||||
friend inline bool operator!=(const result_set_row& x, const result_set_row& y);
|
||||
};
|
||||
|
||||
inline bool operator==(const result_set_row& x, const result_set_row& y) {
|
||||
return x._schema == y._schema && x._cells == y._cells;
|
||||
}
|
||||
|
||||
inline bool operator!=(const result_set_row& x, const result_set_row& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
// Result set is an in-memory representation of query results in
|
||||
// deserialized format. To obtain a result set, use the result_set_builder
|
||||
// class as a visitor to query_result::consume() function.
|
||||
@@ -76,15 +87,20 @@ public:
|
||||
}
|
||||
return _rows[idx];
|
||||
}
|
||||
friend inline bool operator==(const result_set& x, const result_set& y);
|
||||
};
|
||||
|
||||
inline bool operator==(const result_set& x, const result_set& y) {
|
||||
return x._rows == y._rows;
|
||||
}
|
||||
|
||||
// Result set builder is passed as a visitor to query_result::consume()
|
||||
// function. You can call the build() method to obtain a result set that
|
||||
// contains cells from the visited results.
|
||||
class result_set_builder {
|
||||
schema_ptr _schema;
|
||||
std::vector<result_set_row> _rows;
|
||||
std::unordered_map<sstring, boost::any> _pkey_cells;
|
||||
std::unordered_map<sstring, data_value> _pkey_cells;
|
||||
public:
|
||||
result_set_builder(schema_ptr schema);
|
||||
lw_shared_ptr<result_set> build() const;
|
||||
@@ -94,9 +110,9 @@ public:
|
||||
void accept_new_row(const result_row_view &static_row, const result_row_view &row);
|
||||
void accept_partition_end(const result_row_view& static_row);
|
||||
private:
|
||||
std::unordered_map<sstring, boost::any> deserialize(const partition_key& key);
|
||||
std::unordered_map<sstring, boost::any> deserialize(const clustering_key& key);
|
||||
std::unordered_map<sstring, boost::any> deserialize(const result_row_view& row, bool is_static);
|
||||
std::unordered_map<sstring, data_value> deserialize(const partition_key& key);
|
||||
std::unordered_map<sstring, data_value> deserialize(const clustering_key& key);
|
||||
std::unordered_map<sstring, data_value> deserialize(const result_row_view& row, bool is_static);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
42
types.hh
42
types.hh
@@ -169,6 +169,28 @@ inline int32_t compare_unsigned(bytes_view v1, bytes_view v2) {
|
||||
return (int32_t) (v1.size() - v2.size());
|
||||
}
|
||||
|
||||
class abstract_type;
|
||||
|
||||
using data_type = shared_ptr<const abstract_type>;
|
||||
|
||||
class data_value {
|
||||
boost::any _value;
|
||||
data_type _type;
|
||||
public:
|
||||
data_value(boost::any&& value, data_type type)
|
||||
: _value{std::move(value)}
|
||||
, _type{type}
|
||||
{ }
|
||||
const boost::any& value() const {
|
||||
return _value;
|
||||
}
|
||||
data_type type() const {
|
||||
return _type;
|
||||
}
|
||||
friend inline bool operator==(const data_value& x, const data_value& y);
|
||||
friend inline bool operator!=(const data_value& x, const data_value& y);
|
||||
};
|
||||
|
||||
class serialized_compare;
|
||||
|
||||
class abstract_type : public enable_shared_from_this<abstract_type> {
|
||||
@@ -198,6 +220,9 @@ public:
|
||||
}
|
||||
}
|
||||
virtual boost::any deserialize(bytes_view v) const = 0;
|
||||
data_value deserialize_value(bytes_view v) const {
|
||||
return data_value{deserialize(v), shared_from_this()};
|
||||
};
|
||||
virtual void validate(bytes_view v) const {
|
||||
// FIXME
|
||||
}
|
||||
@@ -246,6 +271,9 @@ public:
|
||||
virtual boost::any compose(const bytes& v) const {
|
||||
return deserialize(v);
|
||||
}
|
||||
data_value compose_value(const bytes& v) const {
|
||||
return deserialize_value(v);
|
||||
}
|
||||
bytes decompose(const boost::any& value) const {
|
||||
bytes b(bytes::initialized_later(), serialized_size(value));
|
||||
auto i = b.begin();
|
||||
@@ -284,7 +312,16 @@ public:
|
||||
friend class list_type_impl;
|
||||
};
|
||||
|
||||
using data_type = shared_ptr<const abstract_type>;
|
||||
inline bool operator==(const data_value& x, const data_value& y)
|
||||
{
|
||||
return x._type == y._type && x._type->decompose(x._value) == y._type->decompose(y._value);
|
||||
}
|
||||
|
||||
inline bool operator!=(const data_value& x, const data_value& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
using bytes_view_opt = std::experimental::optional<bytes_view>;
|
||||
|
||||
static inline
|
||||
@@ -394,6 +431,9 @@ public:
|
||||
collection_mutation::one merge(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;
|
||||
data_value deserialize_value(bytes_view v, serialization_format sf) const {
|
||||
return data_value{deserialize(v, sf), shared_from_this()};
|
||||
}
|
||||
bytes_opt reserialize(serialization_format from, serialization_format to, bytes_view_opt v) const;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user