// // SesssionHandle.cpp // // Library: Data/MySQL // Package: MySQL // Module: SessionHandle // // Copyright (c) 2008, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 // #include "Poco/Data/MySQL/SessionHandle.h" #include "Poco/Data/DataException.h" #include "Poco/SingletonHolder.h" #ifdef POCO_OS_FAMILY_UNIX #include #endif #if LIBMYSQL_VERSION_ID >= 80000 typedef bool my_bool; // Workaround to make library work with MySQL client 8.0 as well as earlier versions #endif #define POCO_MYSQL_VERSION_NUMBER ((NDB_VERSION_MAJOR<<16) | (NDB_VERSION_MINOR<<8) | (NDB_VERSION_BUILD&0xFF)) namespace Poco { namespace Data { namespace MySQL { #ifdef POCO_OS_FAMILY_UNIX class ThreadCleanupHelper { public: ThreadCleanupHelper() { if (pthread_key_create(&_key, &ThreadCleanupHelper::cleanup) != 0) throw Poco::SystemException("cannot create TLS key for mysql cleanup"); } void init() { if (pthread_setspecific(_key, reinterpret_cast(1))) throw Poco::SystemException("cannot set TLS key for mysql cleanup"); } static ThreadCleanupHelper& instance() { return *_sh.get(); } static void cleanup(void* data) { mysql_thread_end(); } private: pthread_key_t _key; static Poco::SingletonHolder _sh; }; Poco::SingletonHolder ThreadCleanupHelper::_sh; #endif SessionHandle::SessionHandle(MYSQL* mysql): _pHandle(0) { init(mysql); #ifdef POCO_OS_FAMILY_UNIX ThreadCleanupHelper::instance().init(); #endif } void SessionHandle::init(MYSQL* mysql) { if (!_pHandle) { _pHandle = mysql_init(mysql); if (!_pHandle) throw ConnectionException("mysql_init error"); } } SessionHandle::~SessionHandle() { close(); } void SessionHandle::options(mysql_option opt) { if (mysql_options(_pHandle, opt, 0) != 0) throw ConnectionException("mysql_options error", _pHandle); } void SessionHandle::options(mysql_option opt, bool b) { my_bool tmp = b; if (mysql_options(_pHandle, opt, &tmp) != 0) throw ConnectionException("mysql_options error", _pHandle); } void SessionHandle::options(mysql_option opt, const char* c) { if (mysql_options(_pHandle, opt, c) != 0) throw ConnectionException("mysql_options error", _pHandle); } void SessionHandle::options(mysql_option opt, unsigned int i) { #if (POCO_MYSQL_VERSION_NUMBER < 0x050108) const char* tmp = (const char *)&i; #else const void* tmp = (const void *)&i; #endif if (mysql_options(_pHandle, opt, tmp) != 0) throw ConnectionException("mysql_options error", _pHandle); } void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port) { #ifdef HAVE_MYSQL_REAL_CONNECT if (!mysql_real_connect(_pHandle, host, user, password, db, port, 0, 0)) throw ConnectionFailedException(mysql_error(_pHandle)); #else if (!mysql_connect(_pHandle, host, user, password)) throw ConnectionFailedException(mysql_error(_pHandle)) #endif } void SessionHandle::close() { if (_pHandle) { mysql_close(_pHandle); _pHandle = 0; } } void SessionHandle::startTransaction() { int rc = mysql_autocommit(_pHandle, false); if (rc != 0) { // retry if connection lost int err = mysql_errno(_pHandle); if (err == 2006 /* CR_SERVER_GONE_ERROR */ || err == 2013 /* CR_SERVER_LOST */) { rc = mysql_autocommit(_pHandle, false); } } if (rc != 0) throw TransactionException("Start transaction failed.", _pHandle); } void SessionHandle::commit() { if (mysql_commit(_pHandle) != 0) throw TransactionException("Commit failed.", _pHandle); } void SessionHandle::rollback() { if (mysql_rollback(_pHandle) != 0) throw TransactionException("Rollback failed.", _pHandle); } void SessionHandle::reset() { #if defined(HAVE_MYSQL_RESET_CONNECTION) && (((defined (MYSQL_VERSION_ID)) && (MYSQL_VERSION_ID >= 50700)) || ((defined (MARIADB_PACKAGE_VERSION_ID)) && (MARIADB_PACKAGE_VERSION_ID >= 30000))) if (mysql_reset_connection(_pHandle) != 0) #else if (mysql_refresh(_pHandle, REFRESH_TABLES | REFRESH_STATUS | REFRESH_THREADS | REFRESH_READ_LOCK) != 0) #endif throw TransactionException("Reset connection failed.", _pHandle); } bool SessionHandle::ping() { int rc = mysql_ping(_pHandle); return rc == 0; } } } } // namespace Poco::Data::MySQL