When we rename columns in a table which has materialized views depending on it, we need to also rename them in the materialized views' WHERE clauses. Currently, we do that by creating a new WHERE clause after each rename, with the updated column. This is later converted to a mutation that overwrites the WHERE clause. After multiple renames, we have multiple mutations, each overwriting the WHERE clause with one column renamed. As a result, the final WHERE clause is one of the modified clauses with one column renamed. Instead, we should prepare one new WHERE clause which includes all the renamed columns. This patch accomplishes this by processing all the column renames first, and only preparing the new view schema with the new WHERE clause afterwards. This patch also includes a test reproducer for this scenario. Fixes scylladb/scylladb#22194 Closes scylladb/scylladb#23152
96 lines
4.1 KiB
C++
96 lines
4.1 KiB
C++
/*
|
|
* Copyright (C) 2016-present ScyllaDB
|
|
*
|
|
* Modified by ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
|
|
#include <seastar/core/sstring.hh>
|
|
|
|
#include "cql3/column_identifier.hh"
|
|
#include "cql3/CqlParser.hpp"
|
|
#include "cql3/error_collector.hh"
|
|
#include "cql3/statements/raw/select_statement.hh"
|
|
#include "cql3/dialect.hh"
|
|
|
|
namespace cql3 {
|
|
|
|
namespace util {
|
|
|
|
|
|
void do_with_parser_impl(const std::string_view& cql, dialect d, noncopyable_function<void (cql3_parser::CqlParser& p)> func);
|
|
|
|
template <typename Func, typename Result = cql3_parser::unwrap_uninitialized_t<std::invoke_result_t<Func, cql3_parser::CqlParser&>>>
|
|
Result do_with_parser(const std::string_view& cql, dialect d, Func&& f) {
|
|
std::optional<Result> ret;
|
|
do_with_parser_impl(cql, d, [&] (cql3_parser::CqlParser& parser) {
|
|
ret.emplace(f(parser));
|
|
});
|
|
return std::move(*ret);
|
|
}
|
|
|
|
sstring relations_to_where_clause(const expr::expression& e);
|
|
|
|
expr::expression where_clause_to_relations(const std::string_view& where_clause, dialect d);
|
|
|
|
sstring rename_columns_in_where_clause(const std::string_view& where_clause, std::vector<std::pair<::shared_ptr<column_identifier>, ::shared_ptr<column_identifier>>> renames, dialect d);
|
|
|
|
/// build a CQL "select" statement with the desired parameters.
|
|
/// If select_all_columns==true, all columns are selected and the value of
|
|
/// selected_columns is ignored.
|
|
std::unique_ptr<cql3::statements::raw::select_statement> build_select_statement(
|
|
const std::string_view& cf_name,
|
|
const std::string_view& where_clause,
|
|
bool select_all_columns,
|
|
const std::vector<column_definition>& selected_columns);
|
|
|
|
/// maybe_quote() takes an identifier - the name of a column, table or
|
|
/// keyspace name - and transforms it to a string which can be used in CQL
|
|
/// commands. Namely, if the identifier is not entirely lower-case (including
|
|
/// digits and underscores), it needs to be quoted to be represented in CQL.
|
|
/// Without this quoting, CQL folds uppercase letters to lower case, and
|
|
/// forbids non-alpha-numeric characters in identifier names.
|
|
/// Quoting involves wrapping the string in double-quotes ("). A double-quote
|
|
/// character itself is quoted by doubling it.
|
|
/// maybe_quote() also quotes reserved CQL keywords (e.g., "to", "where")
|
|
/// but doesn't quote *unreserved* keywords (like ttl, int or as).
|
|
/// Note that this means that if new reserved keywords are added to the
|
|
/// parser, a saved output of maybe_quote() may no longer be parsable by
|
|
/// parser. To avoid this forward-compatibility issue, use quote() instead
|
|
/// of maybe_quote() - to unconditionally quote an identifier even if it is
|
|
/// lowercase and not (yet) a keyword.
|
|
sstring maybe_quote(const std::string_view s);
|
|
|
|
/// quote() takes an identifier - the name of a column, table or keyspace -
|
|
/// and transforms it to a string which can be safely used in CQL commands.
|
|
/// Quoting involves wrapping the name in double-quotes ("). A double-quote
|
|
/// character itself is quoted by doubling it.
|
|
/// Quoting is necessary when the identifier contains non-alpha-numeric
|
|
/// characters, when it contains uppercase letters (which will be folded to
|
|
/// lowercase if not quoted), or when the identifier is one of many CQL
|
|
/// keywords. But it's allowed - and easier - to just unconditionally
|
|
/// quote the identifier name in CQL, so that is what this function does does.
|
|
sstring quote(const std::string_view s);
|
|
|
|
/// single_quote() takes a string and transforms it to a string
|
|
/// which can be safely used in CQL commands.
|
|
/// Single quoting involves wrapping the name in single-quotes ('). A sigle-quote
|
|
/// character itself is quoted by doubling it.
|
|
/// Single quoting is necessary for dates, IP addresses or string literals.
|
|
sstring single_quote(const std::string_view s);
|
|
|
|
// Check whether timestamp is not too far in the future as this probably
|
|
// indicates its incorrectness (for example using other units than microseconds).
|
|
void validate_timestamp(const db::config& config, const query_options& options, const std::unique_ptr<attributes>& attrs);
|
|
|
|
} // namespace util
|
|
|
|
} // namespace cql3
|