Compare commits

..

4 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
0afb6b8fb6 Fix missing include for schema.hh in system0_virtual_tables.cc
Co-authored-by: tgrabiec <283695+tgrabiec@users.noreply.github.com>
2025-12-05 16:19:36 +00:00
copilot-swe-agent[bot]
03733ffa1b Simplify system0_virtual_tables implementation
Co-authored-by: tgrabiec <283695+tgrabiec@users.noreply.github.com>
2025-12-05 16:17:19 +00:00
copilot-swe-agent[bot]
780243790e Add system0 virtual tables for group0 updates (initial implementation)
Co-authored-by: tgrabiec <283695+tgrabiec@users.noreply.github.com>
2025-12-05 16:14:31 +00:00
copilot-swe-agent[bot]
1125175b51 Initial plan 2025-12-05 16:01:22 +00:00
12 changed files with 328 additions and 130 deletions

View File

@@ -1,109 +0,0 @@
# Analysis of unimplemented::cause Enum Values
This document provides an analysis of the `unimplemented::cause` enum values after cleanup.
## Removed Unused Enum Values (20 values removed)
The following enum values had **zero usages** in the codebase and have been removed:
- `LWT` - Lightweight transactions
- `PAGING` - Query result paging
- `AUTH` - Authentication
- `PERMISSIONS` - Permission checking
- `COUNTERS` - Counter columns
- `MIGRATIONS` - Schema migrations
- `GOSSIP` - Gossip protocol
- `TOKEN_RESTRICTION` - Token-based restrictions
- `LEGACY_COMPOSITE_KEYS` - Legacy composite key handling
- `COLLECTION_RANGE_TOMBSTONES` - Collection range tombstones
- `RANGE_DELETES` - Range deletion operations
- `COMPRESSION` - Compression features
- `NONATOMIC` - Non-atomic operations
- `CONSISTENCY` - Consistency level handling
- `WRAP_AROUND` - Token wrap-around handling
- `STORAGE_SERVICE` - Storage service operations
- `SCHEMA_CHANGE` - Schema change operations
- `MIXED_CF` - Mixed column family operations
- `SSTABLE_FORMAT_M` - SSTable format M
## Remaining Enum Values (8 values kept)
### 1. `API` (4 usages)
**Impact**: REST API features that are not fully implemented.
**Usages**:
- `api/column_family.cc:1052` - Fails when `split_output` parameter is used in major compaction
- `api/compaction_manager.cc:100,146,216` - Warns when force_user_defined_compaction or related operations are called
**User Impact**: Some REST API endpoints for compaction management are stubs and will warn or fail.
### 2. `INDEXES` (6 usages)
**Impact**: Secondary index features not fully supported.
**Usages**:
- `api/column_family.cc:433,440,449,456` - Warns about index-related operations
- `cql3/restrictions/statement_restrictions.cc:1158` - Fails when attempting filtering on collection columns without proper indexing
- `cql3/statements/update_statement.cc:149` - Warns about index operations
**User Impact**: Some advanced secondary index features (especially filtering on collections) are not available.
### 3. `TRIGGERS` (2 usages)
**Impact**: Trigger support is not implemented.
**Usages**:
- `db/schema_tables.cc:2017` - Warns when loading trigger metadata from schema tables
- `service/storage_proxy.cc:4166` - Warns when processing trigger-related operations
**User Impact**: Cassandra triggers (stored procedures that execute on data changes) are not supported.
### 4. `METRICS` (1 usage)
**Impact**: Some query processor metrics are not collected.
**Usages**:
- `cql3/query_processor.cc:585` - Warns about missing metrics implementation
**User Impact**: Minor - some internal metrics may not be available.
### 5. `VALIDATION` (4 usages)
**Impact**: Schema validation checks are partially implemented.
**Usages**:
- `cql3/functions/token_fct.hh:38` - Warns about validation in token functions
- `cql3/statements/drop_keyspace_statement.cc:40` - Warns when dropping keyspace
- `cql3/statements/truncate_statement.cc:87` - Warns when truncating table
- `service/migration_manager.cc:750` - Warns during schema migrations
**User Impact**: Some schema validation checks are skipped (with warnings logged).
### 6. `REVERSED` (1 usage)
**Impact**: Reversed type support in CQL protocol.
**Usages**:
- `transport/server.cc:2085` - Fails when trying to use reversed types in CQL protocol
**User Impact**: Reversed types are not supported in the CQL protocol implementation.
### 7. `HINT` (1 usage)
**Impact**: Hint replaying is not implemented.
**Usages**:
- `db/batchlog_manager.cc:251` - Warns when attempting to replay hints
**User Impact**: Cassandra hints (temporary storage of writes when nodes are down) are not supported.
### 8. `SUPER` (2 usages)
**Impact**: Super column families are not supported.
**Usages**:
- `db/legacy_schema_migrator.cc:157` - Fails when encountering super column family in legacy schema
- `db/schema_tables.cc:2288` - Fails when encountering super column family in schema tables
**User Impact**: Super column families (legacy Cassandra feature) will cause errors if encountered in legacy data or schema migrations.
## Summary
- **Removed**: 20 unused enum values (76% reduction)
- **Kept**: 8 actively used enum values (24% remaining)
- **Total lines removed**: ~40 lines from enum definition and switch statement
The remaining enum values represent actual unimplemented features that users may encounter, with varying impacts ranging from warnings (TRIGGERS, METRICS, VALIDATION, HINT) to failures (API split_output, INDEXES on collections, REVERSED types, SUPER tables).

View File

@@ -1085,6 +1085,7 @@ scylla_core = (['message/messaging_service.cc',
'db/view/view_building_task_mutation_builder.cc',
'db/virtual_table.cc',
'db/virtual_tables.cc',
'db/system0_virtual_tables.cc',
'db/tablet_options.cc',
'db/object_storage_endpoint_param.cc',
'index/secondary_index_manager.cc',

View File

@@ -186,6 +186,10 @@ void alter_table_statement::add_column(const query_options&, const schema& schem
if (!schema.is_compound()) {
throw exceptions::invalid_request_exception("Cannot use non-frozen collections with a non-composite PRIMARY KEY");
}
if (schema.is_super()) {
throw exceptions::invalid_request_exception("Cannot use non-frozen collections with super column families");
}
// If there used to be a non-frozen collection column with the same name (that has been dropped),
// we could still have some data using the old type, and so we can't allow adding a collection

View File

@@ -152,8 +152,8 @@ public:
builder.with_version(sm.digest());
auto type_str = td.get_or("type", sstring("standard"));
if (type_str == "Super") {
cf_type cf = sstring_to_cf_type(td.get_or("type", sstring("standard")));
if (cf == cf_type::super) {
fail(unimplemented::cause::SUPER);
}
@@ -284,8 +284,13 @@ public:
if (kind_str == "compact_value") {
continue;
}
if (kind == column_kind::clustering_key && !is_compound) {
continue;
if (kind == column_kind::clustering_key) {
if (cf == cf_type::super && component_index != 0) {
continue;
}
if (cf != cf_type::super && !is_compound) {
continue;
}
}
}

View File

@@ -143,7 +143,7 @@ static computed_columns_map get_computed_columns(const schema_mutations& sm);
static std::vector<column_definition> create_columns_from_column_rows(
const query::result_set& rows, const sstring& keyspace,
const sstring& table, column_view_virtual is_view_virtual, const computed_columns_map& computed_columns,
const sstring& table, bool is_super, column_view_virtual is_view_virtual, const computed_columns_map& computed_columns,
const data_dictionary::user_types_storage& user_types);
@@ -1804,6 +1804,9 @@ static schema_mutations make_table_mutations(schema_ptr table, api::timestamp_ty
auto scylla_tables_mutation = make_scylla_tables_mutation(table, timestamp);
list_type_impl::native_type flags;
if (table->is_super()) {
flags.emplace_back("super");
}
if (table->is_dense()) {
flags.emplace_back("dense");
}
@@ -2277,6 +2280,7 @@ schema_ptr create_table_from_mutations(const schema_ctxt& ctxt, schema_mutations
auto id = table_id(table_row.get_nonnull<utils::UUID>("id"));
schema_builder builder{ks_name, cf_name, id};
auto cf = cf_type::standard;
auto is_dense = false;
auto is_counter = false;
auto is_compound = false;
@@ -2285,6 +2289,7 @@ schema_ptr create_table_from_mutations(const schema_ctxt& ctxt, schema_mutations
if (flags) {
for (auto& s : *flags) {
if (s == "super") {
// cf = cf_type::super;
fail(unimplemented::cause::SUPER);
} else if (s == "dense") {
is_dense = true;
@@ -2300,7 +2305,9 @@ schema_ptr create_table_from_mutations(const schema_ctxt& ctxt, schema_mutations
std::vector<column_definition> column_defs = create_columns_from_column_rows(
query::result_set(sm.columns_mutation()),
ks_name,
cf_name,
cf_name,/*,
fullRawComparator, */
cf == cf_type::super,
column_view_virtual::no,
computed_columns,
user_types);
@@ -2479,7 +2486,9 @@ static computed_columns_map get_computed_columns(const schema_mutations& sm) {
static std::vector<column_definition> create_columns_from_column_rows(
const query::result_set& rows,
const sstring& keyspace,
const sstring& table,
const sstring& table, /*,
AbstractType<?> rawComparator, */
bool is_super,
column_view_virtual is_view_virtual,
const computed_columns_map& computed_columns,
const data_dictionary::user_types_storage& user_types)
@@ -2556,12 +2565,12 @@ static schema_builder prepare_view_schema_builder_from_mutations(const schema_ct
}
auto computed_columns = get_computed_columns(sm);
auto column_defs = create_columns_from_column_rows(query::result_set(sm.columns_mutation()), ks_name, cf_name, column_view_virtual::no, computed_columns, user_types);
auto column_defs = create_columns_from_column_rows(query::result_set(sm.columns_mutation()), ks_name, cf_name, false, column_view_virtual::no, computed_columns, user_types);
for (auto&& cdef : column_defs) {
builder.with_column_ordered(cdef);
}
if (sm.view_virtual_columns_mutation()) {
column_defs = create_columns_from_column_rows(query::result_set(*sm.view_virtual_columns_mutation()), ks_name, cf_name, column_view_virtual::yes, computed_columns, user_types);
column_defs = create_columns_from_column_rows(query::result_set(*sm.view_virtual_columns_mutation()), ks_name, cf_name, false, column_view_virtual::yes, computed_columns, user_types);
for (auto&& cdef : column_defs) {
builder.with_column_ordered(cdef);
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (C) 2024-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#include "db/system0_virtual_tables.hh"
#include "db/system_keyspace.hh"
#include "db/virtual_table.hh"
#include "replica/database.hh"
#include "replica/tablets.hh"
#include "schema/schema.hh"
#include "schema/schema_builder.hh"
#include "cql3/query_processor.hh"
#include "mutation/frozen_mutation.hh"
#include "types/types.hh"
#include "utils/log.hh"
#include <seastar/core/coroutine.hh>
namespace db {
namespace {
static constexpr auto SYSTEM0_KEYSPACE_NAME = "system0";
logging::logger sys0log("system0_virtual_tables");
// Virtual table that mirrors system.topology but allows writes via group0
class system0_topology_table : public memtable_filling_virtual_table {
private:
cql3::query_processor& _qp;
public:
explicit system0_topology_table(cql3::query_processor& qp)
: memtable_filling_virtual_table(build_schema())
, _qp(qp)
{}
static schema_ptr build_schema() {
// Use the same schema as system.topology but in system0 keyspace
auto id = generate_legacy_id(SYSTEM0_KEYSPACE_NAME, system_keyspace::TOPOLOGY);
return schema_builder(SYSTEM0_KEYSPACE_NAME, system_keyspace::TOPOLOGY, std::optional(id))
.with_column("key", utf8_type, column_kind::partition_key)
.with_column("host_id", uuid_type, column_kind::clustering_key)
.with_column("datacenter", utf8_type)
.with_column("rack", utf8_type)
.with_column("tokens", set_type_impl::get_instance(utf8_type, true))
.with_column("node_state", utf8_type)
.with_column("release_version", utf8_type)
.with_column("topology_request", utf8_type)
.with_column("replaced_id", uuid_type)
.with_column("rebuild_option", utf8_type)
.with_column("num_tokens", int32_type)
.with_column("tokens_string", utf8_type)
.with_column("shard_count", int32_type)
.with_column("ignore_msb", int32_type)
.with_column("cleanup_status", utf8_type)
.with_column("supported_features", set_type_impl::get_instance(utf8_type, true))
.with_column("request_id", timeuuid_type)
.with_column("ignore_nodes", set_type_impl::get_instance(uuid_type, true), column_kind::static_column)
.with_column("new_cdc_generation_data_uuid", timeuuid_type, column_kind::static_column)
.with_column("new_keyspace_rf_change_ks_name", utf8_type, column_kind::static_column)
.with_column("new_keyspace_rf_change_data", map_type_impl::get_instance(utf8_type, utf8_type, false), column_kind::static_column)
.with_column("version", long_type, column_kind::static_column)
.with_column("fence_version", long_type, column_kind::static_column)
.with_column("transition_state", utf8_type, column_kind::static_column)
.with_column("committed_cdc_generations", set_type_impl::get_instance(cdc_generation_ts_id_type, true), column_kind::static_column)
.with_column("unpublished_cdc_generations", set_type_impl::get_instance(cdc_generation_ts_id_type, true), column_kind::static_column)
.with_column("global_topology_request", utf8_type, column_kind::static_column)
.with_column("global_topology_request_id", timeuuid_type, column_kind::static_column)
.with_column("enabled_features", set_type_impl::get_instance(utf8_type, true), column_kind::static_column)
.with_column("session", uuid_type, column_kind::static_column)
.with_column("tablet_balancing_enabled", boolean_type, column_kind::static_column)
.with_column("upgrade_state", utf8_type, column_kind::static_column)
.with_column("global_requests", set_type_impl::get_instance(timeuuid_type, true), column_kind::static_column)
.set_comment("Virtual table for updating system.topology via group0")
.with_hash_version()
.build();
}
future<> execute(std::function<void(mutation)> mutation_sink) override {
// For reads, we mirror the actual system.topology table
// This is a simplified placeholder implementation
sys0log.debug("system0.topology: read operation");
co_return;
}
future<> apply(const frozen_mutation& fm) override {
sys0log.info("system0.topology: received write operation");
// Convert mutation from system0.topology schema to system.topology schema
const mutation m = fm.unfreeze(_s);
// Re-freeze the mutation with the system.topology schema
auto system_topology_schema = system_keyspace::topology();
mutation target_m(system_topology_schema, m.key());
target_m.partition() = m.partition();
// TODO: Submit mutation to group0 via raft_group0_client
// For now, just log a warning
sys0log.warn("system0.topology: write operations require group0 integration (not yet implemented)");
co_return;
}
};
// Virtual table that mirrors system.tablets but allows writes via group0
class system0_tablets_table : public memtable_filling_virtual_table {
private:
cql3::query_processor& _qp;
public:
explicit system0_tablets_table(cql3::query_processor& qp)
: memtable_filling_virtual_table(build_schema())
, _qp(qp)
{}
static schema_ptr build_schema() {
// Create a simple schema for tablets in system0 keyspace
// This mirrors system.tablets structure
auto id = generate_legacy_id(SYSTEM0_KEYSPACE_NAME, system_keyspace::TABLETS);
auto replica_set_type = replica::get_replica_set_type();
return schema_builder(SYSTEM0_KEYSPACE_NAME, system_keyspace::TABLETS, id)
.with_column("table_id", uuid_type, column_kind::partition_key)
.with_column("tablet_count", int32_type, column_kind::static_column)
.with_column("keyspace_name", utf8_type, column_kind::static_column)
.with_column("table_name", utf8_type, column_kind::static_column)
.with_column("last_token", long_type, column_kind::clustering_key)
.with_column("replicas", replica_set_type)
.with_column("new_replicas", replica_set_type)
.with_column("stage", utf8_type)
.with_column("transition", utf8_type)
.with_column("session", uuid_type)
.set_comment("Virtual table for updating system.tablets via group0")
.with_hash_version()
.build();
}
future<> execute(std::function<void(mutation)> mutation_sink) override {
// For reads, we mirror the actual system.tablets table
// This is a simplified placeholder implementation
sys0log.debug("system0.tablets: read operation");
co_return;
}
future<> apply(const frozen_mutation& fm) override {
sys0log.info("system0.tablets: received write operation");
// Convert mutation from system0.tablets schema to system.tablets schema
const mutation m = fm.unfreeze(_s);
// Re-freeze the mutation with the system.tablets schema
auto system_tablets_schema = system_keyspace::tablets();
mutation target_m(system_tablets_schema, m.key());
target_m.partition() = m.partition();
// TODO: Submit mutation to group0 via raft_group0_client
// For now, just log a warning
sys0log.warn("system0.tablets: write operations require group0 integration (not yet implemented)");
co_return;
}
};
} // anonymous namespace
future<> initialize_system0_virtual_tables(
sharded<service::raft_group_registry>& dist_raft_gr,
sharded<db::system_keyspace>& sys_ks,
sharded<cql3::query_processor>& qp) {
auto& virtual_tables_registry = sys_ks.local().get_virtual_tables_registry();
auto& virtual_tables = *virtual_tables_registry;
auto& db = sys_ks.local().local_db();
auto add_table = [&] (std::unique_ptr<virtual_table>&& tbl) -> future<> {
auto schema = tbl->schema();
virtual_tables[schema->id()] = std::move(tbl);
// Add the table as a local system table (similar to regular virtual tables)
// Note: This creates tables in the system0 keyspace which is treated as internal
co_await db.add_column_family_and_make_directory(schema, replica::database::is_new_cf::yes);
auto& cf = db.find_column_family(schema);
cf.mark_ready_for_writes(nullptr);
auto& vt = virtual_tables[schema->id()];
cf.set_virtual_reader(vt->as_mutation_source());
cf.set_virtual_writer([&vt = *vt] (const frozen_mutation& m) { return vt.apply(m); });
};
// Add system0 virtual tables
co_await add_table(std::make_unique<system0_topology_table>(qp.local()));
co_await add_table(std::make_unique<system0_tablets_table>(qp.local()));
sys0log.info("system0 virtual tables initialized");
}
} // namespace db

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2024-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#pragma once
#include <seastar/core/sharded.hh>
#include "schema/schema_fwd.hh"
namespace service {
class raft_group_registry;
}
namespace cql3 {
class query_processor;
}
namespace db {
class system_keyspace;
// Initialize virtual tables in the system0 keyspace which mirror group0 tables
// from the system keyspace but allow writes via group0.
future<> initialize_system0_virtual_tables(
sharded<service::raft_group_registry>& dist_raft_gr,
sharded<db::system_keyspace>& sys_ks,
sharded<cql3::query_processor>& qp);
} // namespace db

View File

@@ -108,6 +108,7 @@
#include "lang/manager.hh"
#include "sstables/sstables_manager.hh"
#include "db/virtual_tables.hh"
#include "db/system0_virtual_tables.hh"
#include "service/raft/raft_group_registry.hh"
#include "service/raft/raft_group0_client.hh"
@@ -1836,6 +1837,11 @@ To start the scylla server proper, simply invoke as: scylla server (or just scyl
return db::initialize_virtual_tables(db, ss, gossiper, raft_gr, sys_ks, tablet_allocator, messaging, *cfg);
}).get();
checkpoint(stop_signal, "initializing system0 virtual tables");
smp::invoke_on_all([&] {
return db::initialize_system0_virtual_tables(raft_gr, sys_ks, qp);
}).get();
// #293 - do not stop anything
// engine().at_exit([&qp] { return qp.stop(); });
sstables::init_metrics().get();

View File

@@ -50,7 +50,8 @@ static const std::unordered_set<std::string_view> internal_keyspaces = {
db::system_keyspace::NAME,
db::schema_tables::NAME,
auth::meta::legacy::AUTH_KS,
tracing::trace_keyspace_helper::KEYSPACE_NAME
tracing::trace_keyspace_helper::KEYSPACE_NAME,
"system0" // Virtual keyspace for group0 table updates
};
bool is_internal_keyspace(std::string_view name) {

View File

@@ -134,11 +134,14 @@ bool is_compatible(column_kind k1, column_kind k2);
enum class cf_type : uint8_t {
standard,
super,
};
inline sstring cf_type_to_sstring(cf_type t) {
if (t == cf_type::standard) {
return "Standard";
} else if (t == cf_type::super) {
return "Super";
}
throw std::invalid_argument(format("unknown type: {:d}\n", uint8_t(t)));
}
@@ -146,6 +149,8 @@ inline sstring cf_type_to_sstring(cf_type t) {
inline cf_type sstring_to_cf_type(sstring name) {
if (name == "Standard") {
return cf_type::standard;
} else if (name == "Super") {
return cf_type::super;
}
throw std::invalid_argument(format("unknown type: {}\n", name));
}
@@ -683,13 +688,13 @@ public:
}
bool is_cql3_table() const {
return !is_dense() && is_compound();
return !is_super() && !is_dense() && is_compound();
}
bool is_compact_table() const {
return !is_cql3_table();
}
bool is_static_compact_table() const {
return !is_dense() && !is_compound();
return !is_super() && !is_dense() && !is_compound();
}
const table_id& id() const {
@@ -706,6 +711,10 @@ public:
return _raw._type;
}
bool is_super() const {
return _raw._type == cf_type::super;
}
gc_clock::duration gc_grace_seconds() const {
auto seconds = std::chrono::seconds(_raw._props.gc_grace_seconds);
return std::chrono::duration_cast<gc_clock::duration>(seconds);

View File

@@ -21,14 +21,33 @@ static logging::logger ulogger("unimplemented");
std::string_view format_as(cause c) {
switch (c) {
case cause::API: return "API";
case cause::INDEXES: return "INDEXES";
case cause::LWT: return "LWT";
case cause::PAGING: return "PAGING";
case cause::AUTH: return "AUTH";
case cause::PERMISSIONS: return "PERMISSIONS";
case cause::TRIGGERS: return "TRIGGERS";
case cause::COUNTERS: return "COUNTERS";
case cause::METRICS: return "METRICS";
case cause::MIGRATIONS: return "MIGRATIONS";
case cause::GOSSIP: return "GOSSIP";
case cause::TOKEN_RESTRICTION: return "TOKEN_RESTRICTION";
case cause::LEGACY_COMPOSITE_KEYS: return "LEGACY_COMPOSITE_KEYS";
case cause::COLLECTION_RANGE_TOMBSTONES: return "COLLECTION_RANGE_TOMBSTONES";
case cause::RANGE_DELETES: return "RANGE_DELETES";
case cause::VALIDATION: return "VALIDATION";
case cause::REVERSED: return "REVERSED";
case cause::COMPRESSION: return "COMPRESSION";
case cause::NONATOMIC: return "NONATOMIC";
case cause::CONSISTENCY: return "CONSISTENCY";
case cause::HINT: return "HINT";
case cause::SUPER: return "SUPER";
case cause::WRAP_AROUND: return "WRAP_AROUND";
case cause::STORAGE_SERVICE: return "STORAGE_SERVICE";
case cause::API: return "API";
case cause::SCHEMA_CHANGE: return "SCHEMA_CHANGE";
case cause::MIXED_CF: return "MIXED_CF";
case cause::SSTABLE_FORMAT_M: return "SSTABLE_FORMAT_M";
}
abort();
}

View File

@@ -15,14 +15,33 @@
namespace unimplemented {
enum class cause {
API, // REST API features not implemented (force_user_defined_compaction, split_output in major compaction)
INDEXES, // Secondary index features (filtering on collections, clustering columns)
TRIGGERS, // Trigger support in schema tables and storage proxy
METRICS, // Query processor metrics
VALIDATION, // Schema validation in DDL statements (drop keyspace, truncate, token functions)
REVERSED, // Reversed types in CQL protocol
HINT, // Hint replaying in batchlog manager
SUPER, // Super column families (legacy Cassandra feature, never supported)
API,
INDEXES,
LWT,
PAGING,
AUTH,
PERMISSIONS,
TRIGGERS,
COUNTERS,
METRICS,
MIGRATIONS,
GOSSIP,
TOKEN_RESTRICTION,
LEGACY_COMPOSITE_KEYS,
COLLECTION_RANGE_TOMBSTONES,
RANGE_DELETES,
VALIDATION,
REVERSED,
COMPRESSION,
NONATOMIC,
CONSISTENCY,
HINT,
SUPER,
WRAP_AROUND, // Support for handling wrap around ranges in queries on database level and below
STORAGE_SERVICE,
SCHEMA_CHANGE,
MIXED_CF,
SSTABLE_FORMAT_M,
};
[[noreturn]] void fail(cause what);