Files
scylladb/cql3/functions/functions.hh
Marcin Maliszkiewicz 2e69016c4f db: access types during schema merge via special storage
Once we create types atomically the code which is before commit
may depend on newly added types, so it has to access both old and
new types. New storage called in_progress_types_storage was added.
2025-07-10 10:40:42 +02:00

136 lines
5.8 KiB
C++

/*
* Modified by ScyllaDB
*
* Copyright (C) 2015-present ScyllaDB
*/
/*
* SPDX-License-Identifier: (LicenseRef-ScyllaDB-Source-Available-1.0 and Apache-2.0)
*/
#pragma once
#include "function.hh"
#include "cql3/assignment_testable.hh"
#include "cql3/cql3_type.hh"
#include "cql3/functions/function_name.hh"
#include "schema/schema.hh"
#include <unordered_map>
#include "data_dictionary/user_types_metadata.hh"
namespace cql3 {
namespace functions {
//forward declarations
class user_function;
class user_aggregate;
class change_batch;
using declared_t = std::unordered_multimap<function_name, shared_ptr<function>>;
void add_agg_functions(declared_t& funcs);
class functions {
friend class change_batch;
std::unordered_multimap<function_name, shared_ptr<function>> init() noexcept;
protected:
using declared_t = cql3::functions::declared_t;
declared_t _declared;
struct skip_init {};
functions(skip_init) {};
public:
lw_shared_ptr<column_specification> make_arg_spec(const sstring& receiver_ks, std::optional<const std::string_view> receiver_cf,
const function& fun, size_t i) const;
functions() : _declared(init()) {}
shared_ptr<function> get(data_dictionary::database db,
const sstring& keyspace,
const function_name& name,
const std::vector<shared_ptr<assignment_testable>>& provided_args,
const sstring& receiver_ks,
std::optional<const std::string_view> receiver_cf,
const column_specification* receiver = nullptr) const;
template <typename AssignmentTestablePtrRange>
shared_ptr<function> get(data_dictionary::database db,
const sstring& keyspace,
const function_name& name,
AssignmentTestablePtrRange&& provided_args,
const sstring& receiver_ks,
std::optional<const std::string_view> receiver_cf,
const column_specification* receiver = nullptr) const {
const std::vector<shared_ptr<assignment_testable>> args(std::begin(provided_args), std::end(provided_args));
return get(db, keyspace, name, args, receiver_ks, receiver_cf, receiver);
}
std::vector<shared_ptr<user_function>> get_user_functions(const sstring& keyspace) const;
std::vector<shared_ptr<user_aggregate>> get_user_aggregates(const sstring& keyspace) const;
std::ranges::subrange<declared_t::const_iterator> find(const function_name& name) const;
declared_t::const_iterator find_iter(const function_name& name, const std::vector<data_type>& arg_types) const;
shared_ptr<function> find(const function_name& name, const std::vector<data_type>& arg_types) const;
shared_ptr<function> mock_get(const function_name& name, const std::vector<data_type>& arg_types) const;
void add_function(shared_ptr<function>);
void replace_function(shared_ptr<function>);
void remove_function(const function_name& name, const std::vector<data_type>& arg_types);
std::optional<function_name> used_by_user_aggregate(shared_ptr<user_function>) const;
std::optional<function_name> used_by_user_function(const ut_name& user_type) const;
private:
void with_udf_iter(const function_name& name, const std::vector<data_type>& arg_types, std::function<void(declared_t::iterator)> f);
template <typename F>
std::vector<shared_ptr<F>> get_filtered_transformed(const sstring& keyspace) const;
// This method and matchArguments are somewhat duplicate, but this method allows us to provide more precise errors in the common
// case where there is no override for a given function. This is thus probably worth the minor code duplication.
void validate_types(data_dictionary::database db,
const sstring& keyspace,
const schema* schema_opt,
shared_ptr<function> fun,
const std::vector<shared_ptr<assignment_testable>>& provided_args,
const sstring& receiver_ks,
std::optional<const std::string_view> receiver_cf) const;
assignment_testable::test_result match_arguments(data_dictionary::database db, const sstring& keyspace,
const schema* schema_opt,
shared_ptr<function> fun,
const std::vector<shared_ptr<assignment_testable>>& provided_args,
const sstring& receiver_ks,
std::optional<const std::string_view> receiver_cf) const;
bool type_equals(const std::vector<data_type>& t1, const std::vector<data_type>& t2) const;
};
// Getter for static functions object.
const functions& instance();
class change_batch : public functions {
public:
struct func_name_and_args {
function_name name;
std::vector<data_type> arg_types;
bool aggregate;
};
std::vector<func_name_and_args> removed_functions;
// Skip init as we copy data from static instance.
change_batch() : functions(skip_init{}) {
_declared = instance()._declared;
}
// Commit allows to atomically apply changes to main functions instance.
void commit();
// Used only by unittest.
void clear_functions() noexcept;
void remove_function(function_name& name, std::vector<data_type>& arg_types, bool aggregate = false) {
removed_functions.emplace_back(name, arg_types, aggregate);
functions::remove_function(name, arg_types);
};
void remove_aggregate(function_name& name, std::vector<data_type>& arg_types) {
remove_function(name, arg_types, true);
}
};
}
}