/* */ /* * Copyright (C) 2015-present ScyllaDB * * Modified by ScyllaDB */ /* * SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0) */ #pragma once #include "cql3/abstract_marker.hh" #include "cql3/expr/expression.hh" #include "utils/like_matcher.hh" namespace cql3 { /** * A CQL3 condition on the value of a column or collection element. For example, "UPDATE .. IF a = 0". */ class column_condition final { public: // If _collection_element is not zero, this defines the receiver cell, not the entire receiver // column. // E.g. if column type is list and expression is "a = ['test']", then the type of the // column definition below is list. If expression is "a[0] = 'test'", then the column // object stands for the string cell. See column_condition::raw::prepare() for details. const column_definition& column; private: // For collection, when testing the equality of a specific element, nullopt otherwise. std::optional _collection_element; // A literal value for comparison predicates or a multi item terminal for "a IN ?" std::optional _value; // List of terminals for "a IN (value, value, ...)" std::vector _in_values; const std::unique_ptr _matcher; expr::oper_t _op; public: column_condition(const column_definition& column, std::optional collection_element, std::optional value, std::vector in_values, std::unique_ptr matcher, expr::oper_t op) : column(column) , _collection_element(std::move(collection_element)) , _value(std::move(value)) , _in_values(std::move(in_values)) , _matcher(std::move(matcher)) , _op(op) { if (op != expr::oper_t::IN) { assert(_in_values.empty()); } } /** * Collects the column specification for the bind variables of this operation. * * @param boundNames the list of column specification where to collect the * bind variables of this term in. */ void collect_marker_specificaton(prepare_context& ctx); // Retrieve parameter marker values, if any, find the appropriate collection // element if the cell is a collection and an element access is used in the expression, // and evaluate the condition. bool applies_to(const data_value* cell_value, const query_options& options) const; /** * Helper constructor wrapper for * "IF col['key'] = 'foo'" * "IF col = 'foo'" * "IF col LIKE " */ static lw_shared_ptr condition(const column_definition& def, std::optional collection_element, expr::expression value, std::unique_ptr matcher, expr::oper_t op) { return make_lw_shared(def, std::move(collection_element), std::move(value), std::vector{}, std::move(matcher), op); } // Helper constructor wrapper for "IF col IN ... and IF col['key'] IN ... */ static lw_shared_ptr in_condition(const column_definition& def, std::optional collection_element, std::optional in_marker, std::vector in_values) { return make_lw_shared(def, std::move(collection_element), std::move(in_marker), std::move(in_values), nullptr, expr::oper_t::IN); } class raw final { private: std::optional _value; std::vector _in_values; std::optional _in_marker; // Can be nullopt, used with the syntax "IF m[e] = ..." (in which case it's 'e') std::optional _collection_element; expr::oper_t _op; public: raw(std::optional value, std::vector in_values, std::optional in_marker, std::optional collection_element, expr::oper_t op) : _value(std::move(value)) , _in_values(std::move(in_values)) , _in_marker(std::move(in_marker)) , _collection_element(std::move(collection_element)) , _op(op) { } /** * A condition on a column or collection element. * For example: * "IF col['key'] = 'foo'" * "IF col = 'foo'" * "IF col LIKE 'foo%'" */ static lw_shared_ptr simple_condition(cql3::expr::expression value, std::optional collection_element, expr::oper_t op) { return make_lw_shared(std::move(value), std::vector{}, std::nullopt, std::move(collection_element), op); } /** * An IN condition on a column or a collection element. IN may contain a list of values or a single marker. * For example: * "IF col IN ('foo', 'bar', ...)" * "IF col IN ?" * "IF col['key'] IN * ('foo', 'bar', ...)" * "IF col['key'] IN ?" */ static lw_shared_ptr in_condition(std::optional collection_element, std::optional in_marker, std::vector in_values) { return make_lw_shared(std::nullopt, std::move(in_values), std::move(in_marker), std::move(collection_element), expr::oper_t::IN); } lw_shared_ptr prepare(data_dictionary::database db, const sstring& keyspace, const column_definition& receiver) const; }; }; } // end of namespace cql3