From d480daffcae61fdeed6ac0d6d119646100a05290 Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Sat, 6 May 2017 21:51:52 +0200 Subject: [PATCH] cql3/restrictions: Complete implementation of is_satisfied_by() This patch implements the is_satisfied_by() function for the remaining types of restrictions, lifting the function declaration to abstract_restrictions. Signed-off-by: Duarte Nunes --- cql3/restrictions/abstract_restriction.hh | 20 +++ cql3/restrictions/multi_column_restriction.hh | 14 ++ .../single_column_primary_key_restrictions.hh | 11 ++ .../restrictions/single_column_restriction.hh | 20 --- cql3/restrictions/statement_restrictions.cc | 124 +++++++++++++----- cql3/restrictions/token_restriction.hh | 14 ++ 6 files changed, 149 insertions(+), 54 deletions(-) diff --git a/cql3/restrictions/abstract_restriction.hh b/cql3/restrictions/abstract_restriction.hh index 2ef4f8eefc..cd2255e9a4 100644 --- a/cql3/restrictions/abstract_restriction.hh +++ b/cql3/restrictions/abstract_restriction.hh @@ -94,6 +94,26 @@ public: return true; } + /** + * Whether the specified row satisfied this restriction. + * Assumes the row is live, but not all cells. If a cell + * isn't live and there's a restriction on its column, + * then the function returns false. + * + * @param schema the schema the row belongs to + * @param key the partition key + * @param ckey the clustering key + * @param cells the remaining row columns + * @return the restriction resulting of the merge + * @throws InvalidRequestException if the restrictions cannot be merged + */ + virtual bool is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const = 0; + protected: #if 0 protected static ByteBuffer validateIndexedValue(ColumnSpecification columnSpec, diff --git a/cql3/restrictions/multi_column_restriction.hh b/cql3/restrictions/multi_column_restriction.hh index a6783fef61..d4d014cdf0 100644 --- a/cql3/restrictions/multi_column_restriction.hh +++ b/cql3/restrictions/multi_column_restriction.hh @@ -85,6 +85,20 @@ public: do_merge_with(as_pkr); } + bool is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const override { + for (auto&& range : bounds_ranges(options)) { + if (!range.contains(ckey, clustering_key_prefix::prefix_equal_tri_compare(schema))) { + return false; + } + } + return true; + } + protected: virtual void do_merge_with(::shared_ptr> other) = 0; diff --git a/cql3/restrictions/single_column_primary_key_restrictions.hh b/cql3/restrictions/single_column_primary_key_restrictions.hh index 6fc28edf5e..03189cfcb7 100644 --- a/cql3/restrictions/single_column_primary_key_restrictions.hh +++ b/cql3/restrictions/single_column_primary_key_restrictions.hh @@ -336,6 +336,17 @@ public: sstring to_string() const override { return sprint("Restrictions(%s)", join(", ", get_column_defs())); } + + virtual bool is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const override { + return boost::algorithm::all_of( + _restrictions->restrictions() | boost::adaptors::map_values, + [&] (auto&& r) { return r->is_satisfied_by(schema, key, ckey, cells, options, now); }); + } }; template<> diff --git a/cql3/restrictions/single_column_restriction.hh b/cql3/restrictions/single_column_restriction.hh index 767eb81ac5..0a3fd51fdc 100644 --- a/cql3/restrictions/single_column_restriction.hh +++ b/cql3/restrictions/single_column_restriction.hh @@ -71,26 +71,6 @@ public: return _column_def; } - /** - * Whether the specified row satisfied this restriction. - * Assumes the row is live, but not all cells. If a cell - * isn't live and there's a restriction on its column, - * then the function returns false. - * - * @param schema the schema the row belongs to - * @param key the partition key - * @param ckey the clustering key - * @param cells the remaining row columns - * @return the restriction resulting of the merge - * @throws InvalidRequestException if the restrictions cannot be merged - */ - virtual bool is_satisfied_by(const schema& schema, - const partition_key& key, - const clustering_key_prefix& ckey, - const row& cells, - const query_options& options, - gc_clock::time_point now) const = 0; - #if 0 @Override public void addIndexExpressionTo(List expressions, diff --git a/cql3/restrictions/statement_restrictions.cc b/cql3/restrictions/statement_restrictions.cc index 02a8d779cf..ddfe0cffba 100644 --- a/cql3/restrictions/statement_restrictions.cc +++ b/cql3/restrictions/statement_restrictions.cc @@ -90,6 +90,14 @@ public: sstring to_string() const override { return "Initial restrictions"; } + virtual bool is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const override { + return true; + } }; template<> @@ -406,25 +414,34 @@ void statement_restrictions::validate_secondary_index_selections(bool selects_on } } +static bytes_view_opt do_get_value(const schema& schema, + const column_definition& cdef, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + gc_clock::time_point now) { + switch(cdef.kind) { + case column_kind::partition_key: + return key.get_component(schema, cdef.component_index()); + case column_kind::clustering_key: + return ckey.get_component(schema, cdef.component_index()); + default: + auto cell = cells.find_cell(cdef.id); + if (!cell) { + return stdx::nullopt; + } + assert(cdef.is_atomic()); + auto c = cell->as_atomic_cell(); + return c.is_dead(now) ? stdx::nullopt : bytes_view_opt(c.value()); + } +} + bytes_view_opt single_column_restriction::get_value(const schema& schema, const partition_key& key, const clustering_key_prefix& ckey, const row& cells, gc_clock::time_point now) const { - switch(_column_def.kind) { - case column_kind::partition_key: - return key.get_component(schema, _column_def.component_index()); - case column_kind::clustering_key: - return ckey.get_component(schema, _column_def.component_index()); - default: - auto cell = cells.find_cell(_column_def.id); - if (!cell) { - return stdx::nullopt; - } - assert(_column_def.is_atomic()); - auto c = cell->as_atomic_cell(); - return c.is_dead(now) ? stdx::nullopt : bytes_view_opt(c.value()); - } + return do_get_value(schema, _column_def, key, ckey, cells, std::move(now)); } bool single_column_restriction::EQ::is_satisfied_by(const schema& schema, @@ -463,6 +480,23 @@ bool single_column_restriction::IN::is_satisfied_by(const schema& schema, }); } +static query::range to_range(const term_slice& slice, const query_options& options) { + using range_type = query::range; + auto extract_bound = [&] (statements::bound bound) -> stdx::optional { + if (!slice.has_bound(bound)) { + return { }; + } + auto value = slice.bound(bound)->bind_and_get(options); + if (!value) { + return { }; + } + return { range_type::bound(*value, slice.is_inclusive(bound)) }; + }; + return range_type( + extract_bound(statements::bound::START), + extract_bound(statements::bound::END)); +} + bool single_column_restriction::slice::is_satisfied_by(const schema& schema, const partition_key& key, const clustering_key_prefix& ckey, @@ -476,26 +510,7 @@ bool single_column_restriction::slice::is_satisfied_by(const schema& schema, if (!cell_value) { return false; } - - using range_type = query::range; - auto extract_bound = [&] (statements::bound bound) -> stdx::optional { - if (!_slice.has_bound(bound)) { - return { }; - } - auto value = _slice.bound(bound)->bind_and_get(options); - if (!value) { - return { }; - } - return { range_type::bound(*value, _slice.is_inclusive(bound)) }; - }; - auto range = range_type( - extract_bound(statements::bound::START), - extract_bound(statements::bound::END)); - if (_column_def.type->is_reversed()) { - range.reverse(); - } - - return range.contains(*cell_value, _column_def.type->as_tri_comparator()); + return to_range(_slice, options).contains(*cell_value, _column_def.type->as_tri_comparator()); } bool single_column_restriction::contains::is_satisfied_by(const schema& schema, @@ -627,5 +642,46 @@ bool single_column_restriction::contains::is_satisfied_by(const schema& schema, return true; } +bool token_restriction::EQ::is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const { + bool satisfied = false; + auto cdef = _column_definitions.begin(); + for (auto&& operand : values(options)) { + if (operand) { + auto cell_value = do_get_value(schema, **cdef, key, ckey, cells, now); + satisfied = cell_value && (*cdef)->type->compare(*operand, *cell_value) == 0; + } + if (!satisfied) { + break; + } + } + return satisfied; +} + +bool token_restriction::slice::is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const { + bool satisfied = false; + auto range = to_range(_slice, options); + for (auto* cdef : _column_definitions) { + auto cell_value = do_get_value(schema, *cdef, key, ckey, cells, now); + if (!cell_value) { + return false; + } + satisfied = range.contains(*cell_value, cdef->type->as_tri_comparator()); + if (!satisfied) { + break; + } + } + return satisfied; +} + } } diff --git a/cql3/restrictions/token_restriction.hh b/cql3/restrictions/token_restriction.hh index a375a50b14..786847bf60 100644 --- a/cql3/restrictions/token_restriction.hh +++ b/cql3/restrictions/token_restriction.hh @@ -173,6 +173,13 @@ public: sstring to_string() const override { return sprint("EQ(%s)", _value->to_string()); } + + virtual bool is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const override; }; class token_restriction::slice final : public token_restriction { @@ -246,6 +253,13 @@ public: sstring to_string() const override { return sprint("SLICE%s", _slice); } + + virtual bool is_satisfied_by(const schema& schema, + const partition_key& key, + const clustering_key_prefix& ckey, + const row& cells, + const query_options& options, + gc_clock::time_point now) const override; }; }