/* * 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 #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>; void add_agg_functions(declared_t& funcs); class functions { friend class change_batch; std::unordered_multimap> init() noexcept; protected: using declared_t = cql3::functions::declared_t; declared_t _declared; struct skip_init {}; functions(skip_init) {}; public: lw_shared_ptr make_arg_spec(const sstring& receiver_ks, std::optional receiver_cf, const function& fun, size_t i) const; functions() : _declared(init()) {} shared_ptr get(data_dictionary::database db, const sstring& keyspace, const function_name& name, const std::vector>& provided_args, const sstring& receiver_ks, std::optional receiver_cf, const column_specification* receiver = nullptr) const; template shared_ptr get(data_dictionary::database db, const sstring& keyspace, const function_name& name, AssignmentTestablePtrRange&& provided_args, const sstring& receiver_ks, std::optional receiver_cf, const column_specification* receiver = nullptr) const { const std::vector> args(std::begin(provided_args), std::end(provided_args)); return get(db, keyspace, name, args, receiver_ks, receiver_cf, receiver); } std::vector> get_user_functions(const sstring& keyspace) const; std::vector> get_user_aggregates(const sstring& keyspace) const; std::ranges::subrange find(const function_name& name) const; declared_t::const_iterator find_iter(const function_name& name, const std::vector& arg_types) const; shared_ptr find(const function_name& name, const std::vector& arg_types) const; shared_ptr mock_get(const function_name& name, const std::vector& arg_types) const; void add_function(shared_ptr); void replace_function(shared_ptr); void remove_function(const function_name& name, const std::vector& arg_types); std::optional used_by_user_aggregate(shared_ptr) const; std::optional used_by_user_function(const ut_name& user_type) const; private: void with_udf_iter(const function_name& name, const std::vector& arg_types, std::function f); template std::vector> 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 fun, const std::vector>& provided_args, const sstring& receiver_ks, std::optional receiver_cf) const; assignment_testable::test_result match_arguments(data_dictionary::database db, const sstring& keyspace, const schema* schema_opt, shared_ptr fun, const std::vector>& provided_args, const sstring& receiver_ks, std::optional receiver_cf) const; bool type_equals(const std::vector& t1, const std::vector& 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 arg_types; bool aggregate; }; std::vector 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& 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& arg_types) { remove_function(name, arg_types, true); } }; } }