driver/connection_handler.cc (72 lines of code) (raw):

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // // 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 // (GPLv2), as published by the Free Software Foundation, with the // following additional permissions: // // This program is distributed with certain software that is licensed // under separate terms, as designated in a particular file or component // or in the license documentation. Without limiting your rights under // the GPLv2, the authors of this program hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have included with the program. // // Without limiting the foregoing grant of rights under the GPLv2 and // additional permission as to separately licensed software, this // program is also subject to the Universal FOSS Exception, version 1.0, // a copy of which can be found along with its FAQ at // http://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, see // http://www.gnu.org/licenses/gpl-2.0.html. /** @file connection_handler.c @brief connection functions. */ #include "connection_handler.h" #include "connection_proxy.h" #include "driver.h" #include <codecvt> #include <locale> #ifdef __linux__ sqlwchar_string to_sqlwchar_string(const std::string& src) { return std::wstring_convert< std::codecvt_utf8_utf16< char16_t >, char16_t >{} .from_bytes(src); } #else sqlwchar_string to_sqlwchar_string(const std::string& src) { return std::wstring_convert< std::codecvt_utf8< wchar_t >, wchar_t >{} .from_bytes(src); } #endif CONNECTION_HANDLER::CONNECTION_HANDLER(DBC* dbc) : dbc{dbc} {} CONNECTION_HANDLER::~CONNECTION_HANDLER() = default; SQLRETURN CONNECTION_HANDLER::do_connect(DBC* dbc_ptr, DataSource* ds, bool failover_enabled, bool is_monitor_connection) { return dbc_ptr->connect(ds, failover_enabled, is_monitor_connection); } CONNECTION_PROXY* CONNECTION_HANDLER::connect(std::shared_ptr<HOST_INFO> host_info, DataSource* ds, bool is_monitor_connection) { if (dbc == nullptr || host_info == nullptr) { return nullptr; } DataSource* ds_to_use = new DataSource(); ds_to_use->copy(ds ? ds : dbc->ds); const auto new_host = to_sqlwchar_string(host_info->get_host()); DBC* dbc_clone = clone_dbc(dbc, ds_to_use); ds_to_use->opt_SERVER.set_remove_brackets((SQLWCHAR*) new_host.c_str(), new_host.size()); CONNECTION_PROXY* new_connection = nullptr; CLEAR_DBC_ERROR(dbc_clone); const SQLRETURN rc = do_connect(dbc_clone, ds_to_use, ds_to_use->opt_ENABLE_CLUSTER_FAILOVER, is_monitor_connection); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { new_connection = dbc_clone->connection_proxy; dbc_clone->connection_proxy = nullptr; } my_SQLFreeConnect(dbc_clone); if (new_connection != nullptr) { new_connection->set_dbc(dbc); } return new_connection; } void CONNECTION_HANDLER::update_connection( CONNECTION_PROXY* new_connection, const std::string& new_host_name) { if (new_connection->is_connected()) { dbc->close(); dbc->connection_proxy->set_connection(new_connection); CLEAR_DBC_ERROR(dbc); const sqlwchar_string new_host_name_wstr = to_sqlwchar_string(new_host_name); // Update original ds to reflect change in host/server. dbc->ds->opt_SERVER.set_remove_brackets((SQLWCHAR*) new_host_name_wstr.c_str(), new_host_name_wstr.size()); } } DBC* CONNECTION_HANDLER::clone_dbc(DBC* source_dbc, DataSource* ds) { DBC* dbc_clone = nullptr; SQLRETURN status = SQL_ERROR; if (source_dbc && source_dbc->env) { SQLHDBC hdbc; SQLHENV henv = static_cast<SQLHANDLE>(source_dbc->env); status = my_SQLAllocConnect(henv, &hdbc); if (status == SQL_SUCCESS || status == SQL_SUCCESS_WITH_INFO) { dbc_clone = static_cast<DBC*>(hdbc); dbc_clone->init_proxy_chain(ds); } else { const char* err = "Cannot allocate connection handle when cloning DBC"; MYLOG_DBC_TRACE(dbc, err); throw std::runtime_error(err); } } return dbc_clone; }