/* Copyright (c) 2014, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. This program is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have either included with the program or referenced in the documentation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DD__SDI_UTILS_INCLUDED #define DD__SDI_UTILS_INCLUDED #include #include "sql/current_thd.h" // inline_current_thd #include "sql/dd/string_type.h" // dd::String_type #include "sql/error_handler.h" // Internal_error_handler #include "sql/mdl.h" // MDL_request #include "sql/sql_class.h" // THD #ifndef NDEBUG #define ENTITY_FMT "(%s, %llu)" #define ENTITY_VAL(obj) (obj).name().c_str(), (obj).id() #endif /* !NDEBUG */ /** @file @ingroup sdi Inline utility functions used in different TUs. Declared inline in header to avoid any overhead as they are only a syntactic convnience (macro replacement). */ namespace dd { namespace sdi_utils { /** In debug mode, check that a true argument is paired with thd->is_error() or thd->killed being set. In optimized mode it turns into a noop. @param[in] ret return value to check @return same as argument passed in */ inline bool checked_return(bool ret) { #ifndef NDEBUG THD *cthd = current_thd; assert(!ret || cthd->is_system_thread() || cthd->is_error() || cthd->killed); #endif /*!NDEBUG*/ return ret; } /** Convenience function for obtaining MDL. Sets up the MDL_request struct and populates it, before calling Mdl_context::acquire_lock. @param thd thread context @param ns MDL key namespace @param schema_name schema name @param object_name object name @param mt MDL type @param md MDL duration @return value from Mdl_context::acquire_lock */ inline bool mdl_lock(THD *thd, MDL_key::enum_mdl_namespace ns, const String_type &schema_name, const String_type &object_name, enum_mdl_type mt = MDL_EXCLUSIVE, enum_mdl_duration md = MDL_TRANSACTION) { MDL_request mdl_request; MDL_REQUEST_INIT(&mdl_request, ns, schema_name.c_str(), object_name.c_str(), mt, md); return checked_return(thd->mdl_context.acquire_lock( &mdl_request, thd->variables.lock_wait_timeout)); } template const T &ptr_as_cref(const T *p) { assert(p != nullptr); return *p; } /** Class template which derives from Internal_error_handler and overrides handle_condition with the CONDITION_HANDLER_CLOS template parameter. */ template class Closure_error_handler : public Internal_error_handler { CONDITION_HANDLER_CLOS m_ch; bool handle_condition(THD *, uint sql_errno, const char *sqlstate, Sql_condition::enum_severity_level *level, const char *msg) override { return m_ch(sql_errno, sqlstate, level, msg); } public: // CONDITION_HANDLER_CLOS is *class* template argument, so there is no type // deduction, and ch must refer to an R-value. So it is safe to move. explicit Closure_error_handler(CONDITION_HANDLER_CLOS &&ch) : m_ch(std::move(ch)) {} }; /** Set up a custom error handler to use for errors from the execution of a closure. @param thd thread context @param chc closure which implements the Internal_error_handler::handle_condition override @param ac closure action for which error conditions should be handled. @retval true if an error occurs @retval false otherwise */ template bool handle_errors(THD *thd, CH_CLOS &&chc, ACTION_CLOS &&ac) { Closure_error_handler eh{std::forward(chc)}; thd->push_internal_handler(&eh); bool r = ac(); thd->pop_internal_handler(); return r; } template std::unique_ptr make_guard(P_TYPE *p, CLOS_TYPE &&clos) { return std::unique_ptr(p, std::forward(clos)); } } // namespace sdi_utils } // namespace dd #endif // DD__SDI_UTILS_INCLUDED