mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-30 11:36:54 +00:00
Read query as fragmented string from the input stream in transport/server.cc, propagate it a such to query_processor::prepare() and also store it as such in cql3::cql_statement::raw_cql_statement. Unfortunately, the query still has to be linearized for parsing, as ANTLR -- although allows for custom InputStream implementation -- plays pointer arithmetics games with the pointers obtained from them, so fragmented input cannot be used. To amortize the cost of this linearization, the query string is linearized through utils::reusable_buffer. The parser can be invoked recursively, nested invokations linearize directly. Still, this patch limits the places where the query is linearized to the following: * Parsing * Audit * Logs and error messages So the normal query paths for queries that actually can get arbitrarily large (UPDATE and INSERT) should only linearize the query temporarily for parsing.
111 lines
4.6 KiB
C++
111 lines
4.6 KiB
C++
/*
|
|
* Copyright (C) 2016-present ScyllaDB
|
|
*
|
|
* Modified by ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1
|
|
*/
|
|
|
|
#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"
|
|
|
|
#include "utils/mutable_view.hh"
|
|
|
|
namespace utils {
|
|
template <mutable_view> class chunked_string_basic_view;
|
|
using chunked_string_view = chunked_string_basic_view<mutable_view::no>;
|
|
}
|
|
|
|
namespace cql3 {
|
|
|
|
namespace util {
|
|
|
|
|
|
void do_with_parser_impl(utils::chunked_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(utils::chunked_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 cql_config& cql_cfg, const query_options& options, const std::unique_ptr<attributes>& attrs);
|
|
|
|
template<typename T>
|
|
std::vector<T> to_vector(const std::vector<data_value>& values) {
|
|
std::vector<T> ann_vector;
|
|
ann_vector.reserve(values.size());
|
|
std::ranges::transform(values, std::back_inserter(ann_vector), [](const auto& v) { return value_cast<T>(v); });
|
|
return ann_vector;
|
|
}
|
|
|
|
} // namespace util
|
|
|
|
} // namespace cql3
|