From afd68187ea1bdba0b0ecac7a90f047d4bd86d384 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 15 Mar 2026 00:37:09 +0200 Subject: [PATCH] cql3: statement_restrictions: convert constructor loop to iterate over predicates Convert the constructor loop to first build predicates from the prepared where clause, then iterate over the predicates. The IS_NOT branch now uses pred.is_not_null_single_column and pred.on instead of inspecting the expression directly. The branch conditions for multi-column (pred.is_multi_column), token (on_partition_key_token), and single-column (on_column) now use predicate properties instead of expression helpers. Remove extract_column_from_is_not_null_restriction() which is no longer needed. --- cql3/restrictions/statement_restrictions.cc | 48 ++++++++------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/cql3/restrictions/statement_restrictions.cc b/cql3/restrictions/statement_restrictions.cc index 27aeb21e59..0443af8e25 100644 --- a/cql3/restrictions/statement_restrictions.cc +++ b/cql3/restrictions/statement_restrictions.cc @@ -1352,23 +1352,6 @@ static std::vector extract_clustering_prefix_restrictions( return prefix; } -static -const column_definition* -extract_column_from_is_not_null_restriction(const expr::binary_operator& restr) { - const expr::column_value* lhs_col_def = expr::as_if(&restr.lhs); - // The "IS NOT NULL" restriction is only supported (and - // mandatory) for materialized view creation: - if (lhs_col_def == nullptr) { - throw exceptions::invalid_request_exception("IS NOT only supports single column"); - } - // currently, the grammar only allows the NULL argument to be - // "IS NOT", so this assertion should not be able to fail - if (!expr::is(restr.rhs) || !expr::as(restr.rhs).is_null()) { - throw exceptions::invalid_request_exception("Only IS NOT NULL is supported"); - } - return lhs_col_def->col; -} - statement_restrictions::statement_restrictions(private_tag, data_dictionary::database db, schema_ptr schema, @@ -1394,17 +1377,22 @@ statement_restrictions::statement_restrictions(private_tag, prepared_where_clause.push_back(std::move(prepared_restriction)); } + std::vector predicates; for (auto& prepared_restriction : prepared_where_clause) { - auto& restr = prepared_restriction; - if (restr.op == expr::oper_t::IS_NOT) { - // Handle IS NOT NULL restrictions separately - auto col = extract_column_from_is_not_null_restriction(restr); + auto preds = to_predicates(prepared_restriction, _schema.get()); + predicates.insert(predicates.end(), std::make_move_iterator(preds.begin()), std::make_move_iterator(preds.end())); + } + + for (auto& pred : predicates) { + auto& restr = expr::as(pred.filter); + if (pred.is_not_null_single_column) { + auto* col = require_on_single_column(pred); _not_null_columns.insert(col); if (!for_view) { - throw exceptions::invalid_request_exception(format("restriction '{}' is only supported in materialized view creation", restr)); + throw exceptions::invalid_request_exception(format("restriction '{}' is only supported in materialized view creation", pred.filter)); } - } else if (is_multi_column(restr)) { + } else if (pred.is_multi_column) { // Multi column restrictions are only allowed on clustering columns if (is_empty_restriction(_clustering_columns_restrictions)) { _clustering_columns_restrictions = restr; @@ -1462,7 +1450,7 @@ statement_restrictions::statement_restrictions(private_tag, throw exceptions::invalid_request_exception(format("Unsupported multi-column relation: ", restr)); } } - } else if (has_partition_token(restr, *_schema)) { + } else if (std::holds_alternative(pred.on)) { // Token always restricts the partition key if (!partition_key_restrictions_is_empty() && !has_token_restrictions()) { throw exceptions::invalid_request_exception( @@ -1475,8 +1463,8 @@ statement_restrictions::statement_restrictions(private_tag, } _partition_key_restrictions = expr::make_conjunction(_partition_key_restrictions, restr); - } else if (is_single_column_restriction(restr)) { - const column_definition* def = get_the_only_column(restr).col; + } else if (std::holds_alternative(pred.on)) { + const column_definition* def = std::get(pred.on).column; if (def->is_partition_key()) { // View definition allows PK slices, because it's not a performance problem. if (restr.op != expr::oper_t::EQ && restr.op != expr::oper_t::IN && !allow_filtering && !for_view) { @@ -1504,7 +1492,7 @@ statement_restrictions::statement_restrictions(private_tag, "Mixing single column relations and multi column relations on clustering columns is not allowed"); } - const column_definition* new_column = get_the_only_column(restr).col; + const column_definition* new_column = std::get(pred.on).column; const column_definition* last_column = expr::get_last_column_def(_clustering_columns_restrictions); if (last_column != nullptr && !allow_filtering) { @@ -1526,11 +1514,11 @@ statement_restrictions::statement_restrictions(private_tag, _nonprimary_key_restrictions = expr::make_conjunction(_nonprimary_key_restrictions, restr); } } else { - throw exceptions::invalid_request_exception(format("Unhandled restriction: {}", restr)); + throw exceptions::invalid_request_exception(format("Unhandled restriction: {}", pred.filter)); } - if (prepared_restriction.op != expr::oper_t::IS_NOT) { - _where.push_back(prepared_restriction); + if (!pred.is_not_null_single_column) { + _where.push_back(restr); } } if (!_where.empty()) {