schema: introduce make_reversed()

`make_revered()` creates a schema identical to the schema instance it is
called on, with clustering order reversed. To distinguish the reverse
schema from the original one, the node-id part of its version UUID is
bit-flipped. This ensures that reversing a schema twice will result in
the identical schema to the original one (although a different C++
object).

This reversed schema will be used in reversed reads, so intermediate
layers can be ignorant of the fact that the read happens in reverse.
This commit is contained in:
Botond Dénes
2021-08-09 13:06:28 +03:00
parent 9a9b58e67b
commit f200c8104a
3 changed files with 59 additions and 2 deletions

View File

@@ -439,6 +439,18 @@ schema::schema(const schema& o)
{
}
schema::schema(reversed_tag, const schema& o)
: schema(o, [] (schema& s) {
s._raw._version = utils::UUID_gen::negate(s._raw._version);
for (auto& col : s._raw._columns) {
if (col.kind == column_kind::clustering_key) {
col.type = reversed(col.type);
}
}
})
{
}
lw_shared_ptr<const schema> make_shared_schema(std::optional<utils::UUID> id, std::string_view ks_name,
std::string_view cf_name, std::vector<schema::column> partition_key, std::vector<schema::column> clustering_key,
std::vector<schema::column> regular_columns, std::vector<schema::column> static_columns,
@@ -1579,6 +1591,10 @@ bool schema::equal_columns(const schema& other) const {
return boost::equal(all_columns(), other.all_columns());
}
schema_ptr schema::make_reversed() const {
return make_lw_shared<schema>(schema::reversed_tag{}, *this);
}
raw_view_info::raw_view_info(utils::UUID base_id, sstring base_name, bool include_all_columns, sstring where_clause)
: _base_id(std::move(base_id))
, _base_name(std::move(base_name))

View File

@@ -584,6 +584,10 @@ public:
}
};
class schema;
using schema_ptr = lw_shared_ptr<const schema>;
/*
* Effectively immutable.
* Not safe to access across cores because of shared_ptr's.
@@ -695,12 +699,16 @@ public:
data_type type;
};
private:
struct reversed_tag { };
lw_shared_ptr<cql3::column_specification> make_column_specification(const column_definition& def);
void rebuild();
schema(const raw_schema&, std::optional<raw_view_info>);
schema(const schema&, const std::function<void(schema&)>&);
public:
schema(const schema&);
// See \ref make_reversed().
schema(reversed_tag, const schema&);
~schema();
table_schema_version version() const {
return _raw._version;
@@ -967,6 +975,17 @@ public:
const v3_columns& v3() const {
return _v3_columns;
}
// Make a copy of the schema with reversed clustering order.
//
// The reversing is revertible, so that:
//
// s->make_reversed()->make_reversed()->version() == s->version()
//
// But note that: `s != s->make_reversed()->make_reversed()` (they are two
// different C++ objects).
// The schema's version is also reversed using UUID_gen::negate().
schema_ptr make_reversed() const;
};
lw_shared_ptr<const schema> make_shared_schema(std::optional<utils::UUID> id, std::string_view ks_name, std::string_view cf_name,
@@ -975,8 +994,6 @@ lw_shared_ptr<const schema> make_shared_schema(std::optional<utils::UUID> id, st
bool operator==(const schema&, const schema&);
using schema_ptr = lw_shared_ptr<const schema>;
/**
* Wrapper for schema_ptr used by functions that expect an engaged view_info field.
*/

View File

@@ -42,6 +42,7 @@
#include "test/lib/log.hh"
#include "serializer_impl.hh"
#include "cdc/cdc_extension.hh"
#include "utils/UUID_gen.hh"
SEASTAR_TEST_CASE(test_new_schema_with_no_structural_change_is_propagated) {
return do_with_cql_env([](cql_test_env& e) {
@@ -807,3 +808,26 @@ SEASTAR_TEST_CASE(test_schema_tables_use_null_sharder) {
}).get();
}, raft_cql_test_config());
}
SEASTAR_TEST_CASE(test_schema_make_reversed) {
auto schema = schema_builder("tests", get_name())
.with_column("pk", bytes_type, column_kind::partition_key)
.with_column("ck", bytes_type, column_kind::clustering_key)
.with_column("v1", bytes_type)
.build();
testlog.info(" schema->version(): {}", schema->version());
auto reversed_schema = schema->make_reversed();
testlog.info(" reversed_schema->version(): {}", reversed_schema->version());
BOOST_REQUIRE(schema->version() != reversed_schema->version());
BOOST_REQUIRE(utils::UUID_gen::negate(schema->version()) == reversed_schema->version());
auto re_reversed_schema = reversed_schema->make_reversed();
testlog.info("re_reversed_schema->version(): {}", re_reversed_schema->version());
BOOST_REQUIRE(schema->version() == re_reversed_schema->version());
BOOST_REQUIRE(reversed_schema->version() != re_reversed_schema->version());
return make_ready_future<>();
}