diff --git a/cql3/statements/cas_request.cc b/cql3/statements/cas_request.cc index a5f0e866ae..2bd071683e 100644 --- a/cql3/statements/cas_request.cc +++ b/cql3/statements/cas_request.cc @@ -121,10 +121,15 @@ bool cas_request::applies_to() const { const partition_key& pkey = _key.front().start()->value().key().value(); const clustering_key empty_ckey = clustering_key::make_empty(); bool applies = true; + bool is_cas_result_set_empty = true; + bool has_static_column_conditions = false; for (const cas_row_update& op: _updates) { if (op.statement.has_conditions() == false) { continue; } + if (op.statement.has_static_column_conditions()) { + has_static_column_conditions = true; + } // If a statement has only static columns conditions, we must ignore its clustering columns // restriction when choosing a row to check the conditions, i.e. choose any partition row, // because any of them must have static columns and that's all we need to know if the @@ -142,6 +147,7 @@ bool cas_request::applies_to() const { const auto* row = _rows->find_row(pkey, ckey); if (row) { row->is_in_cas_result_set = true; + is_cas_result_set_empty = false; } if (!applies) { // No need to check this condition as we have already failed a previous one. @@ -151,6 +157,19 @@ bool cas_request::applies_to() const { } applies = op.statement.applies_to(row, op.options); } + if (has_static_column_conditions && is_cas_result_set_empty) { + // If none of the fetched rows matches clustering key restrictions and hence none of them is + // included into the CAS result set, but there is a static column condition in the CAS batch, + // we must still include the static row into the result set. Consider the following example: + // CREATE TABLE t(p int, c int, s int static, v int, PRIMARY KEY(p, c)); + // INSERT INTO t(p, s) VALUES(1, 1); + // DELETE v FROM t WHERE p=1 AND c=1 IF v=1 AND s=1; + // In this case the conditional DELETE must return [applied=False, v=null, s=1]. + const auto* row = _rows->find_row(pkey, empty_ckey); + if (row) { + row->is_in_cas_result_set = true; + } + } return applies; } diff --git a/cql3/statements/modification_statement.hh b/cql3/statements/modification_statement.hh index 8d25d40341..3cfc2f16f8 100644 --- a/cql3/statements/modification_statement.hh +++ b/cql3/statements/modification_statement.hh @@ -263,6 +263,8 @@ private: public: // True if the statement has IF conditions. Pre-computed during prepare. bool has_conditions() const { return _has_regular_column_conditions || _has_static_column_conditions; } + // True if the statement has IF conditions that apply to static columns. + bool has_static_column_conditions() const { return _has_static_column_conditions; } // True if this statement needs to read only static column values to check if it can be applied. bool has_only_static_column_conditions() const { return !_has_regular_column_conditions && _has_static_column_conditions; } diff --git a/cql3/update_parameters.hh b/cql3/update_parameters.hh index 942c88b6da..37aea1305f 100644 --- a/cql3/update_parameters.hh +++ b/cql3/update_parameters.hh @@ -60,6 +60,7 @@ public: static constexpr query::partition_slice::option_set options = query::partition_slice::option_set::of< query::partition_slice::option::send_partition_key, query::partition_slice::option::send_clustering_key, + query::partition_slice::option::always_return_static_content, query::partition_slice::option::collections_as_maps>(); // Holder for data for