index: Set tombstone_gc when creating secondary index

Before this commit, when the underlying materialized view was created,
it didn't have the property `tombstone_gc` set to any value. That
was a bug and we fix it now.

Two reproducer tests is added for validation. They reproduce the problem
and don't pass before this commit.

Fixes scylladb/scylladb#26542
This commit is contained in:
Dawid Mędrek
2025-10-13 19:04:49 +02:00
parent e294b80615
commit 7e201eea1a
4 changed files with 34 additions and 4 deletions

View File

@@ -34,6 +34,7 @@
#include "index/secondary_index_manager.hh"
#include "types/concrete_types.hh"
#include "db/tags/extension.hh"
#include "tombstone_gc_extension.hh"
#include <stdexcept>
@@ -113,7 +114,9 @@ static data_type type_for_computed_column(cql3::statements::index_target::target
}
}
view_ptr create_index_statement::create_view_for_index(const schema_ptr schema, const index_metadata& im) const {
view_ptr create_index_statement::create_view_for_index(const schema_ptr schema, const index_metadata& im,
const data_dictionary::database& db) const
{
sstring index_target_name = im.options().at(cql3::statements::index_target::target_option_name);
schema_builder builder{schema->ks_name(), secondary_index::index_table_name(im.name())};
auto target_info = secondary_index::target_parser::parse(schema, im);
@@ -196,6 +199,10 @@ view_ptr create_index_statement::create_view_for_index(const schema_ptr schema,
format("{} IS NOT NULL", index_target->name_as_cql_string()) :
"";
builder.with_view_info(schema, false, where_clause);
auto tombstone_gc_ext = seastar::make_shared<tombstone_gc_extension>(get_default_tombstone_gc_mode(db, schema->ks_name()));
builder.add_extension(tombstone_gc_extension::NAME, std::move(tombstone_gc_ext));
// A local secondary index should be backed by a *synchronous* view,
// see #16371. A view is marked synchronous with a tag. Non-local indexes
// do not need the tags schema extension at all.
@@ -582,7 +589,7 @@ create_index_statement::prepare_schema_mutations(query_processor& qp, const quer
// Produce the underlying view for the index.
if (db::schema_tables::view_should_exist(res->index)) {
view_ptr view = create_view_for_index(cf.schema(), res->index);
view_ptr view = create_view_for_index(cf.schema(), res->index, qp.db());
utils::chunked_vector<mutation> view_muts = co_await service::prepare_new_view_announcement(qp.proxy(), std::move(view), ts);
muts.reserve(muts.size() + view_muts.size());

View File

@@ -54,7 +54,7 @@ public:
index_metadata index;
};
std::optional<base_schema_with_new_index> build_index_schema(data_dictionary::database db) const;
view_ptr create_view_for_index(const schema_ptr, const index_metadata& im) const;
view_ptr create_view_for_index(const schema_ptr, const index_metadata& im, const data_dictionary::database&) const;
private:
void validate_for_local_index(const schema& schema) const;
void validate_for_frozen_collection(const index_target& target) const;

View File

@@ -2176,3 +2176,26 @@ def test_indexing_paging_and_aggregation(cql, test_keyspace):
assert list(cql.execute(stmt)) == [(row_count * row_count // 4,)]
stmt = SimpleStatement(f'SELECT avg(id) FROM {table} WHERE c2 = 1', fetch_size=3)
assert list(cql.execute(stmt)) == [(row_count / 2 + 1,)]
# Verify that a newly created secondary index has
# the property `tombstone_gc` set to some value.
#
# Reproducer of scylladb/scylladb#26542
def test_tombstone_gc_property(cql, test_keyspace, scylla_only):
with new_test_table(cql, test_keyspace, "p int PRIMARY KEY, v int") as table:
index_name = unique_name()
cql.execute(f"CREATE INDEX {index_name} ON {table}(v)")
desc_row = cql.execute(f"DESCRIBE MATERIALIZED VIEW {test_keyspace}.{index_name}_index").one()
assert "tombstone_gc = {" in desc_row.create_statement
# Verify that a newly created unnamed secondary index has
# the property `tombstone_gc` set to some value.
#
# Reproducer of scylladb/scylladb#26542
def test_tombstone_gc_property_unnamed_index(cql, test_keyspace, scylla_only):
with new_test_table(cql, test_keyspace, "p int PRIMARY KEY, v int") as table:
cql.execute(f"CREATE INDEX ON {table}(v)")
desc_row = cql.execute(f"DESCRIBE MATERIALIZED VIEW {table}_v_idx_index").one()
assert "tombstone_gc = {" in desc_row.create_statement

View File

@@ -334,7 +334,7 @@ std::vector<schema_ptr> do_load_schemas(const db::config& cfg, std::string_view
}
it->schema = std::move(new_base_schema);
it->secondary_idx_man.reload();
auto view = p->create_view_for_index(it->schema, index);
auto view = p->create_view_for_index(it->schema, index, db);
real_db.tables.emplace_back(dd_impl, dd_impl.unwrap(ks), view, true);
} else if (auto p = dynamic_cast<cql3::statements::update_statement*>(statement)) {
if (p->keyspace() != db::schema_tables::NAME && p->column_family() != db::schema_tables::DROPPED_COLUMNS) {