xapi/session.cc (208 lines of code) (raw):

/* * Copyright (c) 2016, 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. * * Without limiting anything contained in the foregoing, this file, * which is part of Connector/C++, is also subject to the * Universal FOSS Exception, version 1.0, a copy of which can be found at * https://oss.oracle.com/licenses/universal-foss-exception. * * 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 */ #include <mysqlx/common.h> #include <mysqlx/xapi.h> #include "mysqlx_cc_internal.h" #include <algorithm> #include <string> using namespace mysqlx::common; mysqlx_session_struct::mysqlx_session_struct( mysqlx_client_t *cli) { if (cli) m_impl = std::make_shared<Session_impl>(cli->get_impl()); else throw_error("Invalid client pool"); } mysqlx_session_struct::mysqlx_session_struct( mysqlx_session_options_struct *opt ) { cdk::ds::Multi_source ds; opt->get_data_source(ds); m_impl = std::make_shared<Session_impl>(ds); } mysqlx_session_struct::mysqlx_session_struct( const std::string &host, unsigned short port, const std::string &usr, const std::string *pwd, const std::string *db ) : mysqlx_session_struct(mysqlx_session_options_struct(host, port, usr, pwd, db)) {} mysqlx_session_struct::mysqlx_session_struct( const std::string &conn_str ) : mysqlx_session_struct(mysqlx_session_options_struct(conn_str)) {} mysqlx_stmt_struct* mysqlx_session_struct::sql_query(const char *query_utf8, uint32_t length) { if (!query_utf8 || !(*query_utf8)) throw Mysqlx_exception("Query is empty"); if (length == MYSQLX_NULL_TERMINATED) length = (uint32_t)strlen(query_utf8); std::string query(query_utf8, length); return new_stmt<OP_SQL>(cdk::string(query)); // note: UTF8 conversion } mysqlx_error_struct * mysqlx_session_struct::get_last_error() { cdk::Session &sess = get_session(); // Return session errors from CDK first if (sess.entry_count()) { m_error.set(&sess.get_error()); } else if (!m_error.message() && !m_error.error_num()) return NULL; return &m_error; } const cdk::Error * mysqlx_session_struct::get_cdk_error() { if (get_session().entry_count()) return &get_session().get_error(); return NULL; } void mysqlx_session_struct::reset_diagnostic() { m_error.reset(); } void mysqlx_session_struct::transaction_begin() { // Note: the internal implementation object handles registered results etc. stmt_traits<OP_TRX_BEGIN>::Impl stmt(m_impl); stmt.execute(); } void mysqlx_session_struct::transaction_commit() { stmt_traits<OP_TRX_COMMIT>::Impl stmt(m_impl); stmt.execute(); } void mysqlx_session_struct::transaction_rollback(const char *sp) { stmt_traits<OP_TRX_ROLLBACK>::Impl stmt( m_impl, sp ? std::string(sp) : std::string() ); stmt.execute(); } const char * mysqlx_session_struct::savepoint_set(const char *sp) { stmt_traits<OP_TRX_SAVEPOINT_SET>::Impl stmt( m_impl, sp ? std::string(sp) : std::string() ); stmt.execute(); m_savepoint_name = stmt.get_name(); return m_savepoint_name.c_str(); } void mysqlx_session_struct::savepoint_remove(const char *sp) { if (!sp || !sp[0]) throw_error("Invalid empty save point name"); stmt_traits<OP_TRX_SAVEPOINT_RM>::Impl stmt(m_impl, std::string(sp)); stmt.execute(); } /* ============================================================================ Client object implementation */ mysqlx_client_struct::mysqlx_client_struct(const char *conn_str, const char *client_opt) { mysqlx_session_options_struct opt(conn_str); if (client_opt) opt.set_client_opts(client_opt); cdk::ds::Multi_source ds; opt.get_data_source(ds); m_impl.reset(new Session_pool(ds)); m_impl->set_pool_opts(opt); } mysqlx_client_struct::mysqlx_client_struct(mysqlx_session_options_t *opt) { cdk::ds::Multi_source ds; opt->get_data_source(ds); m_impl.reset(new Session_pool(ds)); m_impl->set_pool_opts(*opt); } using cdk::foundation::connection::TLS; TLS::Options::SSL_MODE uint_to_ssl_mode(unsigned int mode) { switch (mode) { case SSL_MODE_DISABLED: return TLS::Options::SSL_MODE::DISABLED; case SSL_MODE_REQUIRED: return TLS::Options::SSL_MODE::REQUIRED; case SSL_MODE_VERIFY_CA: return TLS::Options::SSL_MODE::VERIFY_CA; case SSL_MODE_VERIFY_IDENTITY: return TLS::Options::SSL_MODE::VERIFY_IDENTITY; default: assert(false); // Quiet compile warnings return TLS::Options::SSL_MODE::DISABLED; } } unsigned int ssl_mode_to_uint(TLS::Options::SSL_MODE mode) { switch (mode) { case TLS::Options::SSL_MODE::DISABLED: return SSL_MODE_DISABLED; case TLS::Options::SSL_MODE::REQUIRED: return SSL_MODE_REQUIRED; case TLS::Options::SSL_MODE::VERIFY_CA: return SSL_MODE_VERIFY_CA; case TLS::Options::SSL_MODE::VERIFY_IDENTITY: return SSL_MODE_VERIFY_IDENTITY; default: assert(false); // Quiet compile warnings return 0; } } const char* opt_name(mysqlx_opt_type_t opt) { using Option = Settings_impl::Session_option_impl; return Settings_impl::option_name(Option(opt)); } const char* ssl_mode_name(mysqlx_ssl_mode_t m) { using SSL_mode = Settings_impl::SSL_mode; return Settings_impl::ssl_mode_name(SSL_mode(m)); } struct Error_bad_option : public Mysqlx_exception { Error_bad_option() : Mysqlx_exception("Unrecognized connection option") {} Error_bad_option(const std::string &opt) : Error_bad_option() { m_message += ": " + opt; } Error_bad_option(unsigned int opt) : Error_bad_option() { std::ostringstream buf; buf << opt; m_message += " (" + buf.str() + ")"; } }; struct Error_dup_option : public Mysqlx_exception { Error_dup_option(mysqlx_opt_type_t opt) { m_message = "Option "; m_message += opt_name(opt); m_message += " defined twice"; } }; struct Error_bad_mode : public Mysqlx_exception { Error_bad_mode(const std::string &m) { m_message = "Unrecognized ssl-mode: " + m; } }; struct Error_ca_mode : public Mysqlx_exception { Error_ca_mode() : Mysqlx_exception("The ssl-ca option is not compatible with ssl-mode") {} Error_ca_mode(mysqlx_ssl_mode_t m) : Error_ca_mode() { m_message += " "; m_message += ssl_mode_name(m); } Error_ca_mode(TLS::Options::SSL_MODE m) : Error_ca_mode(mysqlx_ssl_mode_t(ssl_mode_to_uint(m))) {} };