From 599bcd6ea7f857ff8ed509776a12b277f598b8ec Mon Sep 17 00:00:00 2001 From: Jan Ciolek Date: Mon, 18 Jul 2022 17:03:51 +0200 Subject: [PATCH] cql3: Remove all remaining restrictions code The classes restriction, restrictions and its children aren't used anywhere now and can be safely removed. Some includes need to be modified for the code to compile. Signed-off-by: Jan Ciolek --- cql3/expr/restrictions.cc | 4 +- cql3/restrictions/bounds_slice.hh | 2 +- cql3/restrictions/multi_column_restriction.hh | 443 ------------------ cql3/restrictions/primary_key_restrictions.hh | 144 ------ cql3/restrictions/restriction.hh | 32 -- cql3/restrictions/restrictions.hh | 81 ---- .../single_column_primary_key_restrictions.hh | 270 ----------- .../single_column_restrictions.hh | 212 --------- cql3/restrictions/statement_restrictions.cc | 4 +- cql3/restrictions/statement_restrictions.hh | 5 +- cql3/restrictions/token_restriction.hh | 67 --- cql3/selection/selection.cc | 1 - cql3/statements/select_statement.cc | 1 - test/boost/statement_restrictions_test.cc | 1 - 14 files changed, 5 insertions(+), 1262 deletions(-) delete mode 100644 cql3/restrictions/multi_column_restriction.hh delete mode 100644 cql3/restrictions/primary_key_restrictions.hh delete mode 100644 cql3/restrictions/restriction.hh delete mode 100644 cql3/restrictions/restrictions.hh delete mode 100644 cql3/restrictions/single_column_primary_key_restrictions.hh delete mode 100644 cql3/restrictions/single_column_restrictions.hh delete mode 100644 cql3/restrictions/token_restriction.hh diff --git a/cql3/expr/restrictions.cc b/cql3/expr/restrictions.cc index 7cd6499f2d..81ed6c9be6 100644 --- a/cql3/expr/restrictions.cc +++ b/cql3/expr/restrictions.cc @@ -6,12 +6,10 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include "restrictions.hh" #include "cql3/statements/request_validations.hh" #include "seastar/util/defer.hh" #include "cql3/prepare_context.hh" -#include "cql3/restrictions/multi_column_restriction.hh" -#include "cql3/restrictions/token_restriction.hh" +#include "types/list.hh" namespace cql3 { namespace expr { diff --git a/cql3/restrictions/bounds_slice.hh b/cql3/restrictions/bounds_slice.hh index 8c6cb5d1e0..454a0aa0ff 100644 --- a/cql3/restrictions/bounds_slice.hh +++ b/cql3/restrictions/bounds_slice.hh @@ -10,11 +10,11 @@ #pragma once -#include "cql3/restrictions/restriction.hh" #include #include "to_string.hh" #include "exceptions/exceptions.hh" #include "index/secondary_index_manager.hh" +#include "cql3/expr/expression.hh" namespace cql3 { diff --git a/cql3/restrictions/multi_column_restriction.hh b/cql3/restrictions/multi_column_restriction.hh deleted file mode 100644 index cef5db0934..0000000000 --- a/cql3/restrictions/multi_column_restriction.hh +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (C) 2015-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include "cql3/statements/request_validations.hh" -#include "cql3/restrictions/primary_key_restrictions.hh" -#include "cql3/statements/request_validations.hh" -#include "cql3/restrictions/single_column_primary_key_restrictions.hh" -#include "cql3/restrictions/bounds_slice.hh" -#include "cql3/constants.hh" -#include "cql3/lists.hh" -#include "cql3/expr/expression.hh" -#include "types/list.hh" -#include "types/tuple.hh" - -namespace cql3 { - -namespace restrictions { - -inline -expr::tuple_constructor -column_definitions_as_tuple_constructor(const std::vector& defs) { - std::vector columns; - std::vector column_types; - columns.reserve(defs.size()); - for (auto& def : defs) { - columns.push_back(expr::column_value{def}); - column_types.push_back(def->type); - } - data_type ttype = tuple_type_impl::get_instance(std::move(column_types)); - return expr::tuple_constructor{std::move(columns), std::move(ttype)}; -} - -class multi_column_restriction : public clustering_key_restrictions { -private: - bool _has_only_asc_columns; - bool _has_only_desc_columns; -protected: - schema_ptr _schema; - std::vector _column_defs; -public: - multi_column_restriction(schema_ptr schema, std::vector&& defs) - : _schema(schema) - , _column_defs(std::move(defs)) - { - update_asc_desc_existence(); - } - - virtual std::vector get_column_defs() const override { - return _column_defs; - } - - virtual void merge_with(::shared_ptr other) override { - const auto as_pkr = dynamic_pointer_cast(other); - statements::request_validations::check_true(bool(as_pkr), - "Mixing single column relations and multi column relations on clustering columns is not allowed"); - do_merge_with(as_pkr); - update_asc_desc_existence(); - expression = make_conjunction(std::move(expression), other->expression); - } - -protected: - virtual void do_merge_with(::shared_ptr other) = 0; - - /** - * Returns the names of the columns that are specified within this Restrictions and the other one - * as a comma separated String. - * - * @param otherRestrictions the other restrictions - * @return the names of the columns that are specified within this Restrictions and the other one - * as a comma separated String. - */ - sstring get_columns_in_commons(::shared_ptr other) const { - auto ours = get_column_defs(); - auto theirs = other->get_column_defs(); - - std::sort(ours.begin(), ours.end()); - std::sort(theirs.begin(), theirs.end()); - std::vector common; - std::set_intersection(ours.begin(), ours.end(), theirs.begin(), theirs.end(), std::back_inserter(common)); - - sstring str; - for (auto&& c : common) { - if (!str.empty()) { - str += " ,"; - } - str += c->name_as_text(); - } - return str; - } - - virtual bool has_supporting_index(const secondary_index::secondary_index_manager& index_manager, - expr::allow_local_index allow_local) const override { - for (const auto& index : index_manager.list_indexes()) { - if (!allow_local && index.metadata().local()) { - continue; - } - if (is_supported_by(index)) - return true; - } - return false; - } - - virtual bool is_supported_by(const secondary_index::index& index) const = 0; - - /** - * @return true if the restriction contains at least one column of each - * ordering, false otherwise. - */ - bool is_mixed_order() const { - return !is_desc_order() && !is_asc_order(); - } - - /** - * @return true if all the restricted columns ordered in descending - * order, false otherwise - */ - bool is_desc_order() const { - return _has_only_desc_columns; - } - - /** - * @return true if all the restricted columns ordered in ascending - * order, false otherwise - */ - bool is_asc_order() const { - return _has_only_asc_columns; - } - -private: - /** - * Updates the _has_only_asc_columns and _has_only_desc_columns fields. - */ - void update_asc_desc_existence() { - std::size_t num_of_desc = - std::count_if(_column_defs.begin(), _column_defs.end(), [] (const column_definition* cd) { return cd->type->is_reversed(); }); - _has_only_asc_columns = num_of_desc == 0; - _has_only_desc_columns = num_of_desc == _column_defs.size(); - } -#if 0 - /** - * Check if this type of restriction is supported for the specified column by the specified index. - * @param index the Secondary index - * - * @return true this type of restriction is supported by the specified index, - * false otherwise. - */ - protected abstract boolean isSupportedBy(SecondaryIndex index); -#endif -public: - class EQ; - class IN; - class IN_with_values; - class IN_with_marker; - - class slice; -}; - -class multi_column_restriction::EQ final : public multi_column_restriction { -private: - expr::expression _value; -public: - EQ(schema_ptr schema, std::vector defs, expr::expression value) - : multi_column_restriction(schema, std::move(defs)) - , _value(std::move(value)) - { - using namespace expr; - expression = binary_operator{ - column_definitions_as_tuple_constructor(_column_defs), oper_t::EQ, _value}; - } - - virtual bool is_supported_by(const secondary_index::index& index) const override { - for (auto* cdef : _column_defs) { - if (index.supports_expression(*cdef, expr::oper_t::EQ)) { - return true; - } - } - return false; - } - - virtual void do_merge_with(::shared_ptr other) override { - throw exceptions::invalid_request_exception(format("{} cannot be restricted by more than one relation if it includes an Equal", - get_columns_in_commons(other))); - } -#if 0 - @Override - protected boolean isSupportedBy(SecondaryIndex index) - { - return index.supportsOperator(Operator.EQ); - } -#endif - - clustering_key_prefix composite_value(const query_options& options) const { - cql3::raw_value t = expr::evaluate(_value, options); - auto values = expr::get_tuple_elements(t, *type_of(_value)); - std::vector components; - for (unsigned i = 0; i < values.size(); i++) { - auto component = statements::request_validations::check_not_null(values[i], - "Invalid null value in condition for column {}", - _column_defs.at(i)->name_as_text()); - components.emplace_back(*component); - } - return clustering_key_prefix::from_exploded(*_schema, std::move(components)); - } - -#if 0 - @Override - public final void addIndexExpressionTo(List expressions, - QueryOptions options) throws InvalidRequestException - { - Tuples.Value t = ((Tuples.Value) value.bind(options)); - List values = t.getElements(); - for (int i = 0; i < values.size(); i++) - { - ColumnDefinition columnDef = columnDefs.get(i); - ByteBuffer component = validateIndexedValue(columnDef, values.get(i)); - expressions.add(new IndexExpression(columnDef.name.bytes, Operator.EQ, component)); - } - } -#endif -}; - -class multi_column_restriction::IN : public multi_column_restriction { -public: - IN(schema_ptr schema, std::vector defs) - : multi_column_restriction(schema, std::move(defs)) - { } - - virtual bool is_supported_by(const secondary_index::index& index) const override { - for (auto* cdef : _column_defs) { - if (index.supports_expression(*cdef, expr::oper_t::IN)) { - return true; - } - } - return false; - } -#if 0 - @Override - public void addIndexExpressionTo(List expressions, - QueryOptions options) throws InvalidRequestException - { - List> splitInValues = splitValues(options); - checkTrue(splitInValues.size() == 1, "IN restrictions are not supported on indexed columns"); - - List values = splitInValues.get(0); - checkTrue(values.size() == 1, "IN restrictions are not supported on indexed columns"); - - ColumnDefinition columnDef = columnDefs.get(0); - ByteBuffer component = validateIndexedValue(columnDef, values.get(0)); - expressions.add(new IndexExpression(columnDef.name.bytes, Operator.EQ, component)); - } -#endif - - virtual void do_merge_with(::shared_ptr other) override { - throw exceptions::invalid_request_exception(format("{} cannot be restricted by more than one relation if it includes a IN", - get_columns_in_commons(other))); - } - -#if 0 - @Override - protected boolean isSupportedBy(SecondaryIndex index) - { - return index.supportsOperator(Operator.IN); - } -#endif -}; - -/** - * An IN restriction that has a set of terms for in values. - * For example: "SELECT ... WHERE (a, b, c) IN ((1, 2, 3), (4, 5, 6))" or "WHERE (a, b, c) IN (?, ?)" - */ -class multi_column_restriction::IN_with_values final : public multi_column_restriction::IN { -private: - std::vector _value; -public: - IN_with_values(schema_ptr schema, std::vector defs, std::vector value) - : multi_column_restriction::IN(schema, std::move(defs)) - , _value(std::move(value)) - { - std::vector column_types; - column_types.reserve(defs.size()); - for (const column_definition* cdef : defs) { - column_types.push_back(cdef->type); - } - - // type of the delayed_value is frozen list of tuples - data_type list_elements_type = tuple_type_impl::get_instance(std::move(column_types)); - data_type in_list_type = list_type_impl::get_instance(std::move(list_elements_type), false); - - expr::collection_constructor values_list { - .style = expr::collection_constructor::style_type::list, - .elements = _value, - .type = std::move(in_list_type) - }; - - using namespace expr; - expression = binary_operator{ - column_definitions_as_tuple_constructor(_column_defs), - oper_t::IN, - std::move(values_list)}; - } -}; - - -/** - * An IN restriction that uses a single marker for a set of IN values that are tuples. - * For example: "SELECT ... WHERE (a, b, c) IN ?" - */ -class multi_column_restriction::IN_with_marker final : public multi_column_restriction::IN { -private: - expr::bind_variable _marker; -public: - IN_with_marker(schema_ptr schema, std::vector defs, expr::bind_variable marker) - : IN(schema, std::move(defs)), _marker(marker) { - using namespace expr; - expression = binary_operator{ - column_definitions_as_tuple_constructor(_column_defs), - oper_t::IN, - expr::expression(std::move(marker))}; - } -}; - -class multi_column_restriction::slice final : public multi_column_restriction { - using restriction_shared_ptr = ::shared_ptr; - using mode = expr::comparison_order; - bounds_slice _slice; - mode _mode; - - slice(schema_ptr schema, std::vector defs, bounds_slice slice, mode m) - : multi_column_restriction(schema, std::move(defs)) - , _slice(slice) - , _mode(m) - { } -public: - slice(schema_ptr schema, std::vector defs, statements::bound bound, bool inclusive, expr::expression e, mode m = mode::cql) - : slice(schema, defs, bounds_slice::new_instance(bound, inclusive, e), m) - { - expression = expr::binary_operator{ - column_definitions_as_tuple_constructor(defs), - expr::pick_operator(bound, inclusive), - std::move(e), - m}; - } - - virtual bool is_supported_by(const secondary_index::index& index) const override { - for (auto* cdef : _column_defs) { - if (_slice.is_supported_by(*cdef, index)) { - return true; - } - } - return false; - } -#if 0 - @Override - public void addIndexExpressionTo(List expressions, - QueryOptions options) throws InvalidRequestException - { - throw invalidRequest("Slice restrictions are not supported on indexed columns which are part of a multi column relation"); - } - - @Override - protected boolean isSupportedBy(SecondaryIndex index) - { - return slice.isSupportedBy(index); - } - - private static Composite.EOC eocFor(Restriction r, Bound eocBound, Bound inclusiveBound) - { - if (eocBound.isStart()) - return r.isInclusive(inclusiveBound) ? Composite.EOC.NONE : Composite.EOC.END; - - return r.isInclusive(inclusiveBound) ? Composite.EOC.END : Composite.EOC.START; - } -#endif -public: - virtual void do_merge_with(::shared_ptr other) override { - using namespace statements::request_validations; - check_true(has_slice(other->expression), - "Column \"{}\" cannot be restricted by both an equality and an inequality relation", - get_columns_in_commons(other)); - auto other_slice = static_pointer_cast(other); - - static auto mode2str = [](auto m) { return m == mode::cql ? "plain" : "SCYLLA_CLUSTERING_BOUND"; }; - check_true(other_slice->_mode == this->_mode, - "Invalid combination of restrictions ({} / {})", - mode2str(this->_mode), mode2str(other_slice->_mode) - ); - check_false(_slice.has_bound(statements::bound::START) && other_slice->_slice.has_bound(statements::bound::START), - "More than one restriction was found for the start bound on {}", - get_columns_in_commons(other)); - check_false(_slice.has_bound(statements::bound::END) && other_slice->_slice.has_bound(statements::bound::END), - "More than one restriction was found for the end bound on {}", - get_columns_in_commons(other)); - - if (_column_defs.size() < other_slice->_column_defs.size()) { - _column_defs = other_slice->_column_defs; - } - _slice.merge(other_slice->_slice); - } - -private: - /** - * The function returns the first real inequality component. - * The first real inequality is the index of the first component in the - * tuple that will turn into a slice single column restriction. - * For example: (a, b, c) > (0, 1, 2) and (a, b, c) < (0, 1, 5) will be - * broken into one single column restriction set of the form: - * a = 0 and b = 1 and c > 2 and c < 5 , c is the first element that has - * inequality so for this case the function will return 2. - * @param start_components - the components of the starts tuple range. - * @param end_components - the components of the end tuple range. - * @return an empty value if not found and the index of the first index that - * will yield inequality - */ - std::optional find_first_neq_component(std::vector& start_components, - std::vector& end_components) const { - size_t common_components_count = std::min(start_components.size(), end_components.size()); - for (size_t i = 0; i < common_components_count ; i++) { - if (start_components[i].value() != end_components[i].value()) { - return i; - } - } - - size_t max_components_count = std::max(start_components.size(), end_components.size()); - if (common_components_count < max_components_count) { - return common_components_count; - } else { - return std::nullopt; - } - } -}; - -} - -} diff --git a/cql3/restrictions/primary_key_restrictions.hh b/cql3/restrictions/primary_key_restrictions.hh deleted file mode 100644 index 4f2078fc1a..0000000000 --- a/cql3/restrictions/primary_key_restrictions.hh +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2015-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include - -#include "cql3/query_options.hh" -#include "cql3/statements/bound.hh" -#include "cql3/restrictions/restrictions.hh" -#include "cql3/restrictions/restriction.hh" -#include "cql3/restrictions/restriction.hh" -#include "types.hh" -#include "query-request.hh" -#include - -namespace cql3 { -namespace restrictions { - -/** - * A set of restrictions on a primary key part (partition key or clustering key). - * - * What was in AbstractPrimaryKeyRestrictions was moved here (In pre 1.8 Java interfaces could not have default - * implementations of methods). - */ - -class partition_key_restrictions: public restriction, public restrictions, public enable_shared_from_this { -public: - partition_key_restrictions() = default; - - virtual void merge_with(::shared_ptr other) = 0; - - virtual ::shared_ptr merge_to(schema_ptr, ::shared_ptr restriction) { - merge_with(restriction); - return this->shared_from_this(); - } - - using restrictions::has_supporting_index; - - bool empty() const override { - return get_column_defs().empty(); - } - uint32_t size() const override { - return uint32_t(get_column_defs().size()); - } - - bool has_unrestricted_components(const schema& schema) const { - return size() < schema.partition_key_size(); - } - - virtual bool needs_filtering(const schema& schema) const { - return !empty() && !has_token(expression) && - (has_unrestricted_components(schema) || has_slice_or_needs_filtering(expression)); - } - - // NOTICE(sarna): This function is useless for partition key restrictions, - // but it should remain here until single_column_primary_key_restrictions class is detemplatized. - virtual unsigned int num_prefix_columns_that_need_not_be_filtered() const { - return 0; - } - - virtual bool is_all_eq() const { - return false; - } - - size_t prefix_size(const schema&) const { - return 0; - } -}; - -class clustering_key_restrictions : public restriction, public restrictions, public enable_shared_from_this { -public: - clustering_key_restrictions() = default; - - virtual void merge_with(::shared_ptr other) = 0; - - virtual ::shared_ptr merge_to(schema_ptr, ::shared_ptr restriction) { - merge_with(restriction); - return this->shared_from_this(); - } - - using restrictions::has_supporting_index; - - bool empty() const override { - return get_column_defs().empty(); - } - uint32_t size() const override { - return uint32_t(get_column_defs().size()); - } - - bool has_unrestricted_components(const schema& schema) const { - return size() < schema.clustering_key_size(); - } - - virtual bool needs_filtering(const schema& schema) const { - return false; - } - - // How long a prefix of the restrictions could have resulted in - // need_filtering() == false. These restrictions do not need to be - // applied during filtering. - // For example, if we have the filter "c1 < 3 and c2 > 3", c1 does - // not need filtering (just a read stopping at c1=3) but c2 does, - // so num_prefix_columns_that_need_not_be_filtered() will be 1. - virtual unsigned int num_prefix_columns_that_need_not_be_filtered() const { - return 0; - } - - virtual bool is_all_eq() const { - return false; - } - - size_t prefix_size(const schema& schema) const { - size_t count = 0; - if (schema.clustering_key_columns().empty()) { - return count; - } - auto column_defs = get_column_defs(); - column_id expected_column_id = schema.clustering_key_columns().begin()->id; - for (auto&& cdef : column_defs) { - if (schema.position(*cdef) != expected_column_id) { - return count; - } - expected_column_id++; - count++; - } - return count; - } -}; - -// FIXME(sarna): transitive hack only, do not judge. Should be dropped after all primary_key_restrictions uses are removed from code. -template -using primary_key_restrictions = std::conditional_t, partition_key_restrictions, clustering_key_restrictions>; - - -} -} diff --git a/cql3/restrictions/restriction.hh b/cql3/restrictions/restriction.hh deleted file mode 100644 index 8a397bf5f5..0000000000 --- a/cql3/restrictions/restriction.hh +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2019-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include "cql3/expr/expression.hh" - -namespace cql3 { - -namespace restrictions { - -/** - * Result of relation::to_restriction(). TODO: remove this class and rewrite to_restriction to return - * expression. - */ -class restriction { -public: - // Init to false for now, to easily detect errors. This whole class is going away. - cql3::expr::expression expression = expr::constant::make_bool(false); - virtual ~restriction() {} -}; - -} - -} diff --git a/cql3/restrictions/restrictions.hh b/cql3/restrictions/restrictions.hh deleted file mode 100644 index ada4cf405e..0000000000 --- a/cql3/restrictions/restrictions.hh +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2015-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include - -#include "cql3/query_options.hh" -#include "types.hh" -#include "schema_fwd.hh" -#include "index/secondary_index_manager.hh" -#include "restriction.hh" - -namespace cql3 { - -namespace restrictions { - -/** - * Sets of restrictions - */ -class restrictions { -public: - virtual ~restrictions() {} - - /** - * Returns the column definitions in position order. - * @return the column definitions in position order. - */ - virtual std::vector get_column_defs() const = 0; - - virtual bytes_opt value_for(const column_definition& cdef, const query_options& options) const { - throw exceptions::invalid_request_exception("Single value can be obtained from single-column restrictions only"); - } - - /** - * Check if the restriction is on indexed columns. - * - * @param index_manager the index manager - * @return true if the restriction is on indexed columns, false - */ - virtual bool has_supporting_index(const secondary_index::secondary_index_manager& index_manager, - expr::allow_local_index allow_local) const = 0; - -#if 0 - /** - * Adds to the specified list the index_expressions corresponding to this Restriction. - * - * @param expressions the list to add the index_expressions to - * @param options the query options - * @throws InvalidRequestException if this Restriction cannot be converted into - * index_expressions - */ - virtual void add_index_expression_to(std::vector<::shared_ptr>& expressions, - const query_options& options) = 0; -#endif - - /** - * Checks if this SingleColumnprimary_key_restrictions is empty or not. - * - * @return true if this SingleColumnprimary_key_restrictions is empty, false otherwise. - */ - virtual bool empty() const = 0; - - /** - * Returns the number of columns that have a restriction. - * - * @return the number of columns that have a restriction. - */ - virtual uint32_t size() const = 0; -}; - -} - -} diff --git a/cql3/restrictions/single_column_primary_key_restrictions.hh b/cql3/restrictions/single_column_primary_key_restrictions.hh deleted file mode 100644 index 898e2e41c5..0000000000 --- a/cql3/restrictions/single_column_primary_key_restrictions.hh +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2015-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include -#include -#include "schema_fwd.hh" -#include "cartesian_product.hh" -#include "cql3/restrictions/primary_key_restrictions.hh" -#include "cql3/restrictions/single_column_restrictions.hh" -#include "cql3/cql_config.hh" -#include "clustering_bounds_comparator.hh" -#include -#include -#include - -namespace cql3 { - -namespace restrictions { - -namespace { - -template -const char* -restricted_component_name_v; - -template <> -const char* restricted_component_name_v = "partition key"; - -template <> -const char* restricted_component_name_v = "clustering key"; - - -inline -void check_cartesian_product_size(size_t size, size_t max, const char* component_name) { - if (size > max) { - throw std::runtime_error(fmt::format("{} cartesian product size {} is greater than maximum {}", - component_name, size, max)); - } -} - -} - -/** - * A set of single column restrictions on a primary key part (partition key or clustering key). - */ -template -class single_column_primary_key_restrictions : public primary_key_restrictions { - using range_type = query::range; - using range_bound = typename range_type::bound; - template - friend class single_column_primary_key_restrictions; -private: - schema_ptr _schema; - bool _allow_filtering; - ::shared_ptr _restrictions; -private: - static uint32_t max_cartesian_product_size(const restrictions_config& config); -public: - single_column_primary_key_restrictions(schema_ptr schema, bool allow_filtering) - : _schema(schema) - , _allow_filtering(allow_filtering) - , _restrictions(::make_shared(schema)) - { - this->expression = expr::conjunction{}; // This will track _restrictions, which is a conjunction. - } - - // Convert another primary key restrictions type into this type, possibly using different schema - template - explicit single_column_primary_key_restrictions(schema_ptr schema, const single_column_primary_key_restrictions& other) - : _schema(schema) - , _allow_filtering(other._allow_filtering) - , _restrictions(::make_shared(schema)) - { - for (const auto& entry : other.restrictions()) { - const column_definition* other_cdef = entry.first; - const column_definition* this_cdef = _schema->get_column_definition(other_cdef->name()); - if (!this_cdef) { - throw exceptions::invalid_request_exception(format("Base column {} not found in view index schema", other_cdef->name_as_text())); - } - auto r = ::make_shared(*this_cdef); - r->expression = replace_column_def(entry.second->expression, this_cdef); - _restrictions->add_restriction(r); - } - } - - virtual bool is_all_eq() const override { - return _restrictions->is_all_eq(); - } - - void do_merge_with(const ::shared_ptr& single_column_restriction) { - if (!_restrictions->empty() && !_allow_filtering) { - auto last_column = *_restrictions->last_column(); - auto new_column = *get_the_only_column(single_column_restriction->expression).col; - - if (has_slice(this->expression) && _schema->position(new_column) > _schema->position(last_column)) { - throw exceptions::invalid_request_exception(format("Clustering column \"{}\" cannot be restricted (preceding column \"{}\" is restricted by a non-EQ relation)", - new_column.name_as_text(), last_column.name_as_text())); - } - - if (_schema->position(new_column) < _schema->position(last_column)) { - if (has_slice(single_column_restriction->expression)) { - throw exceptions::invalid_request_exception(format("PRIMARY KEY column \"{}\" cannot be restricted (preceding column \"{}\" is restricted by a non-EQ relation)", - last_column.name_as_text(), new_column.name_as_text())); - } - } - } - _restrictions->add_restriction(single_column_restriction); - this->expression = make_conjunction(std::move(this->expression), single_column_restriction->expression); - } - - virtual void merge_with(::shared_ptr restriction) override { - if (find_binop(restriction->expression, [] (const expr::binary_operator& b) { - return expr::is(b.lhs); - })) { - throw exceptions::invalid_request_exception( - "Mixing single column relations and multi column relations on clustering columns is not allowed"); - } - if (has_token(restriction->expression)) { - throw exceptions::invalid_request_exception( - format("Columns \"{}\" cannot be restricted by both a normal relation and a token relation", - join(", ", get_column_defs()))); - } - do_merge_with(restriction); - } - - std::vector values_as_keys(const query_options& options) const { - std::vector> value_vector; - value_vector.reserve(_restrictions->size()); - for (auto&& e : restrictions()) { - auto&& r = e.second; - assert(!has_slice(r->expression)); - auto values = expr::as(possible_lhs_values(e.first, r->expression, options)); - if (values.empty()) { - return {}; - } - value_vector.emplace_back(std::make_move_iterator(values.begin()), std::make_move_iterator(values.end())); - } - - std::vector result; - auto size = cartesian_product_size(value_vector); - check_cartesian_product_size(size, max_cartesian_product_size(options.get_cql_config().restrictions), - restricted_component_name_v); - result.reserve(size); - for (auto&& v : make_cartesian_product(value_vector)) { - result.emplace_back(ValueType::from_optional_exploded(*_schema, std::move(v))); - } - return result; - } - -public: - std::vector values(const query_options& options) const { - auto src = values_as_keys(options); - std::vector res; - for (const ValueType& r : src) { - for (const auto& component : r.components()) { - res.emplace_back(to_bytes(component)); - } - } - return res; - } - - virtual bytes_opt value_for(const column_definition& cdef, const query_options& options) const override { - return _restrictions->value_for(cdef, options); - } - - const single_column_restrictions::restrictions_map& restrictions() const { - return _restrictions->restrictions(); - } - - virtual bool has_supporting_index(const secondary_index::secondary_index_manager& index_manager, - expr::allow_local_index allow_local) const override { - return _restrictions->has_supporting_index(index_manager, allow_local); - } - -#if 0 - virtual void addIndexExpressionTo(List expressions, QueryOptions options) override { - restrictions.addIndexExpressionTo(expressions, options); - } -#endif - - virtual std::vector get_column_defs() const override { - return _restrictions->get_column_defs(); - } - - virtual bool empty() const override { - return _restrictions->empty(); - } - - virtual uint32_t size() const override { - return _restrictions->size(); - } - - virtual bool needs_filtering(const schema& schema) const override; - virtual unsigned int num_prefix_columns_that_need_not_be_filtered() const override; -}; - -template<> -inline bool single_column_primary_key_restrictions::needs_filtering(const schema& schema) const { - return primary_key_restrictions::needs_filtering(schema); -} - -// How many of the restrictions (in column order) do not need filtering -// because they are implemented as a slice (potentially, a contiguous disk -// read). For example, if we have the filter "c1 < 3 and c2 > 3", c1 does not -// need filtering but c2 does so num_prefix_columns_that_need_not_be_filtered -// will be 1. -template<> -inline unsigned single_column_primary_key_restrictions::num_prefix_columns_that_need_not_be_filtered() const { - // Restrictions currently need filtering in three cases: - // 1. any of them is a CONTAINS restriction - // 2. restrictions do not form a contiguous prefix (i.e. there are gaps in it) - // 3. a SLICE restriction isn't on a last place - column_id position = 0; - unsigned int count = 0; - for (const auto& restriction : restrictions() | boost::adaptors::map_values) { - if (find_needs_filtering(restriction->expression) - || position != get_the_only_column(restriction->expression).col->id) { - return count; - } - if (!has_slice(restriction->expression)) { - position = get_the_only_column(restriction->expression).col->id + 1; - } - count++; - } - return count; -} - -template<> -inline bool single_column_primary_key_restrictions::needs_filtering(const schema&) const { - return num_prefix_columns_that_need_not_be_filtered() < size(); -} - -template<> -inline unsigned single_column_primary_key_restrictions::num_prefix_columns_that_need_not_be_filtered() const { - // skip_filtering() is currently called only for clustering key - // restrictions, so it doesn't matter what we return here. - return 0; -} - -//TODO(sarna): These should be transformed into actual class definitions after detemplatizing single_column_primary_key_restrictions -using single_column_partition_key_restrictions = single_column_primary_key_restrictions; -using single_column_clustering_key_restrictions = single_column_primary_key_restrictions; - -template <> -inline -uint32_t single_column_primary_key_restrictions::max_cartesian_product_size(const restrictions_config& config) { - return config.partition_key_restrictions_max_cartesian_product_size; -} - -template <> -inline -uint32_t single_column_primary_key_restrictions::max_cartesian_product_size(const restrictions_config& config) { - return config.clustering_key_restrictions_max_cartesian_product_size; -} - - -} -} - - - diff --git a/cql3/restrictions/single_column_restrictions.hh b/cql3/restrictions/single_column_restrictions.hh deleted file mode 100644 index c16483b660..0000000000 --- a/cql3/restrictions/single_column_restrictions.hh +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2015-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include "cql3/restrictions/restrictions.hh" -#include "schema_fwd.hh" -#include "types.hh" - -namespace cql3 { - -namespace restrictions { - -/** - * Sets of single column _restrictions. - */ -class single_column_restrictions : public restrictions { -private: - /** - * The comparator used to sort the restrictions. - */ - struct column_definition_comparator { - schema_ptr _schema; - bool operator()(const column_definition* def1, const column_definition* def2) const { - auto pos1 = _schema->position(*def1); - auto pos2 = _schema->position(*def2); - if (pos1 != pos2) { - return pos1 < pos2; - } - // FIXME: shouldn't we use regular column name comparator here? Origin does not... - return less_unsigned(def1->name(), def2->name()); - } - }; - - /** - * The _restrictions per column. - */ -public: - using restrictions_map = std::map, column_definition_comparator>; -private: - restrictions_map _restrictions; - bool _is_all_eq = true; -public: - single_column_restrictions(schema_ptr schema) - : _restrictions(column_definition_comparator{std::move(schema)}) - { } - -#if 0 - @Override - public final void addIndexExpressionTo(List expressions, - QueryOptions options) throws InvalidRequestException - { - for (Restriction restriction : _restrictions.values()) - restriction.addIndexExpressionTo(expressions, options); - } -#endif - - virtual std::vector get_column_defs() const override { - std::vector r; - for (auto&& e : _restrictions) { - r.push_back(e.first); - } - return r; - } - - virtual bytes_opt value_for(const column_definition& cdef, const query_options& options) const override { - auto it = _restrictions.find(std::addressof(cdef)); - if (it == _restrictions.end()) { - return bytes_opt{}; - } else { - const auto values = std::get(possible_lhs_values(&cdef, it->second->expression, options)); - if (values.empty()) { - return bytes_opt{}; - } - assert(values.size() == 1); - return to_bytes(values.front()); - } - } - - /** - * Returns the restriction associated to the specified column. - * - * @param column_def the column definition - * @return the restriction associated to the specified column - */ - ::shared_ptr get_restriction(const column_definition& column_def) const { - auto i = _restrictions.find(&column_def); - if (i == _restrictions.end()) { - return {}; - } - return i->second; - } - - virtual bool empty() const override { - return _restrictions.empty(); - } - - virtual uint32_t size() const override { - return _restrictions.size(); - } - - /** - * Adds the specified restriction to this set of _restrictions. - * - * @param restriction the restriction to add - * @throws InvalidRequestException if the new restriction cannot be added - */ - void add_restriction(::shared_ptr restriction) { - if (!find(restriction->expression, expr::oper_t::EQ)) { - _is_all_eq = false; - } - - auto i = _restrictions.find(get_the_only_column(restriction->expression).col); - if (i == _restrictions.end()) { - _restrictions.emplace_hint(i, get_the_only_column(restriction->expression).col, std::move(restriction)); - } else { - auto& e = i->second->expression; - e = make_conjunction(std::move(e), restriction->expression); - } - } - - virtual bool has_supporting_index(const secondary_index::secondary_index_manager& index_manager, - expr::allow_local_index allow_local) const override { - for (auto&& e : _restrictions) { - if (expr::has_supporting_index(e.second->expression, index_manager, allow_local)) { - return true; - } - } - return false; - } - - /** - * Returns the column after the specified one. - * - * @param column_def the column for which the next one need to be found - * @return the column after the specified one. - */ - const column_definition* next_column(const column_definition& column_def) const { - auto i = _restrictions.find(&column_def); - if (i == _restrictions.end()) { - return nullptr; - } - ++i; - if (i == _restrictions.end()) { - return nullptr; - } - return i->first; - } - - /** - * Returns the definition of the last column. - * - * @return the definition of the last column. - */ - const column_definition* last_column() const { - if (_restrictions.empty()) { - return nullptr; - } - auto i = _restrictions.end(); - --i; - return i->first; - } - - /** - * Returns the last restriction. - * - * @return the last restriction. - */ - ::shared_ptr last_restriction() const { - if (_restrictions.empty()) { - return {}; - } - auto i = _restrictions.end(); - --i; - return i->second; - } - - const restrictions_map& restrictions() const { - return _restrictions; - } - - /** - * Checks if the _restrictions contains multiple contains, contains key, or map[key] = value. - * - * @return true if the _restrictions contains multiple contains, contains key, or , - * map[key] = value; false otherwise - */ - bool has_multiple_contains() const { - uint32_t number_of_contains = 0; - for (auto&& e : _restrictions) { - number_of_contains += count_if(e.second->expression, expr::is_on_collection); - if (number_of_contains > 1) { - return true; - } - } - return number_of_contains > 1; - } - - bool is_all_eq() const { - return _is_all_eq; - } -}; - -} -} diff --git a/cql3/restrictions/statement_restrictions.cc b/cql3/restrictions/statement_restrictions.cc index ac0b536ef7..ade3d5e1b7 100644 --- a/cql3/restrictions/statement_restrictions.cc +++ b/cql3/restrictions/statement_restrictions.cc @@ -19,10 +19,9 @@ #include "cql3/expr/expression.hh" #include "query-result-reader.hh" #include "statement_restrictions.hh" -#include "multi_column_restriction.hh" -#include "token_restriction.hh" #include "data_dictionary/data_dictionary.hh" #include "cartesian_product.hh" +#include "cql3/cql_config.hh" #include "cql3/constants.hh" #include "cql3/lists.hh" @@ -31,7 +30,6 @@ #include "types/list.hh" #include "types/map.hh" #include "types/set.hh" -#include "cql3/expr/restrictions.hh" namespace cql3 { namespace restrictions { diff --git a/cql3/restrictions/statement_restrictions.hh b/cql3/restrictions/statement_restrictions.hh index e042187c8f..750aa04f84 100644 --- a/cql3/restrictions/statement_restrictions.hh +++ b/cql3/restrictions/statement_restrictions.hh @@ -14,13 +14,12 @@ #include #include "bounds_slice.hh" #include "cql3/expr/expression.hh" +#include "cql3/expr/restrictions.hh" #include "to_string.hh" #include "schema_fwd.hh" -#include "cql3/restrictions/restrictions.hh" -#include "cql3/restrictions/primary_key_restrictions.hh" -#include "cql3/restrictions/single_column_restrictions.hh" #include "cql3/prepare_context.hh" #include "cql3/statements/statement_type.hh" +#include "query-request.hh" namespace cql3 { diff --git a/cql3/restrictions/token_restriction.hh b/cql3/restrictions/token_restriction.hh deleted file mode 100644 index c7e407e65e..0000000000 --- a/cql3/restrictions/token_restriction.hh +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2015-present ScyllaDB - * - * Modified by ScyllaDB - */ - -/* - * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) - */ - -#pragma once - -#include "restriction.hh" -#include "primary_key_restrictions.hh" -#include "exceptions/exceptions.hh" -#include "bounds_slice.hh" -#include "keys.hh" - -class column_definition; - -namespace cql3 { - -namespace restrictions { - -/** - * Restriction using the token function. - */ -class token_restriction: public partition_key_restrictions { -private: - /** - * The definition of the columns to which apply the token restriction. - */ - std::vector _column_definitions; -public: - token_restriction(std::vector c) - : _column_definitions(std::move(c)) { - } - - std::vector get_column_defs() const override { - return _column_definitions; - } - - void merge_with(::shared_ptr restriction) override { - if (!has_token(restriction->expression)) { - throw exceptions::invalid_request_exception( - format("Columns \"{}\" cannot be restricted by both a normal relation and a token relation", - join(", ", get_column_defs()))); - } - expression = make_conjunction(std::move(expression), restriction->expression); - } - - virtual bool has_supporting_index(const secondary_index::secondary_index_manager& index_manager, - expr::allow_local_index allow_local) const override { - return false; - } - -#if 0 - void add_index_expression_to(std::vector<::shared_ptr>& expressions, - const query_options& options) override { - throw exceptions::unsupported_operation_exception(); - } -#endif -}; - -} - -} diff --git a/cql3/selection/selection.cc b/cql3/selection/selection.cc index 714466e7d7..6948d954b5 100644 --- a/cql3/selection/selection.cc +++ b/cql3/selection/selection.cc @@ -18,7 +18,6 @@ #include "cql3/selection/selector_factories.hh" #include "cql3/result_set.hh" #include "cql3/query_options.hh" -#include "cql3/restrictions/multi_column_restriction.hh" #include "cql3/restrictions/statement_restrictions.hh" namespace cql3 { diff --git a/cql3/statements/select_statement.cc b/cql3/statements/select_statement.cc index e9b0bc371d..66cbe5b6b7 100644 --- a/cql3/statements/select_statement.cc +++ b/cql3/statements/select_statement.cc @@ -18,7 +18,6 @@ #include "cql3/functions/as_json_function.hh" #include "cql3/selection/selection.hh" #include "cql3/util.hh" -#include "cql3/restrictions/single_column_primary_key_restrictions.hh" #include "cql3/restrictions/statement_restrictions.hh" #include "cql3/selection/selector_factories.hh" #include "validation.hh" diff --git a/test/boost/statement_restrictions_test.cc b/test/boost/statement_restrictions_test.cc index 3fbd5b04d5..75d98efd2c 100644 --- a/test/boost/statement_restrictions_test.cc +++ b/test/boost/statement_restrictions_test.cc @@ -15,7 +15,6 @@ #include "cql3/util.hh" #include "test/lib/cql_assertions.hh" #include "test/lib/cql_test_env.hh" -#include "cql3/restrictions/multi_column_restriction.hh" using namespace cql3;