From e9108677f7e426dd3c28e2998535cf032c2dd47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20M=C4=99drek?= Date: Sat, 12 Jul 2025 00:28:53 +0200 Subject: [PATCH] cql3/statements/view_prop_defs.cc: Move validation logic into file We're moving the rest of the validation logic that can be moved from `cql3/statements/{create,alter}_view_statement.cc` to the new file. --- cql3/statements/alter_view_statement.cc | 14 -------- cql3/statements/create_view_statement.cc | 26 +------------- cql3/statements/view_prop_defs.cc | 46 ++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/cql3/statements/alter_view_statement.cc b/cql3/statements/alter_view_statement.cc index 6cb69ad986..4bf85b8b25 100644 --- a/cql3/statements/alter_view_statement.cc +++ b/cql3/statements/alter_view_statement.cc @@ -81,20 +81,6 @@ view_ptr alter_view_statement::prepare_view(data_dictionary::database db) const _properties->apply_to_builder(view_prop_defs::op_type::alter, builder, std::move(schema_extensions), db, keyspace(), is_colocated); - if (builder.get_gc_grace_seconds() == 0) { - throw exceptions::invalid_request_exception( - "Cannot alter gc_grace_seconds of a materialized view to 0, since this " - "value is used to TTL undelivered updates. Setting gc_grace_seconds too " - "low might cause undelivered updates to expire before being replayed."); - } - - if (builder.default_time_to_live().count() > 0) { - throw exceptions::invalid_request_exception( - "Cannot set or alter default_time_to_live for a materialized view. " - "Data in a materialized view always expire at the same time than " - "the corresponding data in the parent table."); - } - return view_ptr(builder.build()); } diff --git a/cql3/statements/create_view_statement.cc b/cql3/statements/create_view_statement.cc index c5d8c72c90..dc4e15d8a6 100644 --- a/cql3/statements/create_view_statement.cc +++ b/cql3/statements/create_view_statement.cc @@ -122,23 +122,6 @@ std::pair create_view_statement::prepare_view( auto schema_extensions = _properties.properties()->make_schema_extensions(db.extensions()); _properties.validate_raw(view_prop_defs::op_type::create, db, keyspace(), schema_extensions); - if (_properties.use_compact_storage()) { - throw exceptions::invalid_request_exception(format("Cannot use 'COMPACT STORAGE' when defining a materialized view")); - } - - if (_properties.properties()->get_cdc_options(schema_extensions)) { - throw exceptions::invalid_request_exception("Cannot enable CDC for a materialized view"); - } - - const auto maybe_id = _properties.properties()->get_id(); - if (maybe_id && db.try_find_table(*maybe_id)) { - const auto schema_ptr = db.find_schema(*maybe_id); - const auto& ks_name = schema_ptr->ks_name(); - const auto& cf_name = schema_ptr->cf_name(); - - throw exceptions::invalid_request_exception(seastar::format("Table with ID {} already exists: {}.{}", *maybe_id, ks_name, cf_name)); - } - // View and base tables must be in the same keyspace, to ensure that RF // is the same (because we assign a view replica to each base replica). // If a keyspace was not specified for the base table name, it is assumed @@ -351,7 +334,7 @@ std::pair create_view_statement::prepare_view( warnings.emplace_back(std::move(warning_text)); } - schema_builder builder{keyspace(), column_family(), maybe_id}; + schema_builder builder{keyspace(), column_family()}; auto add_columns = [this, &builder] (std::vector& defs, column_kind kind) mutable { for (auto* def : defs) { auto&& type = _properties.get_reversable_type(*def->column_specification->name, def->type); @@ -400,13 +383,6 @@ std::pair create_view_statement::prepare_view( _properties.apply_to_builder(view_prop_defs::op_type::create, builder, std::move(schema_extensions), db, keyspace(), is_colocated); - if (builder.default_time_to_live().count() > 0) { - throw exceptions::invalid_request_exception( - "Cannot set or alter default_time_to_live for a materialized view. " - "Data in a materialized view always expire at the same time than " - "the corresponding data in the parent table."); - } - auto where_clause_text = util::relations_to_where_clause(_where_clause); builder.with_view_info(schema, included.empty(), std::move(where_clause_text)); diff --git a/cql3/statements/view_prop_defs.cc b/cql3/statements/view_prop_defs.cc index 7e3de42baa..afc01816cc 100644 --- a/cql3/statements/view_prop_defs.cc +++ b/cql3/statements/view_prop_defs.cc @@ -10,16 +10,58 @@ namespace cql3::statements { -void view_prop_defs::validate_raw(op_type, const data_dictionary::database db, sstring ks_name, +void view_prop_defs::validate_raw(op_type op, const data_dictionary::database db, sstring ks_name, const schema::extensions_map& exts) const { cf_properties::validate(db, std::move(ks_name), exts); + + if (use_compact_storage()) { + throw exceptions::invalid_request_exception(format("Cannot use 'COMPACT STORAGE' when defining a materialized view")); + } + + if (properties()->get_cdc_options(exts)) { + throw exceptions::invalid_request_exception("Cannot enable CDC for a materialized view"); + } + + if (op == op_type::create) { + const auto maybe_id = properties()->get_id(); + if (maybe_id && db.try_find_table(*maybe_id)) { + const auto schema_ptr = db.find_schema(*maybe_id); + const auto& ks_name = schema_ptr->ks_name(); + const auto& cf_name = schema_ptr->cf_name(); + + throw exceptions::invalid_request_exception(seastar::format("Table with ID {} already exists: {}.{}", *maybe_id, ks_name, cf_name)); + } + } } -void view_prop_defs::apply_to_builder(op_type, schema_builder& builder, schema::extensions_map exts, +void view_prop_defs::apply_to_builder(op_type op, schema_builder& builder, schema::extensions_map exts, const data_dictionary::database db, sstring ks_name, bool is_colocated) const { _properties->apply_to_builder(builder, exts, db, std::move(ks_name), !is_colocated); + + if (op == op_type::create) { + const auto maybe_id = properties()->get_id(); + if (maybe_id) { + builder.set_uuid(*maybe_id); + } + } + + if (op == op_type::alter) { + if (builder.get_gc_grace_seconds() == 0) { + throw exceptions::invalid_request_exception( + "Cannot alter gc_grace_seconds of a materialized view to 0, since this " + "value is used to TTL undelivered updates. Setting gc_grace_seconds too " + "low might cause undelivered updates to expire before being replayed."); + } + } + + if (builder.default_time_to_live().count() > 0) { + throw exceptions::invalid_request_exception( + "Cannot set or alter default_time_to_live for a materialized view. " + "Data in a materialized view always expire at the same time than " + "the corresponding data in the parent table."); + } } } // namespace cql3::statements