From cbd68abde85c3b0d80e7d9656f35db17606bfbcd Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 29 Jun 2023 16:02:12 +0300 Subject: [PATCH] cql: selection: convert used_functions() to expressions used_functions() is used to check whether prepared statements need to be invalidated when user-defined functions change. We need to skip over empty scalar components of aggregates, since these can be defined by users (with the same meaning as if the identity function was used). --- cql3/selection/selection.cc | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/cql3/selection/selection.cc b/cql3/selection/selection.cc index bfc4fd4ec1..a21fc334ec 100644 --- a/cql3/selection/selection.cc +++ b/cql3/selection/selection.cc @@ -297,7 +297,24 @@ public: } virtual std::vector> used_functions() const override { - return selectors_with_processing(_factories).used_functions(); + auto ret = std::vector>(); + expr::recurse_until(expr::tuple_constructor{_selectors}, [&] (const expr::expression& e) { + if (auto fc = expr::as_if(&e)) { + auto func = std::get>(fc->func); + ret.push_back(func); + if (auto agg_func = dynamic_pointer_cast(std::move(func))) { + auto& agg = agg_func->get_aggregate(); + if (agg.aggregation_function) { + ret.push_back(agg.aggregation_function); + } + if (agg.state_to_result_function) { + ret.push_back(agg.state_to_result_function); + } + } + } + return false; + }); + return ret; } protected: @@ -305,11 +322,13 @@ protected: private: ::shared_ptr _factories; std::vector<::shared_ptr> _selectors; + const selection_with_processing& _sel; bool _requires_thread; public: - selectors_with_processing(::shared_ptr factories) + selectors_with_processing(const selection_with_processing& sel, ::shared_ptr factories) : _factories(std::move(factories)) , _selectors(_factories->new_instances()) + , _sel(sel) , _requires_thread(boost::algorithm::any_of(_selectors, [] (auto& s) { return s->requires_thread(); })) { } @@ -343,22 +362,12 @@ protected: } std::vector> used_functions() const { - std::vector> functions; - for (const auto& selector : _selectors) { - if (auto fun_selector = dynamic_pointer_cast(selector); fun_selector) { - functions.push_back(fun_selector->function()); - if (auto user_aggr = dynamic_pointer_cast(fun_selector); user_aggr) { - functions.push_back(user_aggr->sfunc()); - functions.push_back(user_aggr->finalfunc()); - } - } - } - return functions; + return _sel.used_functions(); } }; std::unique_ptr new_selectors() const override { - return std::make_unique(_factories); + return std::make_unique(*this, _factories); } };