From 5824fa65fdf0517793897d79f2f4858408c2b2ae Mon Sep 17 00:00:00 2001 From: Gipson Pulla Date: Thu, 26 Sep 2024 15:23:20 +0530 Subject: [PATCH 01/43] ET#81319 C/CPP weekly branch is broken with DEB and RPM builds adjusting the date in the RPM spec file --- packaging/mysql-connector-c++.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/mysql-connector-c++.spec.in b/packaging/mysql-connector-c++.spec.in index 7ba66f230..a7a2062fe 100644 --- a/packaging/mysql-connector-c++.spec.in +++ b/packaging/mysql-connector-c++.spec.in @@ -175,7 +175,7 @@ rm %{buildroot}/usr/*.cmake %{_includedir}/mysql-cppconn %changelog -* Mon May 12 2024 Gipson Pulla - 9.0.0-1 +* Sun May 12 2024 Gipson Pulla - 9.0.0-1 - Bumped the version to 9.0.0 series. * Fri Nov 03 2023 Sreedhar Sreedhargadda - 8.2.0-1 From 4efbdac8af4a2ea814af77afd58e28f3ee0f24b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 2 Sep 2024 16:01:46 +0200 Subject: [PATCH 02/43] cmake: Add openid_connect to the list of bundled plugins --- jdbc/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/jdbc/CMakeLists.txt b/jdbc/CMakeLists.txt index 84710ff79..60e36e42d 100644 --- a/jdbc/CMakeLists.txt +++ b/jdbc/CMakeLists.txt @@ -429,6 +429,7 @@ endif() set(AUTH_PLUGINS ldap_sasl oci + openid_connect ) if(NOT CMAKE_SYSTEM_NAME MATCHES "SunOS") From a0de055f18ee44591126e1721da04d71d4a70616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Fri, 6 Sep 2024 14:47:39 +0200 Subject: [PATCH 03/43] Add SECURITY.md, update CONTRIBUTING.md --- CONTRIBUTING.md | 38 ++++++++++++++++++-------------------- SECURITY.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 SECURITY.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1d376eb1..1f6990ba2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,33 +9,31 @@ Before reporting a new bug, please check first to see if a similar bug [exists]( Bug reports should be as complete as possible. Please try and include the following: * complete steps to reproduce the issue -* any information about platform and environment that could be specific to the bug +* any information about platform and environment that could be specific to + the bug * Specific version of the product you are using * Specific version of the server being used * C++ code to help reproduce the issue if possible +Please do NOT raise a GitHub Issue to report a security vulnerability. +See SECURITY.md for additional information. + ## Contributing Code -Contributing to this project is easy. You just need to follow these steps. +You need to follow these steps. -* Sign the Oracle Contributor Agreement. You can find instructions for doing that at [OCA Page](https://oca.opensource.oracle.com/) +* Make sure you have a user account at bugs.mysql.com. You'll need to reference + this user account when you submit your OCA (Oracle Contributor Agreement). +* Sign the Oracle Contributor Agreement. You can find instructions for doing + that at [OCA Page](https://oca.opensource.oracle.com/) * Develop your pull request - * Make sure you are aware of the requirements for the project (i.e. don't require C++17 if we are supporting C++11 and higher) -* Validate your pull request by including tests that sufficiently cover the functionality -* Verify that the entire test suite passes with your code applied +* Make sure you are aware of the requirements for the project (i.e. don't + require C++20 if we are supporting C++17 and higher) +* Validate your pull request by including tests that sufficiently cover + the functionality * Submit your pull request +* It is also possible to upload your changes using the 'contribution' tab to + a bug record in https://bugs.mysql.com. -## Running Tests - -Any contributed code should pass our unit tests. -To run the unit tests you need to perform the following steps: - -* Build the Connector/C++ with the cmake option enabling unit tests (-DWITH_TESTS=1) -* Run MySQL Server -* Set the following environment variables: - * XPLUGIN_PORT = - * XLPIGIN_USER = - * XPLUGIN_PASSWORD = -* In the OS command line enter the Connector/C++ build directory and run `ctest` utility - -At the end of `ctest` run the result should indicate 100% tests passed. +Only pull requests from committers that can be verified as having signed the OCA +can be accepted. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..b14ced6a7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Reporting security vulnerabilities + +Oracle values the independent security research community and believes that +responsible disclosure of security vulnerabilities helps us ensure the security +and privacy of all our users. + +Please do NOT raise a GitHub Issue to report a security vulnerability. If you +believe you have found a security vulnerability, please submit a report to +secalert_us@oracle.com preferably with a proof of concept. Please review +some [additional information](https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html) +on how to report security vulnerabilities to Oracle. We encourage people who +contact Oracle Security to use email encryption using our [encryption key](https://www.oracle.com/security-alerts/encryptionkey.html). + +We ask that you do not use other channels or contact the project maintainers +directly. + +Non-vulnerability related security issues including ideas for new or improved +security features are welcome on GitHub Issues. + +## Security updates, alerts and bulletins + +Security updates will be released on a regular cadence. Many of our projects +will typically release security fixes in conjunction with the Oracle Critical Patch +Update program. Additional information, including past advisories, is available +on our [security alerts page](https://www.oracle.com/security-alerts/). + +## Security-related information + +We will provide security related information such as a threat model, considerations +for secure use, or any known security issues in our documentation. Please note +that labs and sample code are intended to demonstrate a concept and may not be +sufficiently hardened for production use. \ No newline at end of file From 1b98739cd6a3d9910d9ebd14b0a666490490e986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Tue, 8 Oct 2024 09:08:53 +0200 Subject: [PATCH 04/43] jdbc/test: Fix use of std::filesystem with gcc8 --- jdbc/test/CMakeLists.txt | 18 ++++++++++++++---- jdbc/test/unit/CMakeLists.txt | 7 ++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/jdbc/test/CMakeLists.txt b/jdbc/test/CMakeLists.txt index a8ee26532..50e9b2b14 100644 --- a/jdbc/test/CMakeLists.txt +++ b/jdbc/test/CMakeLists.txt @@ -41,6 +41,20 @@ INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/include") INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/include/jdbc") INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/include/jdbc/cppconn") +set(MY_TARGET_LINK_LIBRARIES connector-jdbc) + + +if(DEFINED GCC AND GCC VERSION_LESS 9) + + # Note: Some unit tests use std::filesystem part of the standard library + # Before version 9 of gcc that requires linking with the additional library + + list(APPEND MY_TARGET_LINK_LIBRARIES -lstdc++fs) + # message(STATUS "Added libstdc++fs for GCC version ${GCC}: ${MY_TARGET_LINK_LIBRARIES}") + +endif() + + IF(MSBUILD) IF(CMAKE_BUILD_TYPE STREQUAL "Debug") LINK_DIRECTORIES(${MYSQL_DIR}/lib/debug) @@ -50,10 +64,6 @@ IF(MSBUILD) ADD_DEFINITIONS("-D_SCL_SECURE_NO_WARNINGS") ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS") - - SET(MY_TARGET_LINK_LIBRARIES connector-jdbc) -ELSEIF(NOT MSBUILD) - SET(MY_TARGET_LINK_LIBRARIES connector-jdbc) ENDIF() if(NOT MYSQLCLIENT_STATIC_LINKING) diff --git a/jdbc/test/unit/CMakeLists.txt b/jdbc/test/unit/CMakeLists.txt index 0fa38be18..29b7f7be8 100644 --- a/jdbc/test/unit/CMakeLists.txt +++ b/jdbc/test/unit/CMakeLists.txt @@ -26,12 +26,13 @@ # along with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +list(APPEND MY_TARGET_LINK_LIBRARIES test_framework) + IF(WIN32) if(MSBUILD) LINK_DIRECTORIES(${MYSQL_DIR}/lib/$(ConfigurationName)) LINK_DIRECTORIES(../framework/$(ConfigurationName)) endif() - SET(MY_TARGET_LINK_LIBRARIES connector-jdbc test_framework) SET(MY_TARGET_LINK_LIBRARIES_STATIC_CPPLIB connector-jdbc-static test_framework) # ADD_DEFINITIONS("-D_SECURE_SCL") ADD_DEFINITIONS("-D_SCL_SECURE_NO_WARNINGS") @@ -64,7 +65,6 @@ IF(WIN32) ) ELSEIF(NOT WIN32) - SET(MY_TARGET_LINK_LIBRARIES connector-jdbc test_framework) FIND_LIBRARY(MYSQLCPPCONN_DYNLOAD_MYSQL_LIB NAMES libmysqlclient_r.so @@ -95,9 +95,6 @@ ELSEIF(NOT WIN32) ) ENDIF(WIN32) -if(NOT MYSQLCLIENT_STATIC_LINKING) - list(APPEND MY_TARGET_LINK_LIBRARIES MySQL::client) -endif() IF(CMAKE_COMPILER_IS_GNUCC AND MYSQLCPPCONN_GCOV_ENABLE) SET(MY_GCOV_LINK_LIBRARIES gcov) From 457e63dfcf18a3782cd1d0354a69381e92579161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Tue, 8 Oct 2024 09:53:25 +0200 Subject: [PATCH 05/43] jdbc/test: Fix install specs for OpenID test tokens --- jdbc/test/unit/classes/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdbc/test/unit/classes/CMakeLists.txt b/jdbc/test/unit/classes/CMakeLists.txt index 80d23482f..a3e1477e5 100644 --- a/jdbc/test/unit/classes/CMakeLists.txt +++ b/jdbc/test/unit/classes/CMakeLists.txt @@ -221,7 +221,7 @@ foreach (token # Install tokens install( - FILES ${token} + FILES tokens/${token} DESTINATION tests/jdbc COMPONENT JDBCTests EXCLUDE_FROM_ALL From ec885974e6a747f665289fcd5b2cfa6cb74d3a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Wed, 9 Oct 2024 11:15:34 +0200 Subject: [PATCH 06/43] Ignore stuff in .vscode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 39affa8f2..59cf60a56 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .vs out CMakeUserPresets.json +.vscode From 70bcefc43c55b802b8fbb4231f20aa9717bdf77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Wed, 13 Nov 2024 13:52:34 +0100 Subject: [PATCH 07/43] cdk: Disable false -Warray-bounds and -Wstringop-overflow warnings --- CMakeLists.txt | 3 +++ cdk/include/mysql/cdk/foundation/codec.h | 8 ++++++++ cdk/include/mysql/cdk/foundation/common.h | 21 ++++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 341ed2de7..e87a67076 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,7 +299,10 @@ endif() if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0) # Silence a warning produced by a regression in GCC 12.0 and newer # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106199 + # Note: The stringop-overflow warnings are shown also during linking phase + # (observed with GCC 14.2) add_compile_options(-Wno-stringop-overflow) + add_link_options(-Wno-stringop-overflow) endif() diff --git a/cdk/include/mysql/cdk/foundation/codec.h b/cdk/include/mysql/cdk/foundation/codec.h index 8310bb6ae..5551574c0 100644 --- a/cdk/include/mysql/cdk/foundation/codec.h +++ b/cdk/include/mysql/cdk/foundation/codec.h @@ -220,8 +220,14 @@ static size_t convert(bytes buf, T &val) /* If buf size is smaller than sizeof(T), convert 1,2,4 or 8 initial bytes from the buffer: as much as fits into T. + + Note: We check here that buffer size is big enough to store given amount + of bytes but compilers still complain under -Warray-bounds (seen on + Solaris with gcc 11.4). */ +PUSH_ARRAY_BOUNDS_WARNING_CDK + if (buf.size() >= sizeof(T)) { val= *(T*)buf.begin(); @@ -252,6 +258,8 @@ static size_t convert(bytes buf, T &val) return 1; } +POP_ARRAY_BOUNDS_WARNING_CDK + // TODO: better error description throw_error(cdkerrc::conversion_error, "Number_codec: no data for conversion"); diff --git a/cdk/include/mysql/cdk/foundation/common.h b/cdk/include/mysql/cdk/foundation/common.h index c13abca42..0ec552799 100644 --- a/cdk/include/mysql/cdk/foundation/common.h +++ b/cdk/include/mysql/cdk/foundation/common.h @@ -42,7 +42,7 @@ #define DIAGNOSTIC_PUSH_CDK PRAGMA_CDK(warning (push)) #define DIAGNOSTIC_POP_CDK PRAGMA_CDK(warning (pop)) -#elif defined __GNUC__ || defined __clang__ +#elif defined __GNUC__ || defined __clang__ #define PRAGMA_CDK(X) _Pragma(#X) #define DISABLE_WARNING_CDK(W) PRAGMA_CDK(GCC diagnostic ignored #W) @@ -113,6 +113,25 @@ #define POP_SYS_WARNINGS_CDK DIAGNOSTIC_POP_CDK +/* + Macros to disable false positives from -Warray-bounds checks for lines + of code that were manually verified to be correct. +*/ + +#ifdef _MSC_VER + +#define PUSH_ARRAY_BOUNDS_WARNING_CDK DIAGNOSTIC_PUSH_CDK +#define POP_ARRAY_BOUNDS_WARNING_CDK DIAGNOSTIC_POP_CDK + +#else + +#define PUSH_ARRAY_BOUNDS_WARNING_CDK \ + DIAGNOSTIC_PUSH_CDK DISABLE_WARNING_CDK(-Warray-bounds) +#define POP_ARRAY_BOUNDS_WARNING_CDK DIAGNOSTIC_POP_CDK + +#endif + + // Avoid warnings from Protobuf includes #if defined _MSC_VER From 0128aeb592462f53a1d96242206a50f2ddde2316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 18 Nov 2024 15:04:48 +0100 Subject: [PATCH 08/43] cmake: fix overwriting of WITH_MYSQL value if set by project consuming the package --- mysql-concpp-config.cmake.in | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mysql-concpp-config.cmake.in b/mysql-concpp-config.cmake.in index e1469eefb..d8e12d673 100644 --- a/mysql-concpp-config.cmake.in +++ b/mysql-concpp-config.cmake.in @@ -155,10 +155,20 @@ else() set(JDBC_MYSQL_DEP OFF) endif() -set(WITH_MYSQL ${JDBC_MYSQL_DEP} - CACHE INTERNAL - "MySQL install location (to find the client library)" -) +# Note: This script is executed as part of find_package() invocation. If +# the invoking project sets WITH_MYSQL variable we want its value to be used +# here as it should point at the actual install location. However, for some +# reason set(WITH_MYSQL ... CACHE ...) overwrites cache entry with the same +# name from the invoking project (probably a result of running it from inside +# find_package()). To avoid override we define cache entry only if the variable +# is not already set. + +if(NOT DEFINED WITH_MYSQL) + set(WITH_MYSQL ${JDBC_MYSQL_DEP} + CACHE INTERNAL + "MySQL install location (to find the client library)" + ) +endif() macro(main) From 98b28a1223eb5d36fd80bd43a4db7742bc843832 Mon Sep 17 00:00:00 2001 From: Gipson Pulla Date: Tue, 19 Nov 2024 14:07:38 +0530 Subject: [PATCH 09/43] ET#83337 CPP weekly branch issues with pkgver in OpenSuse The -p argument to %post* macro don't run when there is comment or more commands below. --- packaging/mysql-connector-c++.spec.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packaging/mysql-connector-c++.spec.in b/packaging/mysql-connector-c++.spec.in index 64b208877..71d79aedb 100644 --- a/packaging/mysql-connector-c++.spec.in +++ b/packaging/mysql-connector-c++.spec.in @@ -221,7 +221,8 @@ rm -rf %{buildroot}%{_libdir}/{plugin,private} %post jdbc -p /sbin/ldconfig -%postun jdbc -p /sbin/ldconfig +%postun jdbc +/sbin/ldconfig ############################################### From 2d864972361552eaeedc93df86b186b8f4d4e7fe Mon Sep 17 00:00:00 2001 From: Bogdan Degtyariov Date: Fri, 29 Nov 2024 14:01:19 +1100 Subject: [PATCH 10/43] Bug#36929651 - CPP: issues with loading authentication plugins Change-Id: Ifed7ea6554c0842d1dc1e0c808ec430b79f6402d --- jdbc/driver/mysql_connection.cpp | 456 +++++++++--------- jdbc/driver/mysql_connection.h | 63 ++- jdbc/driver/mysql_driver.cpp | 6 +- jdbc/driver/mysql_driver.h | 25 +- .../mysql_native_connection_wrapper.cpp | 156 +++++- .../mysql_native_connection_wrapper.h | 64 ++- .../nativeapi/native_connection_wrapper.h | 38 ++ jdbc/test/unit/classes/connection.cpp | 78 ++- 8 files changed, 608 insertions(+), 278 deletions(-) diff --git a/jdbc/driver/mysql_connection.cpp b/jdbc/driver/mysql_connection.cpp index e233698fd..bae182b1a 100644 --- a/jdbc/driver/mysql_connection.cpp +++ b/jdbc/driver/mysql_connection.cpp @@ -96,10 +96,6 @@ #endif -bool oci_plugin_is_loaded = false; -bool openid_plugin_is_loaded = false; - - #ifdef DEFAULT_PLUGIN_DIR std::string default_plugin_dir(DEFAULT_PLUGIN_DIR); #else @@ -429,130 +425,182 @@ struct Prio }; -/* - A callback setter object arranges for WebAuthn/Fido authentication - callbacks to be used by the WebAuthn clientlib authentication plugin. +sql::mysql::MySQL_Driver *MySQL_Connection::PluginGuard::callback_drv + = nullptr; + +MySQL_Connection::PluginGuard::state +MySQL_Connection::PluginGuard::webauthn_plugin_state + = state::NONE; + +MySQL_Connection::PluginGuard::PluginGuard(MySQL_Connection *c) +: prx{c->proxy} +{ + //assert(c); + if (!prx.expired()) + prx.lock()->lock_plugin(true); +} + - If a user has registered a callback with a driver that creates a connection - then a callback function is registered with authentication plugin which will - call the callback stored in the driver. +/* + This method arranges for the WebAuthN authentication plugin callback to be + set in agreement with the webauthn callback function specified by the given + driver: - The callback function registered with authentication plugin must be changed - depending on which driver is used to create a connection. A callback setter - object makes necessary changes when it detects that the current driver passed - to its ctor is different from the one used last time. + 1. If driver's callback is set then that callback should be called by + the plugin (if the plugin is used during authentication). - While exists, callback setter also prevents modification of authentication - plugin callbacks by concurrent threads. + 2. Otherwise, if there is no driver specific callback, the plugin should + use its default callback. */ -struct MySQL_Driver::WebAuthn_Callback_Setter +void MySQL_Connection::PluginGuard::register_webauthn_callback(MySQL_Driver &drv) { - using Proxy = NativeAPI::NativeConnectionWrapper; + std::string plugin = "authentication_webauthn_client"; + std::string opt = "plugin_authentication_webauthn_client_messages_callback"; + + if (prx.expired()) + return; + + auto proxy = prx.lock(); + + /* + Compute desired plugin state based on its current state nad driver settings. - WebAuthn_Callback_Setter(MySQL_Driver &drv, Proxy *prx) - : lock{mutex} + Returns NONE if plugin is already in correct state, DEFAULT if plugin's + default callback should be restored or CALLER if plugin should + be configured to call driver's callback. + */ + + auto target_state = [&]() -> state { /* - Note: Meaning of callback type value: + If no WebAuthN callback is registered in the driver but + the plugin was configured to call driver's callback + ( webauthn_plugin_state == CALLER ) we must reset plugin to use its + default callback. + + Note that nothing needs to be done if plugin is not loaded at the moment + ( webauthn_plugin_state == NONE ) because in that case if the plugin + is loaded during authentication it will use its default callback as + required. + */ - 0 or 3 = no callback - 1 or 4 = webauthn only callback - 2 or 5 = webauthn and fido callback + if (!drv.webauthn_callback && webauthn_plugin_state == state::CALLER) + return state::DEFAULT; - Values 3,4,5 indicate that the callback function has been already - (de-)registered with the plugin(s). + /* + If driver has a WebAuthN callback but the plugin is not configured + to call it ( webauthn_plugin_state != CALLER ) or the driver whose + callback would be called is not correct ( callback_drv != &drv ) we must + configure the plugin accordingly. */ - auto callback_type = reinterpret_cast(drv.fido_callback); + if ( + drv.webauthn_callback + && (webauthn_plugin_state != state::CALLER || callback_drv != &drv) + ) + return state::CALLER; + // If neither of the above then the plugin is already in the correct state. + + return state::NONE; + }; + + + try + { /* - Do nothing if we use the same driver as last time nad (de-)registration - was already done. + There is nothing to be done if the plugin is already correctly + configured. We also know that no concurrent thread that makes + a connection can change plugin configuration because to do so it would + need to first grab an exclusive plugin lock (see below) and that is + not possible while this thread holds a shared lock. */ - if ((2 < callback_type) && (driver == &drv)) + if (state::NONE == target_state()) return; - driver = &drv; // Set current driver. - /* - Note: A webauthn callback (callback_type 2 or 5) is registered with - "webauthn" plugin as well as fido callback (callback_type 1 or 4). - If user did not register any callback (callback_type 0 or 3) then - plugin callback is re-set to null. + Current plugin configuration is not as needed nad we must change it + accordingly. To do so we first grab an exclusive plugin lock to ensure + that we don't change the current plugin configuration while another + thread is making connection and relying on it. */ - register_callback(prx, (callback_type % 3) > 0); + proxy->lock_plugin_exclusive(); /* - Note: This will be reset to value 0-2 when user deregisters - the callback or registers a new one. + Note that while upgrading the lock to an exclusive one other threads can + get it before this thread and can change the plugin configuration that + was present during first `target_state()` call above. For that reason we + call `target_state()` again to re-evaluate the required changes and act + accordingly. */ - drv.fido_callback = reinterpret_cast(callback_type + 3); - } - - private: + switch (target_state()) + { + case state::DEFAULT: + { + /* + Note: setting callback option to nullptr restores plugin's default + callback. + */ + proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + plugin, opt, nullptr); + webauthn_plugin_state = state::DEFAULT; + } + break; - // The driver whose callback will be called by authentication plugins. + case state::CALLER: + { + proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + plugin, opt, (const void*)callback_caller); + callback_drv = &drv; + webauthn_plugin_state = state::CALLER; + } + break; - static sql::mysql::MySQL_Driver * driver; - /* - Callback function to be registered with authentication plugins. - If the current driver has a stored callback then it is being called. - */ + default: break; + } - static void callback_func(const char* msg) + /* + At this point we have plugin configured as required by the diver callback + settings and we know this will not change as long as we hold the plugin + lock. + */ + } + catch (sql::MethodNotImplementedException &) { - if (!driver || !driver->fido_callback) + // Note: Ignore errors when re-setting the callback + if(!drv.webauthn_callback) return; - driver->webauthn_callback(msg); - } - static std::mutex mutex; - std::lock_guard lock; - - static - void register_callback(Proxy *proxy, bool set_or_reset) + } + catch (sql::InvalidArgumentException &e) { - std::string plugin = "authentication_webauthn_client"; - std::string opt = "plugin_authentication_webauthn_client"; - - try - { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - plugin.c_str(), opt.c_str(), - set_or_reset ? (const void*)callback_func : nullptr - ); - } - catch (sql::MethodNotImplementedException &) - { - // Note: Ignore errors when re-setting the callback - - if(!set_or_reset) - return; - - } - catch (sql::InvalidArgumentException &e) - { - if(!set_or_reset) - return; - - throw ::sql::SQLException( - "Failed to set fido message callback for " - + plugin + " plugin"); - } - }; + if(!drv.webauthn_callback) + return; -}; + throw ::sql::SQLException( + "Failed to set fido message callback for " + + plugin + " plugin"); + } +} -std::mutex MySQL_Driver::WebAuthn_Callback_Setter::mutex; -sql::mysql::MySQL_Driver *MySQL_Driver::WebAuthn_Callback_Setter::driver - = nullptr; +void MySQL_Connection::PluginGuard::callback_caller(const char* msg) +{ + if (!callback_drv || !callback_drv->webauthn_callback) + return; + callback_drv->webauthn_callback(msg); +} +MySQL_Connection::PluginGuard::~PluginGuard() +{ + if (!prx.expired()) + prx.lock()->lock_plugin(false); +} /* We support : @@ -1253,86 +1301,6 @@ void MySQL_Connection::init(ConnectOptionsMap & properties) proxy->options(MYSQL_OPT_SSL_MODE, &ssl_mode_val); #endif - } else if (!it->first.compare(OPT_OCI_CONFIG_FILE)) { - try { - p_s= (it->second).get(); - } catch (sql::InvalidArgumentException&) { - throw sql::InvalidArgumentException("Wrong type passed for OPT_OCI_CONFIG_FILE. Expected sql::SQLString."); - } - - try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_oci_client", - "oci-config-file", - *p_s); - oci_plugin_is_loaded = true; - } catch (sql::InvalidArgumentException &e) { - throw ::sql::SQLUnsupportedOptionException( - "Failed to set config file for authentication_oci_client plugin", - OPT_OCI_CONFIG_FILE - ); - } - } else if (!it->first.compare(OPT_OCI_CLIENT_CONFIG_PROFILE)) { - try { - p_s = (it->second).get(); - } catch (sql::InvalidArgumentException &) { - throw sql::InvalidArgumentException( - "Wrong type passed for OPT_OCI_CLIENT_CONFIG_PROFILE. Expected " - "sql::SQLString."); - } - - try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_oci_client", - "authentication-oci-client-config-profile", *p_s); - oci_plugin_is_loaded = true; - } catch (sql::InvalidArgumentException &e) { - throw ::sql::SQLUnsupportedOptionException( - "Failed to set config profile for authentication_oci_client plugin", - OPT_OCI_CLIENT_CONFIG_PROFILE); - } - - } else if (!it->first.compare(OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE)) { -#if defined(_WIN32) - try { - p_s = (it->second).get(); - } catch (sql::InvalidArgumentException &) { - throw sql::InvalidArgumentException( - "Wrong type passed for OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE. " - "Expected sql::SQLString."); - } - - try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_kerberos_client", - "plugin_authentication_kerberos_client_mode", - *p_s); - } catch (sql::InvalidArgumentException &e) { - throw ::sql::SQLUnsupportedOptionException( - "Failed to set config file for authentication_kerberos_client " - "plugin", - OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE); - } -#endif // defined(_WIN32) - } else if (!it->first.compare(OPT_OPENID_TOKEN_FILE)) { - try { - p_s= (it->second).get(); - } catch (sql::InvalidArgumentException&) { - throw sql::InvalidArgumentException("Wrong type passed for OPT_OPENID_TOKEN_FILE. Expected sql::SQLString."); - } - - try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_openid_connect_client", - "id-token-file", - *p_s); - openid_plugin_is_loaded = true; - } catch (sql::InvalidArgumentException &e) { - throw ::sql::SQLUnsupportedOptionException( - "Failed to set token file for authentication_openid_connect_client plugin", - OPT_OPENID_TOKEN_FILE - ); - } } else if (!it->first.compare(OPT_PLUGIN_DIR)) { // Nothing to do here: this option was handeld before the loop @@ -1358,49 +1326,115 @@ void MySQL_Connection::init(ConnectOptionsMap & properties) } /* End of cycle on connection options map */ - if (oci_plugin_is_loaded) { - if (properties.find(OPT_OCI_CONFIG_FILE) == properties.end()) { - // If OCI plugin is loaded, but oci-config-file is not explicitly set - // the option value needs resetting. - try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_oci_client", - "oci-config-file", - nullptr); - } catch (sql::InvalidArgumentException &) { - // Do nothing, the exception is expected. - } - } - if (properties.find(OPT_OCI_CLIENT_CONFIG_PROFILE) == properties.end()) { - // If OCI plugin is loaded, but oci-config-profile is not explicitly set - // the option value needs resetting. + /* + Setting plugin options. + + Note that plugins are shared between different drivers but each driver and + each connection can have its own plugin settings. For that reason plugin + options are set here, before making a connection, to the values specified + by this connection and driver. + + The guard is needed to prevent overwritting plugin options by another + connection while this connection is being established. + + Note: If connection options do not specify a value for a plugin option that + plugin option is set to null which resets it to its default value (which + could be overwriten by other connections). + + TODO: Move setting of plugin options later in the connection process, after + any other options which can take long time to set (e.g. OpenSSL options or + options involving DNS resolution). This is because setting plugin options + can potentially block other connection and this blocking should be as short + as possible. + */ + + MySQL_Connection::PluginGuard guard{this}; + + auto set_plugin_option = [this, &properties] ( + const ::sql::SQLString con_opt_name, + int plugin_type, + const ::sql::SQLString & plugin_name, + const ::sql::SQLString & option, + const char * err_msg) + { + sql::SQLString *p_s = nullptr; + + auto opt = properties.find(con_opt_name); + if (opt != properties.end()) + { try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_oci_client", - "authentication-oci-client-config-profile", - nullptr); - } catch (sql::InvalidArgumentException &) { - // Do nothing, the exception is expected. + p_s = (opt->second).get(); + } catch (sql::InvalidArgumentException&) { + throw sql::InvalidArgumentException( + "Wrong type passed for " + con_opt_name + + ". Expected sql::SQLString."); } } - } + /* + Note: the plugin option will be set to nullptr if the corresponding + connection option was not set. This has the effect of re-setting plugin + option to its default value (if it was changed). + */ - if (openid_plugin_is_loaded) { - if (properties.find(OPT_OPENID_TOKEN_FILE) == properties.end()) { - // If OpenID plugin is loaded, but OPT_OPENID_TOKEN_FILE is not explicitly set - // the option value needs resetting. - try { - proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN, - "authentication_openid_connect_client", - "id-token-file", - nullptr); - } catch (sql::InvalidArgumentException &) { - // Do nothing, the exception is expected. - } + const void* val = p_s ? p_s->c_str() : nullptr; + try { + proxy->plugin_option(plugin_type, plugin_name, option, val); + } catch (sql::InvalidArgumentException &e) { + if (val) + // Throw only when setting a non-null value + throw ::sql::SQLUnsupportedOptionException(err_msg, + con_opt_name.asStdString()); } - } + }; + + set_plugin_option(OPT_OCI_CONFIG_FILE, + MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + "authentication_oci_client", + "oci-config-file", + "Failed to set config file for authentication_oci_client plugin" + ); + + set_plugin_option(OPT_OCI_CLIENT_CONFIG_PROFILE, + MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + "authentication_oci_client", + "authentication-oci-client-config-profile", + "Failed to set config profile for authentication_oci_client plugin" + ); + +#if defined(_WIN32) + set_plugin_option(OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE, + MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + "authentication_kerberos_client", + "plugin_authentication_kerberos_client_mode", + "Failed to set config file for authentication_kerberos_client plugin" + ); +#endif + + set_plugin_option(OPT_OPENID_TOKEN_FILE, + MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + "authentication_openid_connect_client", + "id-token-file", + "Failed to set token file for authentication_openid_connect_client plugin" + ); + + /* + Setting webauthn callback functions. + + The callback is an option of the webauthn authentication plugin that + is configured on the driver level (as opposed to plugin options above, + which are configured on per-connection basis). Correctly setting the option + based on driver configuration is handled by register_webauthn_callback() function + of PluginGuard class. The option will be set only if needed. + + Note: If register_webauthn_callback() sets a callback then the plugin options guard + ensures that this callback function is not modified by other connections + while being used. + */ + + guard.register_webauthn_callback(*static_cast(driver)); + #undef PROCESS_CONNSTR_OPTION @@ -1573,16 +1607,6 @@ void MySQL_Connection::init(ConnectOptionsMap & properties) } - /* - Note: If needed the setter will update callback functions registered with - webauthn/fido authentication plugins to call the callback stored - in the driver. It also protects the callbacks from being modified while - connection is being made. - */ - - MySQL_Driver::WebAuthn_Callback_Setter - setter{*static_cast(driver), proxy.get()}; - //Connect loop { bool connected = false; diff --git a/jdbc/driver/mysql_connection.h b/jdbc/driver/mysql_connection.h index 5d38fd45f..dd4aa23bf 100644 --- a/jdbc/driver/mysql_connection.h +++ b/jdbc/driver/mysql_connection.h @@ -73,6 +73,8 @@ class MySQL_Prepared_Statement; namespace NativeAPI { class NativeConnectionWrapper; +struct st_mysql_client_plugin; +extern std::map <::sql::SQLString, st_mysql_client_plugin*> plugins_cache; } class CPPCONN_PUBLIC_FUNC MySQL_Connection : public sql::Connection @@ -83,13 +85,15 @@ class CPPCONN_PUBLIC_FUNC MySQL_Connection : public sql::Connection MySQL_Statement * createServiceStmt(); public: - MySQL_Connection(Driver * _driver, - ::sql::mysql::NativeAPI::NativeConnectionWrapper & _proxy, + + using Proxy = ::sql::mysql::NativeAPI::NativeConnectionWrapper; + + MySQL_Connection(Driver * _driver, Proxy& _proxy, const sql::SQLString& hostName, const sql::SQLString& userName, const sql::SQLString& password); - MySQL_Connection(Driver * _driver, ::sql::mysql::NativeAPI::NativeConnectionWrapper & _proxy, + MySQL_Connection(Driver * _driver, Proxy & _proxy, std::map< sql::SQLString, sql::ConnectPropertyVal > & options); virtual ~MySQL_Connection(); @@ -193,7 +197,7 @@ class CPPCONN_PUBLIC_FUNC MySQL_Connection : public sql::Connection #pragma warning(push) #pragma warning(disable: 4251) #endif - std::shared_ptr< NativeAPI::NativeConnectionWrapper > proxy; + std::shared_ptr proxy; #ifdef _WIN32 #pragma warning(pop) #endif @@ -217,6 +221,57 @@ class CPPCONN_PUBLIC_FUNC MySQL_Connection : public sql::Connection /* Prevent use of these */ MySQL_Connection(const MySQL_Connection &); void operator=(MySQL_Connection &); + + struct PluginGuard; +}; + +class MySQL_Driver; + +/* + A PluginGuard instance is used to lock plugin options so that no other + connections can set them while the guard exists. + + It also manages the callback setting of the WebAuthN authentication + plugin -- see register_webauthn_callback() method. +*/ + +struct MySQL_Connection::PluginGuard +{ + std::weak_ptr prx; + + PluginGuard(MySQL_Connection *c); + ~PluginGuard(); + + /* + Depending on whether user has set the WebAuthN callback + for the driver or not, this method arranges for either + the driver's callback or the default callback be called + in case WebAuthN authentication is used while making + a connection. + */ + void register_webauthn_callback(MySQL_Driver &drv); + + private: + + /* + State of the WebAuthN plugin: + + NONE -- plugin is not loaded; + DEFAULT -- plugin is loaded and uses default callback; + CALLER -- plugin is loaded and its callback is set to + the `callback_caller()` function. + */ + static + enum class state { NONE, DEFAULT, CALLER } webauthn_plugin_state; + + // The driver whose callback is called by `callback_caller()` + static sql::mysql::MySQL_Driver * callback_drv; + + /* + Callback function to be registered with WebAuthN authentication plugin. + It calls the callback function of `callback_drv` if that is present. + */ + static void callback_caller(const char* msg); }; } /* namespace mysql */ diff --git a/jdbc/driver/mysql_driver.cpp b/jdbc/driver/mysql_driver.cpp index 1783b9111..b2c1b57fb 100644 --- a/jdbc/driver/mysql_driver.cpp +++ b/jdbc/driver/mysql_driver.cpp @@ -207,15 +207,15 @@ void MySQL_Driver::setCallBack(sql::WebAuthn_Callback& cb) /* - Note: Values 1 and 4 of `fido_callback` mean that user has set a WebAuthn + Note: Value 1 of `fido_callback` means that user has set a WebAuthn callback before and it can not be overwritten by Fido one. If later user - de-registers a WebAuthn callaback then `fido_callback` becomes 0 or 4 and + de-registers a WebAuthn callaback then `fido_callback` becomes 0 and error will not be thrown -- user can set a new Fido callback in this situation. */ #define CHECK_FIDO_ERROR \ - if (1 == (reinterpret_cast(fido_callback) % 3)) \ + if (1 == reinterpret_cast(fido_callback)) \ throw sql::SQLException{ \ "You are trying to overwrithe WebAuthn callback with FIDO one. " \ "FIDO authentication plugin and the corresponding callback type " \ diff --git a/jdbc/driver/mysql_driver.h b/jdbc/driver/mysql_driver.h index f764304fc..3e25db3ea 100644 --- a/jdbc/driver/mysql_driver.h +++ b/jdbc/driver/mysql_driver.h @@ -52,7 +52,6 @@ namespace NativeAPI class NativeDriverWrapper; } -//class sql::mysql::NativeAPI::NativeDriverWrapper; class CPPCONN_PUBLIC_FUNC MySQL_Driver : public sql::Driver { @@ -66,9 +65,10 @@ class CPPCONN_PUBLIC_FUNC MySQL_Driver : public sql::Driver #endif /* - Note: With current implementation `fido_callback` and `fido_callback_store` - are not really used and should be removed after deprecation of Fido - authentication plugin and when ABI can be changed. + Note: Currently we do not have a separate FIDO authentication plugin and + a callback for it. However, we keep `fido_callback` and + `fido_callback_store` members to not break ABI. The `fido_callback` is also + re-used as a flag in the logic of `setCallback()` methods (see there). */ ::sql::Fido_Callback* fido_callback = nullptr; @@ -77,9 +77,6 @@ class CPPCONN_PUBLIC_FUNC MySQL_Driver : public sql::Driver /* Callback function to be called by WebAuthn authentication plugin to notify the user. - - Note: The `fido_callback` pointer is re-used as a flag to indicate if - the callback was set by a user and its type (WebAuthn vs. Fido). */ std::function webauthn_callback; @@ -102,6 +99,20 @@ class CPPCONN_PUBLIC_FUNC MySQL_Driver : public sql::Driver const sql::SQLString & getName() override; + /* + We do not have a FIDO authentication plugin any more but for backward + compatibility user can still set a Fido_Callback and it will be used with + the WebAuthN plugin instead. + + New code should use only WebAuthn_Callback -- there is no need to use + the deprecated Fido_Callback other than in old code that was not yet aware + of WebAuthN authentication. + + An attempt to use both types of callbacks and overwrite earlier + WebAuthn_Callback with Fido_Callback will throw an error (it is still OK + to overwrite earlier Fido_Callback with WebAuthn_Callback though). + */ + void setCallBack(sql::Fido_Callback &cb) override; void setCallBack(sql::Fido_Callback &&cb) override; diff --git a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp index 2e5e73e40..b513a8127 100644 --- a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp +++ b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp @@ -34,6 +34,7 @@ #include #include +#include #include "../mysql_util.h" #include "../mysql_connection_options.h" @@ -52,6 +53,9 @@ namespace mysql namespace NativeAPI { +std::shared_mutex plugins_cache_mutex; +std::map <::sql::SQLString, st_mysql_client_plugin*> plugins_cache; + /* Function to convert sql::mysql::MySQL_Connection_Options to libmysqlclient mysql_option @@ -452,6 +456,111 @@ MySQL_NativeConnectionWrapper::get_option(::sql::mysql::MySQL_Connection_Options } /* }}} */ + +/* + Accessing plugin options. +*/ + +void MySQL_NativeConnectionWrapper::lock_plugin_impl(lock_type type) +{ + switch (type) + { + case lock_type::GUARD: + case lock_type::SHARED: + // Note: We don't take shared lock if exclusive lock is in place + if (!plugins_ex_lock.owns_lock() && !plugins_sh_lock.owns_lock()) + plugins_sh_lock.lock(); + + if (!plugin_guard) + plugin_guard = (lock_type::GUARD == type); + break; + + case lock_type::EXCLUSIVE: + // Nothing to do if we already hold an exclusive lock + if (plugins_ex_lock.owns_lock()) + break; + // Before taking exclusive lock we need to release the shared lock + if (plugins_sh_lock.owns_lock()) + plugins_sh_lock.unlock(); + // This will wait until no other connection holds a lock + plugins_ex_lock.lock(); + break; + + case lock_type::UNLOCK: + // UNLOCK has no effect if GUARD lock was taken + if (plugin_guard) + break; + // Otherwise UNLOCK and UNGUARD are the same + // FALLTHROUGH + case lock_type::UNGUARD: + if (plugins_sh_lock.owns_lock()) + plugins_sh_lock.unlock(); + if (plugins_ex_lock.owns_lock()) + plugins_ex_lock.unlock(); + break; + } +} + +struct MySQL_NativeConnectionWrapper::PluginGuard +{ + using ConWrapper = MySQL_NativeConnectionWrapper; + + ConWrapper *conn; + + PluginGuard(ConWrapper *c) + : conn{c} + { + conn->lock_plugin_impl(lock_type::SHARED); + } + + ~PluginGuard() + { + // Note: This will do nothing if external guard was created + conn->lock_plugin_impl(lock_type::UNLOCK); + } + + // Upgrade initial shared lock to exclusive one + + void lock() + { + conn->lock_plugin_impl(lock_type::EXCLUSIVE); + } + + /* + Find a plugin in the plugin cache. If `load` is true then loads the plugin + into cache if not already there; otherwise null is returned if the plugin + was not found. + + Throws error if loading of the plugin failed. + */ + + st_mysql_client_plugin* + get_plugin(int plugin_type, SQLString const &name, bool load) + { + /* + Note: Shared plugin lock is held when this method is called (taken in + the constructor). + */ + + if (plugins_cache.count(name) > 0) + return plugins_cache.at(name); + else if (load) + { + /* load client authentication plugin if required */ + auto *plugin = conn->api->client_find_plugin(conn->mysql, name.c_str(), plugin_type); + + lock(); // Upgrade to exclusive lock before writing to cache + + plugins_cache.emplace(name, plugin); + + return plugin; + } + else + return nullptr; + } +}; + + int MySQL_NativeConnectionWrapper::plugin_option( int plugin_type, @@ -459,14 +568,27 @@ MySQL_NativeConnectionWrapper::plugin_option( const ::sql::SQLString & option, const void * value) try{ + PluginGuard guard{this}; + /* + Note: Try to load plugin into cache only if the option has non-default + value. + */ + + struct st_mysql_client_plugin *plugin + = guard.get_plugin(plugin_type, plugin_name, value != nullptr); + + /* + Note: `plugin` can be null here only if we are setting option to + the default value and the plugin was not found in the cache. Otherwise + an attempt to load the plugin will be made and error will be thrown if + it could not be done. + */ + + if (!plugin) + return 0; - /* load client authentication plugin if required */ - struct st_mysql_client_plugin *plugin = - api->client_find_plugin(mysql, plugin_name.c_str(), plugin_type); - - /* set option value in plugin */ + guard.lock(); // Note: Only now an exclusive lock is required return api->plugin_options(plugin, option.c_str(), value); - } catch(sql::InvalidArgumentException &e) { @@ -481,35 +603,21 @@ MySQL_NativeConnectionWrapper::plugin_option( const ::sql::SQLString & plugin_name, const ::sql::SQLString & option, const ::sql::SQLString & value) -try{ - - /* load client authentication plugin if required */ - struct st_mysql_client_plugin *plugin = - api->client_find_plugin(mysql, plugin_name.c_str(), plugin_type); - - /* set option value in plugin */ - return api->plugin_options(plugin, option.c_str(), value.c_str()); - -} -catch(sql::InvalidArgumentException &e) { - std::string err(e.what()); - err+= " for plugin " + plugin_name; - throw sql::InvalidArgumentException(err); + return plugin_option(plugin_type, plugin_name, option, value.c_str()); } + int MySQL_NativeConnectionWrapper::get_plugin_option( int plugin_type, const ::sql::SQLString & plugin_name, const ::sql::SQLString & option, const ::sql::SQLString & value) { - + PluginGuard guard{this}; /* load client authentication plugin if required */ - struct st_mysql_client_plugin *plugin = - api->client_find_plugin(mysql, plugin_name.c_str(), - plugin_type); + struct st_mysql_client_plugin *plugin = guard.get_plugin(plugin_type, plugin_name, true); /* get option value from plugin */ return api->plugin_get_option(plugin, option.c_str(), (void*)value.c_str()); diff --git a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h index 865302ae1..fbc3e272d 100644 --- a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h +++ b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h @@ -37,7 +37,8 @@ #include #include - +#include +#include namespace sql { @@ -53,12 +54,12 @@ inline const char * nullIfEmpty(const ::sql::SQLString & str) return str.length() > 0 ? str.c_str() : NULL; } +extern std::shared_mutex plugins_cache_mutex; class MySQL_NativeConnectionWrapper : public NativeConnectionWrapper { /* api should be declared before mysql here */ std::shared_ptr api; - bool reconnect = false; ::sql::SQLString m_host; ::sql::SQLString m_user; @@ -176,6 +177,65 @@ struct st_mysql* mysql; NativeStatementWrapper &stmt_init() override; unsigned int warning_count() override; + + void lock_plugin(bool lock_or_unlock) override + { + lock_plugin_impl(lock_or_unlock ? lock_type::GUARD : lock_type::UNGUARD); + } + + void lock_plugin_exclusive() override + { + lock_plugin_impl(lock_type::EXCLUSIVE); + } + + /* + Implementation of plugin locking. + + There are the following lock request that can be made with + lock_plugin_impl() method: + + - SHARED lock can be taken if there are no EXCLUSIVE locks present (when + requested it watis until this is the case), existence of other SHARED + (or GUARD) locks does not prevent SHARED lock to be taken; + + - GUARD lock is like a SHARED lock but it prevents locks to be released + by UNLOCK request (see below). + + - EXCLUSIVE lock can be taken only when no other connection holds any type + of lock (when requested it waits until this is the case). EXCLUSIVE lock + can be requested while holding SHARED or GUARD lock. + + The UNLOCK request is used to remove SHARED or EXCLUSIVE locks provided + that no GUARD lock was taken. If GUARD lock was taken then an UNLOCK + request has no effect -- any locks taken remain in place. Only UNGUARD + request can be used to remove locks after GUARD request -- either + the original GUARD lock or an EXCLUSIVE lock to which it was upgraded. + + If connection already holds a plugin lock then another request to get + a lock has the following effect depending on the requested lock type: + + - EXCLUSIVE - upgrade shared lock to exclusive one + - GUARD - keep existing locks until UNGUARD request is made + - SHARED - no effect + */ + + enum class lock_type {GUARD, SHARED, EXCLUSIVE, UNLOCK, UNGUARD}; + + void lock_plugin_impl(lock_type); + + // These are used by lock_plugin_impl() + + std::shared_lock plugins_sh_lock{plugins_cache_mutex, std::defer_lock}; + std::unique_lock plugins_ex_lock{plugins_cache_mutex, std::defer_lock}; + bool plugin_guard = false; + + /* + This class handles locking of plugin when plugin options are set + (in plugin_option() methods) as well as implements access to the plugin + cache. + */ + + struct PluginGuard; }; } /* namespace NativeAPI */ diff --git a/jdbc/driver/nativeapi/native_connection_wrapper.h b/jdbc/driver/nativeapi/native_connection_wrapper.h index e1d517265..247572c49 100644 --- a/jdbc/driver/nativeapi/native_connection_wrapper.h +++ b/jdbc/driver/nativeapi/native_connection_wrapper.h @@ -69,6 +69,7 @@ enum Protocol_Type PROTOCOL_COUNT }; + class NativeConnectionWrapper : public util::nocopy { public: @@ -180,6 +181,43 @@ class NativeConnectionWrapper : public util::nocopy virtual unsigned int warning_count() = 0; + /* + This method is used to lock plugin options. + + After lock_plugin(true) call other connections that try to set plugin + options using plugin_option() methods will wait until lock_plugin(false) + is called on this connection. + */ + + virtual void lock_plugin(bool) = 0; + + /* + This method is used to lock plugin options exclusively before making any + plugin_option() call. + + Normally a thread takes an exclusive lock on plugin options only when it + calls `plugin_option()` method to modify one. This might however lead to + a race condition in a situation like this: + + lock_plugin(true); // lock plugin options + val = get_plugin_option(...); // read some option <1> + plugin_option(...); // write other option <2> + + If in <2> we want to set option X based on the value `val` of another + option Y that was read in step <1> there is no guarantee that at the time + of setting option X option Y has still the same value `val` that we saw + before. This is because while plugin_option() waits for exclusive access + to the options another thread can get that exclusive access first and + modify the value of Y. To avoid such race condition the code should grab + an exclusive lock on plugin options up-front rather than during + `plugin_option()` call: + + lock_plugin_exclusive(); + val = get_plugin_option(...); + plugin_option(...); + */ + + virtual void lock_plugin_exclusive() = 0; }; } /* namespace NativeAPI */ diff --git a/jdbc/test/unit/classes/connection.cpp b/jdbc/test/unit/classes/connection.cpp index f42ad2017..9b00b58f1 100644 --- a/jdbc/test/unit/classes/connection.cpp +++ b/jdbc/test/unit/classes/connection.cpp @@ -3986,8 +3986,18 @@ void connection::tls_deprecation() 4. Set env variable MYSQL_WEBAUTHN to non-empty value */ -/* Variable value will be changed by callbacks */ -int callback_variable = -1; +/* + Variable value will be changed by callbacks. + We want to use thread local variable to avoid theoretical race condition + when after a connection is made and before the check is done another + thread might modify the variable value. + + The aim of the test is to make sure the correct callback is called inside + each thread. If the wrong callback is called the local thread variable + will have unexpected value. Hence we can detect if the driver incorrectly + handles setting of callbacks. +*/ +thread_local int callback_variable = -1; void my_callback(sql::SQLString s) { @@ -4040,9 +4050,14 @@ void connection::test_fido_webauthn(sql::ConnectOptionsMap &opt, bool callback_i auto test_connection_drv = [&opt](int expected, sql::Driver *drv) { callback_variable = 0; - cout << "Before connect: " << callback_variable << endl; - Connection fido_connection(drv->connect(opt)); - cout << "After connect: " << callback_variable << endl; + cout << "Before connect: " << callback_variable << + " Expected: " << expected << + " DRIVER=" << drv << " THREAD=" << std::this_thread::get_id() << endl; + auto cn = drv->connect(opt); + Connection fido_connection(cn); + cout << "After connect: " << callback_variable << + " Expected: " << expected << + " DRIVER=" << drv << " THREAD=" << std::this_thread::get_id() << endl; ASSERT_EQUALS(expected, callback_variable); }; @@ -4053,7 +4068,6 @@ void connection::test_fido_webauthn(sql::ConnectOptionsMap &opt, bool callback_i try { - cout << endl << "Default callback (0)" << endl; test_connection(0); @@ -4086,46 +4100,66 @@ void connection::test_fido_webauthn(sql::ConnectOptionsMap &opt, bool callback_i cout << endl << "Multi driver tests: " << endl; - auto multi_drv_test = [test_connection_drv]() + /* + The driver instances should be created before they are + used inside the multi-thread test. + */ + sql::Driver *driver1 = sql::mysql::get_driver_instance_by_name("drv1"); + sql::Driver *driver2 = sql::mysql::get_driver_instance_by_name("drv2"); + + auto multi_drv_test = [test_connection_drv, driver1, driver2]() { - sql::Driver * driver1 = sql::mysql::get_driver_instance_by_name("drv1"); - driver1->setCallBack(CB{[](sql::SQLString msg) { - cout << "Driver 1 Callback : " << msg << endl; + driver1->setCallBack(CB{[driver1](sql::SQLString msg) { + cout << "Driver 1 Callback : " << msg << " DRIVER=" << + driver1 << " THREAD=" << std::this_thread::get_id() << endl; callback_variable = 111; }}); - sql::Driver * driver2 = sql::mysql::get_driver_instance_by_name("drv2"); - driver2->setCallBack(CB{[](sql::SQLString msg) { - cout << "Driver 2 Callback : " << msg << endl; + driver2->setCallBack(CB{[driver2](sql::SQLString msg) { + cout << "Driver 2 Callback : " << msg << " DRIVER=" << + driver2 << " THREAD=" << std::this_thread::get_id() << endl; callback_variable = 222; }}); test_connection_drv(111, driver1); test_connection_drv(222, driver2); - // Multi-driver callbacks have to be reset too. - // Otherwise they will remain set in the next test. - driver1->setCallBack(CB{nullptr}); - driver2->setCallBack(CB{nullptr}); }; multi_drv_test(); + /* + Multi-driver callbacks have to be reset too. + Otherwise they will remain set in the next test. + */ + + driver1->setCallBack(CB{nullptr}); + driver2->setCallBack(CB{nullptr}); + cout << endl << "Multithread driver tests: " << endl; { std::vector workers; - for (int i = 0; i < 3; ++i) - { + for (int i = 0; i < 3; ++i) { workers.push_back(std::thread{multi_drv_test}); } - for (auto &w : workers) - { + for (auto &w : workers) { w.join(); } } + + /* + Multi-driver callbacks have to be reset after all threads finish. + Otherwise, resetting a callback for a driver after one thread + is finished, but another one is still running will result in + premature disabling of the callbacks. + */ + + driver1->setCallBack(CB{nullptr}); + driver2->setCallBack(CB{nullptr}); + } catch (sql::SQLException &e) { @@ -4387,7 +4421,7 @@ void connection::openid_token() sql::ConnectOptionsMap opts = map; opts[OPT_USERNAME] = "MySQLUser"; opts["hostName"] = url; - + if (getenv("PLUGIN_DIR")) opts[OPT_PLUGIN_DIR] = getenv("PLUGIN_DIR"); From d4cb9ff1dbf3e39d69808f0322ef3c760d6962d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 2 Dec 2024 09:42:35 +0100 Subject: [PATCH 11/43] jdbc: Add pthread dependency --- jdbc/driver/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jdbc/driver/CMakeLists.txt b/jdbc/driver/CMakeLists.txt index 271077073..f9ffa2cc3 100755 --- a/jdbc/driver/CMakeLists.txt +++ b/jdbc/driver/CMakeLists.txt @@ -204,8 +204,11 @@ add_library(jdbc STATIC ${MYSQLCPPCONN_SOURCES}) IF(WIN32) target_link_libraries(jdbc PRIVATE Dnsapi) -ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - target_link_libraries(jdbc PRIVATE resolv) +ELSE() + target_link_libraries(jdbc PRIVATE pthread) + IF(NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + target_link_libraries(jdbc PRIVATE resolv) + ENDIF() ENDIF() if (MYSQLCLIENT_STATIC_BINDING) From f22c43623ea5aec151c3c5fe70997aaf7c75ea98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 2 Dec 2024 13:27:35 +0100 Subject: [PATCH 12/43] jdbc/test: Better detection whether stdc++fs is required --- jdbc/test/CMakeLists.txt | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/jdbc/test/CMakeLists.txt b/jdbc/test/CMakeLists.txt index 50e9b2b14..a35b906fc 100644 --- a/jdbc/test/CMakeLists.txt +++ b/jdbc/test/CMakeLists.txt @@ -44,13 +44,26 @@ INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/include/jdbc/cppconn") set(MY_TARGET_LINK_LIBRARIES connector-jdbc) -if(DEFINED GCC AND GCC VERSION_LESS 9) +# Note: Some unit tests use std::filesystem part of the standard C++ library +# and for some versions of the standard library its implementation is in +# additional library stdc++fs. - # Note: Some unit tests use std::filesystem part of the standard library - # Before version 9 of gcc that requires linking with the additional library +if(NOT WIN32) - list(APPEND MY_TARGET_LINK_LIBRARIES -lstdc++fs) - # message(STATUS "Added libstdc++fs for GCC version ${GCC}: ${MY_TARGET_LINK_LIBRARIES}") + set(check_src "${CMAKE_CURRENT_BINARY_DIR}/filesystem_chk.cc") + file(WRITE "${check_src}" + "#include \n" + "int main() { (void)std::filesystem::current_path(); }" + ) + + try_compile(COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR} "${check_src}" + # OUTPUT_VARIABLE build_log + ) + + if(NOT COMPILE_RESULT) + list(APPEND MY_TARGET_LINK_LIBRARIES -lstdc++fs) + endif() endif() From c28f4251cbea6e9b9b65e3046ab5c83038613aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Thu, 5 Dec 2024 12:26:52 +0100 Subject: [PATCH 13/43] testapp: Fix location of OpenSSL libraries if WITH_SSL option is given --- testapp/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testapp/CMakeLists.txt b/testapp/CMakeLists.txt index 6eb221018..ef6f691cd 100644 --- a/testapp/CMakeLists.txt +++ b/testapp/CMakeLists.txt @@ -66,7 +66,8 @@ if(WITH_SSL) message(STATUS "Using custom OpenSSL libraries at: ${WITH_SSL}") add_library(openssl INTERFACE) - target_link_directories(openssl INTERFACE "${WITH_SSL}") + # TODO: Is this path correct also on non-Win platforms? + target_link_directories(openssl INTERFACE "${WITH_SSL}/lib") if(WIN32) set(ssl_libs libssl libcrypto) From 697d3c667f57b98d1633a7bcf5ec5b7f917dd7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 13 May 2024 15:27:23 +0200 Subject: [PATCH 14/43] WL#16321: Let CMake configuration script handle debug-only installs Change-Id: Ib34939d538c00240deb976d3079f0fe91c6ee30f --- mysql-concpp-config.cmake.in | 612 ++++++++++++++++++++++++++--------- 1 file changed, 454 insertions(+), 158 deletions(-) diff --git a/mysql-concpp-config.cmake.in b/mysql-concpp-config.cmake.in index d8e12d673..6592d2014 100644 --- a/mysql-concpp-config.cmake.in +++ b/mysql-concpp-config.cmake.in @@ -47,15 +47,18 @@ # # - Xxx_FOUND # - Xxx_DEBUG_FOUND, Xxx_debug_FOUND -- (1) +# - Xxx_RELEASE_FOUND, Xxx_release_FOUND -- (1) # - Xxx_VERSION, Xxx_VERSION_CC # - Xxx_ROOT_DIR -- (2) # - Xxx_RUNTIME_LIBRARY_DIRS, Xxx_RUNTIME_LIBRARY_DIR -- (2,3) -# - Xxx_PLUGIN_DIR -- (4) +# - Xxx_RUNTIME_LIBRARY_DIRS_DEBUG, Xxx_RUNTIME_LIBRARY_DIR_DEBUG -- (4a) +# - Xxx_RUNTIME_LIBRARY_DIRS_RELEASE, Xxx_RUNTIME_LIBRARY_DIR_RELEASE -- (4b) +# - Xxx_PLUGIN_DIR -- (5a,5b) # # In these variable names Xxx is either `MYSQL_CONCPP` or `mysql-concpp`, # CC is version component: one of `MAJOR`, `MINOR` or `PATCH`. # -# Note (1): These are set to true if debug libraries are available +# Note (1): These are set to true if debug/release libraries are available # (see below). # # Note (2): Set only in case of a monolithic install (TGZ, ZIP, MSI). @@ -67,13 +70,28 @@ # case the _RUNTIME_LIBRARY_DIR(S) variable gives the location where shared # connector libraries can be found. # -# Note (4): The JDBC connector might require loading of authentication plugins -# at connection time (depending on authentication mechaism being used). These +# Note (4a): If debug variants of connector libraries were found these +# variables are set to their location. +# +# Note (4b): For consistency, these variables are set if release variants +# of connector libraries were found and in that case they are equal +# to _RUNTIME_LIBRARY_DIR(S) ones. +# +# Note (5a): The JDBC connector might require loading of authentication plugins +# at connection time (depending on authentication mechanism being used). These # plugins are in the location given by _PLUGIN_DIR variable. Depending on # the installation type it might be necessary to specify this location # with connection configuration options for plugins to be correctly found # at runtime (see: https://dev.mysql.com/doc/connector-cpp/8.2/en/connector-cpp-authentication.html) # +# Note (5b): Authentication plugins are bundled with the connector and +# the _PLUGIN_DIR variable is set only when the JDBC connector links the MySQL +# client library statically (which is the typical case). It is also possible +# to build JDBC connector with dynamic linking to the MySQL client library. +# In that case plugins are not bundled with the connector and _PLUGIN_DIR +# variable is not set -- if needed the plugins that come with the MySQL client +# library should be used in that case. +# # Note: The variables are put in the cache but if Xxx_FOUND is not set or # is false then the module will be re-loaded and the other variables in # the cache will be overwritten with newly detected values. @@ -81,14 +99,15 @@ # Note: If mysql-concpp_FIND_VERBOSE is true when loading package diagnostic # messages will be printed by this script. # +# # OpenSSL dependency # ------------------ # -# Connector/C++ requires OpenSSL libraires. Depending on the platform and +# Connector/C++ requires OpenSSL libraries. Depending on the platform and # the installation type it is either expected that OpenSSL will be installed # on the system or these libraries are bundled in the connector package. # Connector library targets are configured to use OpenSSL from appropriate -# locations. This can be overriden by user -- if `mysql::openssl` target +# locations. This can be overridden by user -- if `mysql::openssl` target # is defined prior to loading `mysql-concpp` package then this target is used # to resolve dependency on the OpenSSL library. # @@ -119,11 +138,26 @@ # clause of `find_package()` command. If this is done then `find_package()` # will fail if debug libraries were not found. # +# When using custom builds of Connector/C++ it is possible to have +# an installation with only debug libraries. On Windows, in such situation, +# the connector targets created here will work only for debug builds. +# On non-Windows platforms debug libraries can and will be used for building +# in any mode. Presence of release libraries is indicated by _RELEASE_FOUND +# variable. One can use `REQUIRE release` clause of `find_package()` command +# to ensure that release variants of the libraries are present. +# # Note: Debug libraries are needed and used only on Windows. For Linux # separate packages with debug symbols are available that can be used -# to debug connector libraries but only release builds of these libararies +# to debug connector libraries but only release builds of these libraries # are distributed. # +# Note: When only debug libraries are available the _RUNTIME_LIBRARY_DIR(S) +# variables point at the location of these debug libraries on non-Windows +# platforms (because they are used by other build types). However, on Windows +# the _RUNTIME_LIBRARY_DIR(S) variables still point to the location where +# release variants of the libraries should be installed (but are not present). +# The libraries can be located using _RUNTIME_LIBRARY_DIR(S)_DEBUG variables +# in such scenario. # message(STATUS "mysql-concpp module config (${MYSQL_CONCPP_FOUND}, ${mysql-concpp_FOUND})") @@ -138,72 +172,65 @@ function(message_info) message(STATUS "mysql-concpp: " ${ARGV}) endfunction() +function(set_warning) + set(warning_message ${ARGV} CACHE INTERNAL "warning message") +endfunction() + # -# If WITH_MYSQL is not false then it is assumed that the `concpp-jdbc-static` -# target depends on the MySQL client library. Additionally, if WITH_MYSQL is a -# path pointing at MySQL install location, the library path will be extended so -# that linker looks for the client library at that location. -# -# Note: The default value is set based on whether the JDBC connector was -# statically linked with the client library or not. +# JDBC_MYSQL_DEP tells whether JDBC connector library depends on the MySQL +# client library. This is not the case when the connector library links +# the client library statically. However, if WITH_MYSQL option is defined +# and not false then JDBC targets are always configured to depend on the client +# library. Additionally, if WITH_MYSQL is a path pointing at MySQL install +# location, the library path will be extended so that linker looks for the +# client library at that location. # -if(NOT @MYSQLCLIENT_STATIC_LINKING@) +set(JDBC_MYSQL_DEP OFF) +if(WITH_MYSQL OR NOT @MYSQLCLIENT_STATIC_LINKING@) set(JDBC_MYSQL_DEP ON) -else() - set(JDBC_MYSQL_DEP OFF) -endif() - -# Note: This script is executed as part of find_package() invocation. If -# the invoking project sets WITH_MYSQL variable we want its value to be used -# here as it should point at the actual install location. However, for some -# reason set(WITH_MYSQL ... CACHE ...) overwrites cache entry with the same -# name from the invoking project (probably a result of running it from inside -# find_package()). To avoid override we define cache entry only if the variable -# is not already set. - -if(NOT DEFINED WITH_MYSQL) - set(WITH_MYSQL ${JDBC_MYSQL_DEP} - CACHE INTERNAL - "MySQL install location (to find the client library)" - ) endif() macro(main) - # Set paths to look for headers and libraries either relative to this file - # or in system-wide locations. - # - # FIXME: lib64/ or lib/ as appropriate for the platform - + # We can have two types of installations -- in case of RPM/DEB install + # connector files are installed to system-wide locations (system-wide + # install), in other cases all connector files are installed into a single + # root directory (monolithic install). if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/include/mysqlx/xdevapi.h") # Case of monolithic install + set(monolithic 1) + set(MYSQL_CONCPP_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}") - set(LIB_PATH "${MYSQL_CONCPP_ROOT_DIR}/@INSTALL_LIB_DIR@") message_info("Module installed at: ${MYSQL_CONCPP_ROOT_DIR}") - set(INCLUDE_PATH "${MYSQL_CONCPP_ROOT_DIR}/include") + + set(INCLUDE_DIR "${MYSQL_CONCPP_ROOT_DIR}/include") + set(LIBRARY_DIR "${MYSQL_CONCPP_ROOT_DIR}/@INSTALL_LIB_DIR@") + + set(fail_message "Could NOT find MySQL Connector/C++ libraries at ${MYSQL_CONCPP_ROOT_DIR}.") else() # System-wide install, DEB or RPM layout. - set(INCLUDE_PATH "/usr/include/mysql-cppconn") - get_filename_component(LIB_PATH "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) + set(monolithic 0) - file(GLOB found "${LIB_PATH}/*libmysqlcppconn*") + set(INCLUDE_DIR "/usr/include/mysql-cppconn") - if(NOT found) - # Note: Use RPM layout as fallback - set(LIB_PATH "/usr/@INSTALL_LIB_DIR@") - endif() + # We do not set LIBRARY_DIR because in this case we will search for the libraries in system-wide locations. + + set(fail_message + "Could NOT find MySQL Connector/C++ libraries at system-wide locations." + ) endif() + # Headers must always be found first. find_includes() @@ -218,25 +245,109 @@ macro(main) message_info("Include path: ${MYSQL_CONCPP_INCLUDE_DIR}") - # Note: On windows we look for the import library, not the DLL. This import - # library normally is in a ./vsNN subfolder of the library path. + # This suffix is used to locate static and import libraries on Windows - unset(vs_suffix) + set(vs_suffix) if(WIN32) set(vs_suffix vs14) endif() - # Find required dependencies. Currtently this looks for OpenSSL and defines + # Find required dependencies. Currently this looks for OpenSSL and defines # `mysql::openssl` interface library for it if found. find_deps() # Find connector libraries and define interface targets for the ones that - # were found. + # were found. This will set/update LIBRARY_DIR to the location where + # libraries were found and will also set RELEASE/DEBUG_FOUND flags + # if the corresponding variant of the libraries was found. + + set(DEBUG_FOUND 0) + set(RELEASE_FOUND 0) find_connector(XDevAPI) find_connector(JDBC) + + set(MYSQL_CONCPP_DEBUG_FOUND ${DEBUG_FOUND}) + set(MYSQL_CONCPP_RELEASE_FOUND ${RELEASE_FOUND}) + + if(monolithic) + + # Set MYSQL_CONCPP_RUNTIME_LIBRARY_DIR_*. Variables based on LIBRARY_DIR + # determined above. + + if(DEBUG_FOUND) + + set(MYSQL_CONCPP_RUNTIME_LIBRARY_DIR_DEBUG "${LIBRARY_DIR}/debug") + + elseif(WIN32) + + set_warning( + "Debug variants of connector libraries were not found" + "at the install location -- building in debug mode will not work" + ) + + endif() + + + if(RELEASE_FOUND) + + set(MYSQL_CONCPP_RUNTIME_LIBRARY_DIR_RELEASE "${LIBRARY_DIR}") + set(MYSQL_CONCPP_RUNTIME_LIBRARY_DIR "${LIBRARY_DIR}") + + elseif(NOT WIN32) + + # If release libraries were not found and we are on non-Win platform we + # will use debug libraries also for release builds. + + message_info( + "Using debug variants of connector libraries for release builds because" + " release variants are not found at the install location" + ) + + set( + MYSQL_CONCPP_RUNTIME_LIBRARY_DIR + "${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR_DEBUG}" + ) + + else() + + # On Windows one can not mix release and debug code. The targets created + # above have only debug-mode paths defined. We set + # MYSQL_CONCPP_RUNTIME_LIBRARY_DIR to the path where release libraries + # would be expected even if they were not found there. + + set_warning( + "Release variants of connector libraries were not found" + "at the install location -- building in release mode will not work" + ) + + set(MYSQL_CONCPP_RUNTIME_LIBRARY_DIR "${LIBRARY_DIR}") + + endif() + + # Note: Set plugin dir location only if connector has client library + # statically linked in (does not depend on external one). + + if(NOT JDBC_MYSQL_DEP) + set(MYSQL_CONCPP_PLUGIN_DIR "${LIBRARY_DIR}/plugin") + endif() + + else() + + # Note: In system-wide install case we do not set _RUNTIME_LIBRARY_DIR_* + # variables as libraries are installed at system-wide locations. + + if(NOT JDBC_MYSQL_DEP) + set(MYSQL_CONCPP_PLUGIN_DIR + "${LIBRARY_DIR}/mysql/libmysqlcppconn@JDBC_ABI_VERSION_MAJOR@/plugin" + ) + endif() + + endif() + + # Aliases for -xdevapi* targets. foreach(suffix "" "-static" "-debug" "-static-debug") @@ -253,8 +364,6 @@ macro(main) # Note: The different find_xxx() functions set the specific part # of the message, such as ${fail_message_devapi}, in case of failure. - set(fail_message "Could NOT find MySQL Connector/C++ at ${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}.") - if(fail_message_devapi) # AND MYSQL_CONCPP_FIND_REQUIRED_devapi) list(APPEND fail_message ${fail_message_devapi}) elseif(fail_message_jdbc) # AND MYSQL_CONCPP_FIND_REQUIRED_jdbc) @@ -263,37 +372,70 @@ macro(main) set_not_found(${fail_message}) + # Build the success message which can optionally contain warnings + # TODO: Warnings about missing debug/release library variants + + set(MYSQL_CONCPP_FOUND_MSG ${MYSQL_CONCPP_INCLUDE_DIR}) + if(warning_message) + string(JOIN " " warning_message ${warning_message}) + set(MYSQL_CONCPP_FOUND_MSG + "${MYSQL_CONCPP_FOUND_MSG} WARNING: ${warning_message}" + ) + endif() + include(FindPackageHandleStandardArgs) + # Note: The _FOUND variable name expected by FPHSA for component CCC + # is mysql-concpp_CCC_FOUND + + set(mysql-concpp_debug_FOUND ${MYSQL_CONCPP_DEBUG_FOUND}) + set(mysql-concpp_release_FOUND ${MYSQL_CONCPP_RELEASE_FOUND}) + find_package_handle_standard_args(mysql-concpp REQUIRED_VARS - mysql-concpp_VERSION - MYSQL_CONCPP_FOUND + MYSQL_CONCPP_FOUND_MSG MYSQL_CONCPP_INCLUDE_DIR + MYSQL_CONCPP_FOUND VERSION_VAR mysql-concpp_VERSION - # HANDLE_COMPONENTS + HANDLE_COMPONENTS FAIL_MESSAGE "${mysql-concpp_NOT_FOUND_MESSAGE}" ) # Set alternative variables + set(MYSQL_CONCPP_debug_FOUND ${MYSQL_CONCPP_DEBUG_FOUND}) + set(MYSQL_CONCPP_release_FOUND ${MYSQL_CONCPP_RELEASE_FOUND}) + foreach(var - ROOT_DIR PLUGIN_DIR RUNTIME_LIBRARY_DIR RUNTIME_LIBRARY_DIRS DEBUG_FOUND + ROOT_DIR PLUGIN_DIR + RUNTIME_LIBRARY_DIR RUNTIME_LIBRARY_DIRS + RUNTIME_LIBRARY_DIR_DEBUG RUNTIME_LIBRARY_DIRS_DEBUG + RUNTIME_LIBRARY_DIR_RELEASE RUNTIME_LIBRARY_DIRS_RELEASE + DEBUG_FOUND debug_FOUND RELEASE_FOUND release_FOUND ) if(NOT DEFINED MYSQL_CONCPP_${var}) continue() endif() - set(mysql-concpp_${var} ${MYSQL_CONCPP_${var}} CACHE INTERNAL "mysql-concpp module config variable" FORCE) - set(MYSQL_CONCPP_${var} ${MYSQL_CONCPP_${var}} CACHE INTERNAL "mysql-concpp module config variable" FORCE) + # handle _DIR_ and _DIRS_ variants if(var STREQUAL "RUNTIME_LIBRARY_DIR") - set(MYSQL_CONCPP_RUNTIME_LIBRARY_DIRS - "${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}" - ) + foreach(suffix "" "_RELEASE" "_DEBUG") + if(NOT DEFINED MYSQL_CONCPP_RUNTIME_LIBRARY_DIR${suffix}) + continue() + endif() + set( + MYSQL_CONCPP_RUNTIME_LIBRARY_DIRS${suffix} + "${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR${suffix}}" + ) + endforeach() endif() + set(mysql-concpp_${var} ${MYSQL_CONCPP_${var}} CACHE INTERNAL "mysql-concpp module config variable" FORCE) + set(MYSQL_CONCPP_${var} ${MYSQL_CONCPP_${var}} CACHE INTERNAL "mysql-concpp module config variable" FORCE) + + endforeach(var) foreach(ver "" _MAJOR _MINOR _PATCH _TWEAK _COUNT) @@ -323,11 +465,11 @@ endfunction() function(find_includes) - #message(STATUS "Looking for headers at: ${INCLUDE_PATH}") + #message(STATUS "Looking for headers at: ${INCLUDE_DIR}") find_path(MYSQL_CONCPP_INCLUDE_DIR NAMES mysqlx/xdevapi.h - PATHS ${INCLUDE_PATH} + PATHS ${INCLUDE_DIR} NO_DEFAULT_PATH NO_CACHE ) @@ -336,10 +478,10 @@ function(find_includes) if(MYSQL_CONCPP_ROOT_DIR) set(fail_message_includes - "at MYSQL_CONCPP_ROOT_DIR: ${INCLUDE_PATH}" + "at MYSQL_CONCPP_ROOT_DIR: ${INCLUDE_DIR}" ) else() - set(fail_message_includes "at ${INCLUDE_PATH}") + set(fail_message_includes "at ${INCLUDE_DIR}") endif() set_parent(fail_message_includes) @@ -354,47 +496,31 @@ endfunction() # Find XDevAPI or JDBC connector libraries, as specified by parameter `which` # and create interface library targets for them. Both shared and static -# variants are searched for. +# variants are searched for. If some libraries are not found the corresponding +# targets are not created. +# +# If LIBRARY_DIR is set the libraries are searched in that location, otherwise +# they are searched in system-wide locations. In either case LIBRARY_DIR is +# set/updated to the location where libraries were found. # -# TODO: Currently this will fail if release libraries are not found, even -# if debug ones are present. Should this be changed? +# Flags RELEASE_FOUND and DEBUG_FOUND are set if the corresponding variants +# of the libraries were found. function(find_connector which) if(which STREQUAL "JDBC") set(base_name "mysqlcppconn") - set(target_name "concpp-jdbc") + set(target_name "jdbc") else() set(base_name "mysqlcppconnx") - set(target_name "concpp-xdevapi") + set(target_name "xdevapi") endif() - # Set location of shared libraries or DLLs in case of Win (if not already - # done). - - if(NOT MYSQL_CONCPP_RUNTIME_LIBRARY_DIR) - - set(MYSQL_CONCPP_RUNTIME_LIBRARY_DIR "${LIB_PATH}") - - # Note: set MYSQL_CONCPP_RUNTIME_LIBRARY_DIR as output variable only - # in case of monolithic install. - - if(MYSQL_CONCPP_ROOT_DIR) - - message_info( - "Runtime library folder: ${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}" - ) - set_parent(MYSQL_CONCPP_RUNTIME_LIBRARY_DIR) - - endif() - - set( - MYSQL_CONCPP_PLUGIN_DIR "${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}/plugin" - PARENT_SCOPE - ) - - endif() + # Look for the connector library and if found create the import target for + # it. Sets ${target_name}_RELEASE and ${target_name}_DEBUG to indicate + # whether release/debug variant of the library was found. Also sets + # or updates LIBRARY_DIR to the location where the library was found. add_connector_target(${which} ${target_name} ${base_name}) @@ -406,27 +532,48 @@ function(find_connector which) add_connector_target(${which} ${target_name}-static ${base_name}-static) endif() - set_parent(MYSQL_CONCPP_DEBUG_FOUND) + # Process targets created above to do consistency checks and declare required + # dependencies. Also sets DEBUG/RELEASE_FOUND flags as needed. foreach(tgt ${target_name} ${target_name}-static) - if(NOT TARGET mysql::${tgt}) + if(${tgt}_RELEASE) + set_parent(RELEASE_FOUND 1) + endif() + + if(${tgt}_DEBUG) + set_parent(DEBUG_FOUND 1) + endif() + + if(NOT TARGET mysql::concpp-${tgt}) continue() endif() + if(DEBUG_FOUND AND NOT ${tgt}_DEBUG) + list(APPEND DEBUG_MISSING ${tgt}) + endif() + set_parent(DEBUG_MISSING) + + if(RELEASE_FOUND AND NOT ${tgt}_RELEASE) + list(APPEND RELEASE_MISSING ${tgt}) + endif() + set_parent(RELEASE_MISSING) + unset(libs) - # JDBC dependency on the client library if specified via WITH_MYSQL + # JDBC dependency on the client library - if(target_name MATCHES "-jdbc" AND WITH_MYSQL) + if(tgt MATCHES "jdbc" AND JDBC_MYSQL_DEP) - list(APPEND libs mysqlclient) + if(NOT WIN32) + list(APPEND libs mysqlclient) + endif() - if(EXISTS "${WITH_MYSQL}/lib") + if(DEFINED WITH_MYSQL AND EXISTS "${WITH_MYSQL}/lib") message_info("Client library path: ${WITH_MYSQL}/lib") - target_link_directories(mysql::${tgt} + target_link_directories(mysql::concpp-${tgt} INTERFACE "${WITH_MYSQL}/lib" ) @@ -436,7 +583,7 @@ function(find_connector which) # OpenSSL dependency (target `mysql::openssl` is defined by find_deps()) # - # Note: Even though legacy connector does not use OpenSSL directly it migth + # Note: Even though JDBC connector does not use OpenSSL directly it might # have the client library statically linked in and get dependency # on OpenSSL that way. @@ -446,7 +593,7 @@ function(find_connector which) if(tgt MATCHES "-static") - set_target_properties(mysql::${tgt} PROPERTIES + set_target_properties(mysql::concpp-${tgt} PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES CXX INTERFACE_COMPILE_DEFINITIONS STATIC_CONCPP ) @@ -477,99 +624,219 @@ function(find_connector which) endif() - target_link_libraries(mysql::${tgt} INTERFACE ${libs}) + target_link_libraries(mysql::concpp-${tgt} INTERFACE ${libs}) - string(JOIN " " libs ${libs}) - message_info("Link libraries for target ${tgt}: ${libs}") + if(libs) + string(JOIN " " libs ${libs}) + message_info("Link libraries for target ${tgt}: ${libs}") + endif() endforeach(tgt) endfunction(find_connector) -# Create connector library import target named ${tgt} and pointing at library -# with base name ${base_name}. Target is not created if the library could -# not be found. If debug variant of library is found then it is used -# for IMPORT_LOCATION_DEBUG. In this case _DEBUG_FOUND variable is set to 1. +# Create connector library import target named ${tgt} pointing at library +# with base name ${base_name} if it was found. +# +# If LIBRARY_DIR is set the library is searched in that location, otherwise it +# is searched in system-wide locations. If the library is found, LIBRARY_DIR +# is set/updated to the location where it was found. +# +# Both release and debug variants of the library are searched for. Flags +# ${tgt}_RELEASE and ${tgt}_DEBUG are set to tell which variant was found. +# +# Note: The which parameter, either "XDevAPI" or "JDBC", is used for +# diagnostics only. function(add_connector_target which tgt base_name) + set(lib_name "${base_name}") set(type "SHARED") + set(static 0) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + if(tgt MATCHES "-static") set(type "STATIC") + set(static 1) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + endif() + + set(XDevAPI_abi @ABI_VERSION_MAJOR@) + set(JDBC_abi @JDBC_ABI_VERSION_MAJOR@) + set(find_lib_paths) + set(win_opts) + + if(LIBRARY_DIR) + set(find_lib_paths PATHS "${LIBRARY_DIR}" NO_DEFAULT_PATH) + endif() + + if(WIN32) + if(static) + set(win_opts PATH_SUFFIXES ${vs_suffix}) + else() + set(lib_name "${base_name}-${${which}_abi}-vs14") + endif() endif() + #message("!!! looking for ${lib_name} with options: ${find_lib_opts}") + unset(lib_path CACHE) find_library(lib_path - NAMES ${base_name} - PATHS ${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}/${vs_suffix} - NO_DEFAULT_PATH + NAMES ${lib_name} + ${find_lib_paths} ${win_opts} NO_CACHE ) - if(NOT lib_path) - message_info("Did not find ${which} ${type} library") - return() - endif() + if(lib_path) - message_info("${which} ${type} library at: ${lib_path}") - #message(STATUS "Creating target: mysql::${tgt}") + message_info( + "Found ${which} ${type} library at: ${lib_path}" + ) - add_library(mysql::${tgt} ${type} IMPORTED GLOBAL) + set_parent(${tgt}_RELEASE 1) - target_compile_features(mysql::${tgt} INTERFACE cxx_std_11) + # Note: LIBRARY_DIR is not yet set here if we were looking for the library + # in system-wide locations. In any case we set/update LIBRARY_DIR to + # the actual location of the library that was found. - set_target_properties(mysql::${tgt} PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${MYSQL_CONCPP_INCLUDE_DIR}" - ) + get_filename_component(LIBRARY_DIR "${lib_path}" DIRECTORY) + set_parent(LIBRARY_DIR) - # TODO: On Win set IMPORTED_LOCATION to the DLL path rather than the import library... + if(WIN32 AND NOT static) + find_imp_lib(imp_lib_path ${base_name} "${lib_path}") + endif() - set_target_properties(mysql::${tgt} PROPERTIES - IMPORTED_LOCATION "${lib_path}" - ) + endif() - if(WIN32) - set_target_properties(mysql::${tgt} PROPERTIES - IMPORTED_IMPLIB "${lib_path}" + # Look for debug variant of the library if LIBRARY_DIR is set. This is + # the case in one of these situations: + # + # a) the release library was found at LIBRARY_DIR above; + # + # b) we have monolithic connector install and LIBRARY_DIR is the library + # location inside that monolithic install. + # + # Case (b) is if we have not found the release library inside a monolithic + # connector installation but we still can find a debug library there. + + if(LIBRARY_DIR) + + unset(lib_path_debug CACHE) + find_library(lib_path_debug + NAMES ${lib_name} + PATHS "${LIBRARY_DIR}/debug" + ${win_opts} + NO_DEFAULT_PATH + NO_CACHE ) - endif() - # Look for debug variant of the library. + if(lib_path_debug) - unset(lib_path_debug CACHE) - find_library(lib_path_debug - NAMES ${base_name} - PATHS ${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}/debug/${vs_suffix} - NO_DEFAULT_PATH - NO_CACHE - ) + message_info( + "Found debug variant of ${which} ${type} library at: ${lib_path_debug}" + ) - if(lib_path_debug) + set_parent(${tgt}_DEBUG 1) - message_info( - "Found debug variant of ${which} ${type} library at: ${lib_path_debug}" - ) + if(WIN32 AND NOT static) + find_imp_lib(imp_lib_path_debug ${base_name} "${lib_path_debug}") + endif() - set(MYSQL_CONCPP_DEBUG_FOUND 1 PARENT_SCOPE) + endif() endif() - # Note: On non-Windows platforms we set the debug location of the connector - # target only if the debug library variant was found so that if it was - # not found then the release variant will be used. + + if(NOT lib_path AND NOT lib_path_debug) + + message_info("Did not find ${which} ${type} library") + return() + + endif() + + # + # Note: At this point we know that either the release or the debug connector + # was found. + # + # On non-Windows platforms the release connector can be used for debug + # builds if the debug connector was not found and vice-versa, the debug + # connector can be used for release builds if the release connector was + # not found. + # + # However, on Windows it is not possible to mix debug and release code which + # is reflected in the logic below. # - # However, on Windows it is not possible to mix debug and release code. - # Therefore we always set the debug location of the connector target - # on Windows so that if it is used in debug builds and the debug library - # variant is not present a linker error will be reported. - if(WIN32) + if(WIN32 AND NOT lib_path_debug) + + # If debug connector was not found on Windows we still set debug path to its + # expected location so that: + # + # 1. If debug connector is added later it will be used in debug builds. + # + # 2. If debug connector is not present then debug builds will fail which + # is what we want in that case (rather than incorrectly using the release + # variant of the library). + # + # Note: LIBRARY_DIR must be defined because the release library must have + # been found above. set(lib_path_debug - "${MYSQL_CONCPP_RUNTIME_LIBRARY_DIR}/debug/${vs_suffix}/${base_name}.lib" + "${LIBRARY_DIR}/debug/${lib_name}.dll" + ) + set(imp_lib_path_debug + "${LIBRARY_DIR}/debug/${vs_suffix}/${base_name}.lib" ) + # Note: If debug connector was not found on non-Windows platform then + # lib_path_debug remains undefined which means that the import target will + # not have a _DEBUG location defined. Therefore the main (release) location + # will be used also in debug builds as we want in that case. + + elseif(WIN32 AND NOT lib_path) + + # If release connector was not found on Windows we still set the release + # path to its expected location so that release builds will fail (because + # the release library will be not found at the location) or, if release + # connector is added later release builds will start working. + + set(lib_path "${LIBRARY_DIR}/${lib_name}.dll") + set(imp_lib_path "${LIBRARY_DIR}/${vs_suffix}/${base_name}.lib") + + elseif(NOT WIN32 AND NOT lib_path) + + # If we are on non-Windows platform and the release connector was not found + # then use the debug connector as a replacement. + + set(lib_path "${lib_path_debug}") + + endif() + + + set(tgt "concpp-${tgt}") + #message(STATUS "Creating target: mysql::${tgt}") + + add_library(mysql::${tgt} ${type} IMPORTED GLOBAL) + target_compile_features(mysql::${tgt} INTERFACE cxx_std_11) + + set_target_properties(mysql::${tgt} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${MYSQL_CONCPP_INCLUDE_DIR}" + ) + + + if(lib_path) + + set_target_properties(mysql::${tgt} PROPERTIES + IMPORTED_LOCATION "${lib_path}" + ) + + if(WIN32 AND imp_lib_path) + set_target_properties(mysql::${tgt} PROPERTIES + IMPORTED_IMPLIB "${imp_lib_path}" + ) + endif() + endif() if(lib_path_debug) @@ -578,9 +845,9 @@ function(add_connector_target which tgt base_name) IMPORTED_LOCATION_DEBUG "${lib_path_debug}" ) - if(WIN32) + if(WIN32 AND imp_lib_path_debug) set_target_properties(mysql::${tgt} PROPERTIES - IMPORTED_IMPLIB_DEBUG "${lib_path_debug}" + IMPORTED_IMPLIB_DEBUG "${imp_lib_path_debug}" ) endif() @@ -589,6 +856,35 @@ function(add_connector_target which tgt base_name) endfunction(add_connector_target) +# On Windows find import library for the DLL library at the given `path` with +# given `base_name`. The location of the import library is stored in variable +# named by `var`. +# +# Note: Not finding an import library for a DLL is a fatal error. + +function(find_imp_lib var base_name path) + + get_filename_component(base_path ${path} DIRECTORY) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib) + + #message("!!! Looking for import library for: ${path}") + find_library(${var} + NAMES ${base_name} + PATHS ${base_path} + PATH_SUFFIXES ${vs_suffix} + NO_DEFAULT_PATH + NO_CACHE + ) + + if(NOT ${var}) + message(FATAL_ERROR "Could not find import library for ${path}") + endif() + + set_parent(${var}) + +endfunction(find_imp_lib) + + function(find_deps) if(TARGET mysql::openssl) From 55153d447f7cc86ec0a4c9b7d22eb6ee627f6e6c Mon Sep 17 00:00:00 2001 From: Bogdan Degtyariov Date: Thu, 21 Nov 2024 14:40:22 +1100 Subject: [PATCH 15/43] WL#16645 - Option to select WebAuthN authenticator device Change-Id: I537456d51f0ec568f96e60d8ed7386f36198c861 --- jdbc/cppconn/connection.h | 1 + jdbc/driver/mysql_connection.cpp | 132 ++++++++++++++---- .../mysql_native_connection_wrapper.cpp | 37 +++-- .../mysql_native_connection_wrapper.h | 15 +- .../nativeapi/native_connection_wrapper.h | 42 ++++-- jdbc/test/unit/classes/connection.cpp | 11 ++ 6 files changed, 180 insertions(+), 58 deletions(-) diff --git a/jdbc/cppconn/connection.h b/jdbc/cppconn/connection.h index 12ae59b97..7c4db2e3e 100644 --- a/jdbc/cppconn/connection.h +++ b/jdbc/cppconn/connection.h @@ -139,6 +139,7 @@ "OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE" #define OPT_OCI_CLIENT_CONFIG_PROFILE "OPT_OCI_CLIENT_CONFIG_PROFILE" #define OPT_OPENID_TOKEN_FILE "OPT_OPENID_TOKEN_FILE" +#define OPT_WEBAUTHN_DEVICE_NUMBER "OPT_WEBAUTHN_DEVICE_NUMBER" /* Telemetry options diff --git a/jdbc/driver/mysql_connection.cpp b/jdbc/driver/mysql_connection.cpp index bae182b1a..5b933d139 100644 --- a/jdbc/driver/mysql_connection.cpp +++ b/jdbc/driver/mysql_connection.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef HAVE_STDINT_H #include #endif @@ -318,6 +319,16 @@ static const String2IntMap stringOptions[]= {OPT_LOAD_DATA_LOCAL_DIR, MYSQL_OPT_LOAD_DATA_LOCAL_DIR, false} }; +static const std::unordered_set stringPluginOptions = { + OPT_OCI_CONFIG_FILE, + OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE, + OPT_OCI_CLIENT_CONFIG_PROFILE, + OPT_OPENID_TOKEN_FILE +}; + +static const std::unordered_set intPluginOptions = { + OPT_WEBAUTHN_DEVICE_NUMBER +}; //Option conversion for libmysqlclient < 80011 @@ -1335,12 +1346,12 @@ void MySQL_Connection::init(ConnectOptionsMap & properties) options are set here, before making a connection, to the values specified by this connection and driver. - The guard is needed to prevent overwritting plugin options by another + The guard is needed to prevent overwriting plugin options by another connection while this connection is being established. Note: If connection options do not specify a value for a plugin option that plugin option is set to null which resets it to its default value (which - could be overwriten by other connections). + could be overwritten by other connections). TODO: Move setting of plugin options later in the connection process, after any other options which can take long time to set (e.g. OpenSSL options or @@ -1351,44 +1362,105 @@ void MySQL_Connection::init(ConnectOptionsMap & properties) MySQL_Connection::PluginGuard guard{this}; + /* + Set option `option` of plugin `plugin_name` of type `plugin_type` to + the value given by connection option `con_opt_name` if it is specified. + Otherwise (if the connection option is not specified) reset plugin option + value to the default value given by `default_val`. + + If plugin option value could not be set throw error with description given + by `err_msg` (not if the plugin option is set to its default value). + + Note that for most plugin options the default value is restored when + the option is set to null. + */ + auto set_plugin_option = [this, &properties] ( const ::sql::SQLString con_opt_name, int plugin_type, const ::sql::SQLString & plugin_name, const ::sql::SQLString & option, - const char * err_msg) + const char * err_msg, + const void* default_val = nullptr + ) { sql::SQLString *p_s = nullptr; + const void* val = nullptr; auto opt = properties.find(con_opt_name); if (opt != properties.end()) { - try { - p_s = (opt->second).get(); - } catch (sql::InvalidArgumentException&) { - throw sql::InvalidArgumentException( - "Wrong type passed for " + con_opt_name + - ". Expected sql::SQLString."); + if (stringPluginOptions.count(con_opt_name)) + { + try + { + p_s = (opt->second).get(); + if (!p_s) + throw sql::InvalidArgumentException{ + "No string value passed for " + con_opt_name + }; + val = p_s->c_str(); + } + catch (sql::InvalidArgumentException&) + { + throw sql::InvalidArgumentException( + "Wrong type passed for " + con_opt_name + + ". Expected sql::SQLString."); + } + } + else if (intPluginOptions.count(con_opt_name)) + { + try + { + val = (opt->second).get(); + if (!val) + throw sql::InvalidArgumentException{ + "No int value passed for " + con_opt_name + }; + } + catch (sql::InvalidArgumentException&) + { + throw sql::InvalidArgumentException( + "Wrong type passed for " + con_opt_name + + ". Expected int."); + } + } + else + { + /* + We end up here only if below this lambda is called with connection + option that is not a plugin option (not listed in + `stringPluginOptions` or `intPluginOptions` -- that should never + happen. + */ + assert(false); } } - /* - Note: the plugin option will be set to nullptr if the corresponding - connection option was not set. This has the effect of re-setting plugin - option to its default value (if it was changed). - */ + try + { + /* + Note: `val` is null if the connection option was not set. In that case + we reset plugin option to the default value as given by `default_val` + parameter. The last argument of `plugin_option()` informs that the + option set is the default one which is the case when `val` is null. + */ - const void* val = p_s ? p_s->c_str() : nullptr; - try { - proxy->plugin_option(plugin_type, plugin_name, option, val); - } catch (sql::InvalidArgumentException &e) { + proxy->plugin_option( + plugin_type, plugin_name, option, + val ? val : default_val, val == nullptr + ); + } + catch (sql::InvalidArgumentException &e) + { if (val) - // Throw only when setting a non-null value + // Throw only when setting to a non-default value throw ::sql::SQLUnsupportedOptionException(err_msg, con_opt_name.asStdString()); } }; + set_plugin_option(OPT_OCI_CONFIG_FILE, MYSQL_CLIENT_AUTHENTICATION_PLUGIN, "authentication_oci_client", @@ -1419,18 +1491,30 @@ void MySQL_Connection::init(ConnectOptionsMap & properties) "Failed to set token file for authentication_openid_connect_client plugin" ); + // Note: The default value for WebAuthN "device" option is 0. + + const int webauthn_device_default_val = 0; + + set_plugin_option(OPT_WEBAUTHN_DEVICE_NUMBER, + MYSQL_CLIENT_AUTHENTICATION_PLUGIN, + "authentication_webauthn_client", + "device", + "Failed to set a WebAuthn authentication device", + &webauthn_device_default_val + ); + /* Setting webauthn callback functions. The callback is an option of the webauthn authentication plugin that is configured on the driver level (as opposed to plugin options above, which are configured on per-connection basis). Correctly setting the option - based on driver configuration is handled by register_webauthn_callback() function - of PluginGuard class. The option will be set only if needed. + based on driver configuration is handled by register_webauthn_callback() + function of PluginGuard class. The option will be set only if needed. - Note: If register_webauthn_callback() sets a callback then the plugin options guard - ensures that this callback function is not modified by other connections - while being used. + Note: If register_webauthn_callback() sets a callback then the plugin + options guard ensures that this callback function is not modified by other + connections while being used. */ guard.register_webauthn_callback(*static_cast(driver)); diff --git a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp index b513a8127..b86c0aec4 100644 --- a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp +++ b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.cpp @@ -563,19 +563,23 @@ struct MySQL_NativeConnectionWrapper::PluginGuard int MySQL_NativeConnectionWrapper::plugin_option( - int plugin_type, - const ::sql::SQLString & plugin_name, - const ::sql::SQLString & option, - const void * value) -try{ + int plugin_type, + const ::sql::SQLString & plugin_name, + const ::sql::SQLString & option, + const void * value, + bool default_value +) +try +{ PluginGuard guard{this}; + /* - Note: Try to load plugin into cache only if the option has non-default - value. + Note: Try to load plugin into cache only if the option is set to + a non-default value. */ struct st_mysql_client_plugin *plugin - = guard.get_plugin(plugin_type, plugin_name, value != nullptr); + = guard.get_plugin(plugin_type, plugin_name, !default_value); /* Note: `plugin` can be null here only if we are setting option to @@ -597,14 +601,19 @@ catch(sql::InvalidArgumentException &e) throw sql::InvalidArgumentException(err); } + int MySQL_NativeConnectionWrapper::plugin_option( - int plugin_type, - const ::sql::SQLString & plugin_name, - const ::sql::SQLString & option, - const ::sql::SQLString & value) -{ - return plugin_option(plugin_type, plugin_name, option, value.c_str()); + int plugin_type, + const ::sql::SQLString & plugin_name, + const ::sql::SQLString & option, + const ::sql::SQLString & value, + bool default_value +) +{ + return plugin_option( + plugin_type, plugin_name, option, value.c_str(), default_value + ); } diff --git a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h index fbc3e272d..04f63e2fe 100644 --- a/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h +++ b/jdbc/driver/nativeapi/mysql_native_connection_wrapper.h @@ -141,12 +141,15 @@ struct st_mysql* mysql; int get_option(::sql::mysql::MySQL_Connection_Options, const bool &) override; int get_option(::sql::mysql::MySQL_Connection_Options, const int &) override; - int plugin_option(int plugin_type, const ::sql::SQLString &plugin_name, - const ::sql::SQLString &option, const void *) override; - - int plugin_option(int plugin_type, const ::sql::SQLString &plugin_name, - const ::sql::SQLString &option, - const ::sql::SQLString &value) override; + int plugin_option( + int plugin_type, const ::sql::SQLString &plugin_name, + const ::sql::SQLString &option, const void *, bool + ) override; + + int plugin_option( + int plugin_type, const ::sql::SQLString &plugin_name, + const ::sql::SQLString &option, const ::sql::SQLString &value, bool + ) override; int get_plugin_option(int plugin_type, const ::sql::SQLString &plugin_name, const ::sql::SQLString &option, diff --git a/jdbc/driver/nativeapi/native_connection_wrapper.h b/jdbc/driver/nativeapi/native_connection_wrapper.h index 247572c49..6efb8b425 100644 --- a/jdbc/driver/nativeapi/native_connection_wrapper.h +++ b/jdbc/driver/nativeapi/native_connection_wrapper.h @@ -140,20 +140,34 @@ class NativeConnectionWrapper : public util::nocopy virtual int get_option(::sql::mysql::MySQL_Connection_Options, const int &) = 0; - virtual int plugin_option(int plugin_type, - const ::sql::SQLString & plugin_name, - const ::sql::SQLString & option, - const void * value) = 0; - - virtual int plugin_option(int plugin_type, - const ::sql::SQLString & plugin_name, - const ::sql::SQLString & option, - const ::sql::SQLString & value) = 0; - - virtual int get_plugin_option(int plugin_type, - const ::sql::SQLString & plugin_name, - const ::sql::SQLString & option, - const ::sql::SQLString & value) = 0; + /* + Note: The `default_value` flag informs whether the value to which option + is set is its default value. This can be used to avoid unnecessary loading + of the plugin. + */ + + virtual int plugin_option( + int plugin_type, + const ::sql::SQLString & plugin_name, + const ::sql::SQLString & option, + const void * value, + bool default_value = false + ) = 0; + + virtual int plugin_option( + int plugin_type, + const ::sql::SQLString & plugin_name, + const ::sql::SQLString & option, + const ::sql::SQLString & value, + bool default_value = false + ) = 0; + + virtual int get_plugin_option( + int plugin_type, + const ::sql::SQLString & plugin_name, + const ::sql::SQLString & option, + const ::sql::SQLString & value + ) = 0; virtual bool has_query_attributes() = 0; diff --git a/jdbc/test/unit/classes/connection.cpp b/jdbc/test/unit/classes/connection.cpp index 9b00b58f1..182cec77f 100644 --- a/jdbc/test/unit/classes/connection.cpp +++ b/jdbc/test/unit/classes/connection.cpp @@ -4045,6 +4045,17 @@ void connection::test_fido_webauthn(sql::ConnectOptionsMap &opt, bool callback_i if (getenv("PLUGIN_DIR")) opt[OPT_PLUGIN_DIR] = getenv("PLUGIN_DIR"); + /* + This is for extra testing of WEBAUTHN_DEVICE_NUMBER option in various + scenarios of Webauthn authentication. + */ + + { + char *opt_val = getenv("WEBAUTHN_DEVICE_NUMBER"); + if (opt_val) + opt[OPT_WEBAUTHN_DEVICE_NUMBER] = std::atoi(opt_val); + } + sql::Driver * driver = sql::mysql::get_driver_instance(); auto test_connection_drv = [&opt](int expected, sql::Driver *drv) From 4fec7b4cb9e8f5f19e14700670432d6e0b7dd91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Fri, 6 Dec 2024 13:43:25 +0100 Subject: [PATCH 16/43] Bump connector version to 9.2.0 --- doc/doxygen.cfg | 2 +- version.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index 63094ffb6..2468e4ff0 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -75,7 +75,7 @@ PROJECT_NAME = "MySQL Connector/C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 9.1.0 +PROJECT_NUMBER = 9.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/version.cmake b/version.cmake index 7598398df..2ec78a02e 100644 --- a/version.cmake +++ b/version.cmake @@ -35,7 +35,7 @@ set(COPYRIGHT_YEAR "2024" CACHE INTERNAL "version info") # set(CONCPP_VERSION_MAJOR 9 CACHE INTERNAL "version info") -set(CONCPP_VERSION_MINOR 1 CACHE INTERNAL "version info") +set(CONCPP_VERSION_MINOR 2 CACHE INTERNAL "version info") set(CONCPP_VERSION_MICRO 0 CACHE INTERNAL "version info") # Level is "-alpha", "-beta", empty if GA set(CONCPP_VERSION_LEVEL "" CACHE INTERNAL "version info") From d8eedf37011a132c42fb4016e66d277934ffea13 Mon Sep 17 00:00:00 2001 From: Apoorva Verma Date: Wed, 11 Dec 2024 09:40:12 +0100 Subject: [PATCH 17/43] Updated the LICENSE files --- LICENSE.txt | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index ddcd86cb1..0603db9cc 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/C++ 9.1.0 Community +MySQL Connector/C++ 9.2.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/C++ 9.1.0 Community. + MySQL Connector/C++ 9.2.0 Community. - Last updated: September 2024 + Last updated: November 2024 Licensing Information - This release of MySQL Connector/C++ 9.1.0 Community is brought to you + This release of MySQL Connector/C++ 9.2.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/C++ 9.1.0 Community is designed to + This distribution of MySQL Connector/C++ 9.2.0 Community 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 the license documentation. Without limiting your rights @@ -570,6 +570,15 @@ documentation and/or software. Google Protocol Buffers +You may be receiving a copy of abseil-cpp as part of this product in object code + form. +The terms of the Oracle license do NOT apply to abseil-cpp. +abseil-cpp is licensed under the Apache 2.0 license, separate from the Oracle pr +oduct. +If you do not wish to install this library, you may remove it, but the Oracle pr +ogram +might not operate properly or at all without it. + Copyright 2008 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -637,7 +646,14 @@ in the 'Standard Licenses' section. Kerberos5 -Kerberos5 +You may be receiving a copy of the kerberos documentation as part of this +product. The terms of the Oracle license do NOT apply to Kerberos documentation. + +Kerberos documentation is licensed under the CC-BY-SA 3.0 license, separate from + +the Oracle product. +If you do not wish to install this library, you may remove it, but +the Oracle program might not operate properly or at all without it. Copyright (C) 1985-2019 by the Massachusetts Institute of Technology. From 883d20d0193ee19387cc8010634c809a1fd817c1 Mon Sep 17 00:00:00 2001 From: Apoorva Verma Date: Wed, 11 Dec 2024 12:15:33 +0100 Subject: [PATCH 18/43] Updated the copyright year --- README.txt | 2 +- packaging/deb-in/copyright.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt index ffdc35cbe..d8d6abc47 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -Copyright (c) 2008, 2024, Oracle and/or its affiliates. +Copyright (c) 2008, 2025, Oracle and/or its affiliates. This is a release of MySQL Connector/C++, the C++ interface for communicating with MySQL servers. diff --git a/packaging/deb-in/copyright.in b/packaging/deb-in/copyright.in index 3977c6f7a..b6ef630aa 100644 --- a/packaging/deb-in/copyright.in +++ b/packaging/deb-in/copyright.in @@ -4,7 +4,7 @@ Upstream-Contact: MySQL Release Engineering Source: https://dev.mysql.com/doc/connector-cpp/en/ Files: * -Copyright: 2008, 2024, Oracle and/or its affiliates. +Copyright: 2008, 2025, Oracle and/or its affiliates. License: @DEB_LICENSENAME@ This is a release of MySQL Connector/C++, the C++ interface for communicating with MySQL servers. From 70abc970b99086978b6d654826f3a8b3ebee72dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Wed, 11 Dec 2024 16:54:17 +0100 Subject: [PATCH 19/43] Bug#37278704: Do not throw exceptions from destructors Note: throwing from destructors was the root cause for the bug. --- cdk/core/session.cc | 10 ++++++-- cdk/foundation/connection_openssl.cc | 6 ++--- cdk/foundation/connection_tcpip.cc | 2 +- cdk/foundation/connection_tcpip_base.h | 4 +-- cdk/foundation/socket_detail.cc | 9 ++++++- cdk/include/mysql/cdk/api/document.h | 4 +-- cdk/include/mysql/cdk/api/obj_ref.h | 2 +- cdk/include/mysql/cdk/api/session.h | 2 +- cdk/include/mysql/cdk/codec.h | 2 +- cdk/include/mysql/cdk/common.h | 2 +- cdk/include/mysql/cdk/data_source.h | 10 ++++---- cdk/include/mysql/cdk/foundation/async.h | 2 +- cdk/include/mysql/cdk/foundation/codec.h | 4 +-- .../mysql/cdk/foundation/connection_tcpip.h | 2 +- .../mysql/cdk/foundation/diagnostics.h | 8 +++--- .../mysql/cdk/foundation/error_category.h | 2 +- .../mysql/cdk/foundation/opaque_impl.h | 2 +- .../mysql/cdk/foundation/opaque_impl.i | 2 +- cdk/include/mysql/cdk/foundation/stream.h | 2 +- cdk/include/mysql/cdk/foundation/variant.h | 4 +-- cdk/include/mysql/cdk/mysqlx/common.h | 8 +++--- cdk/include/mysql/cdk/mysqlx/result.h | 21 +++++++++++----- cdk/include/mysql/cdk/mysqlx/session.h | 4 +-- cdk/include/mysql/cdk/protocol/mysqlx.h | 8 +++--- cdk/include/mysql/cdk/protocol/mysqlx/expr.h | 2 +- cdk/include/mysql/cdk/session.h | 2 +- cdk/mysqlx/converters.h | 2 +- cdk/mysqlx/result.cc | 4 +-- cdk/mysqlx/session.cc | 7 ++---- cdk/mysqlx/stmt.h | 25 +++++++++++-------- cdk/protocol/mysqlx/builders.h | 4 +-- cdk/protocol/mysqlx/crud.cc | 5 ++-- cdk/protocol/mysqlx/protocol.cc | 2 +- cdk/protocol/mysqlx/protocol.h | 6 +++-- cdk/protocol/mysqlx/protocol_compression.cc | 8 +++--- cdk/protocol/mysqlx/protocol_compression.h | 10 ++++---- common/op_impl.h | 14 +++++++---- devapi/impl.h | 2 +- devapi/result.cc | 2 +- devapi/session.cc | 2 +- include/mysqlx/common.h | 2 ++ include/mysqlx/common/op_if.h | 2 +- include/mysqlx/devapi/detail/result.h | 2 +- include/mysqlx/devapi/detail/session.h | 9 ++++--- include/mysqlx/devapi/executable.h | 2 +- 45 files changed, 136 insertions(+), 100 deletions(-) diff --git a/cdk/core/session.cc b/cdk/core/session.cc index 7a00cc1fe..feb642e8e 100644 --- a/cdk/core/session.cc +++ b/cdk/core/session.cc @@ -53,7 +53,7 @@ struct Session_builder struct ReportStatus { - //False if not able to connect, true if all is good. + // False if not able to connect, true if all is good. option_t m_status = false; Session_builder::ep_filter_t m_filter; size_t m_id; @@ -63,6 +63,12 @@ struct Session_builder , m_id(id) {} + /* + Note: The only reason for ReportStatus object is to use RAII to invoke + m_filter() on destruction to report session creation status. So this + is part of logic of methods that use such object and as such is allowed + to throw errors from the dtor. + */ ~ReportStatus() { @@ -481,7 +487,7 @@ Session::Session(ds::Unix_socket &ds, const ds::Unix_socket::Options &options) #endif //#ifndef WIN32 -Session::~Session() +Session::~Session() NOEXCEPT { delete m_session; delete m_connection; diff --git a/cdk/foundation/connection_openssl.cc b/cdk/foundation/connection_openssl.cc index 24dc71469..e0f2e09aa 100644 --- a/cdk/foundation/connection_openssl.cc +++ b/cdk/foundation/connection_openssl.cc @@ -265,12 +265,12 @@ class connection_TLS_impl , m_options(options) {} - ~connection_TLS_impl() + ~connection_TLS_impl() NOEXCEPT { if (m_tls) { /* - Server is expecting a SSL quiet shutdown. + Server is expecting a SSL quiet shutdown. */ SSL_set_quiet_shutdown(m_tls, 1); SSL_shutdown(m_tls); @@ -697,7 +697,7 @@ class safe_X509 : m_X509(obj) {} - ~safe_X509() + ~safe_X509() NOEXCEPT { if (std::is_same::value) { diff --git a/cdk/foundation/connection_tcpip.cc b/cdk/foundation/connection_tcpip.cc index cb4374dd4..7a8bfe366 100644 --- a/cdk/foundation/connection_tcpip.cc +++ b/cdk/foundation/connection_tcpip.cc @@ -138,7 +138,7 @@ class Socket_system_initializer detail::initialize_socket_system(); } - ~Socket_system_initializer() + ~Socket_system_initializer() NOEXCEPT { try { diff --git a/cdk/foundation/connection_tcpip_base.h b/cdk/foundation/connection_tcpip_base.h index 6a4dc4cc0..9bfb12cb4 100644 --- a/cdk/foundation/connection_tcpip_base.h +++ b/cdk/foundation/connection_tcpip_base.h @@ -110,9 +110,9 @@ class Socket_base::Impl return detail::poll_one(m_sock, detail::POLL_MODE_WRITE, false) > 0; } - virtual ~Impl() + virtual ~Impl() NOEXCEPT { - close(); + try { close(); } catch (...) {} } virtual void do_connect() =0; diff --git a/cdk/foundation/socket_detail.cc b/cdk/foundation/socket_detail.cc index ffea5d61c..6663dc5c8 100644 --- a/cdk/foundation/socket_detail.cc +++ b/cdk/foundation/socket_detail.cc @@ -643,7 +643,7 @@ Socket connect(const char *host_name, unsigned short port, struct AddrInfoGuard { addrinfo* list; - ~AddrInfoGuard() { freeaddrinfo(list); } + ~AddrInfoGuard() NOEXCEPT { freeaddrinfo(list); } } guard = { host_list }; @@ -916,6 +916,13 @@ void recv(Socket socket, byte *buffer, size_t buffer_size) size_t bytes_received = 0; + /* + Note: In presence of timeouts recv_some() can return 0 which would lead + to an infinite loop here! See also bug#37278716. + + A solution would be to throw error if timeout was hit? + */ + while (bytes_received != buffer_size) bytes_received += recv_some(socket, buffer + bytes_received, buffer_size - bytes_received, true); } diff --git a/cdk/include/mysql/cdk/api/document.h b/cdk/include/mysql/cdk/api/document.h index ed76ff758..0fb456fa4 100644 --- a/cdk/include/mysql/cdk/api/document.h +++ b/cdk/include/mysql/cdk/api/document.h @@ -107,7 +107,7 @@ class Any_processor virtual Doc_prc* doc() =0; - virtual ~Any_processor() {} + virtual ~Any_processor() NOEXCEPT {} }; @@ -156,7 +156,7 @@ class Doc_processor */ virtual Any_prc* key_val(const string &key) =0; - virtual ~Doc_processor() {} + virtual ~Doc_processor() NOEXCEPT {} }; diff --git a/cdk/include/mysql/cdk/api/obj_ref.h b/cdk/include/mysql/cdk/api/obj_ref.h index 9f0ce2eaf..8c4747c44 100644 --- a/cdk/include/mysql/cdk/api/obj_ref.h +++ b/cdk/include/mysql/cdk/api/obj_ref.h @@ -47,7 +47,7 @@ class Ref_base { public: - virtual ~Ref_base() {} + virtual ~Ref_base() NOEXCEPT {} virtual const string name() const =0; virtual const string orig_name() const { return name(); } diff --git a/cdk/include/mysql/cdk/api/session.h b/cdk/include/mysql/cdk/api/session.h index 40dd4b9df..0460ef44b 100644 --- a/cdk/include/mysql/cdk/api/session.h +++ b/cdk/include/mysql/cdk/api/session.h @@ -44,7 +44,7 @@ class Session { public: - virtual ~Session() {} + virtual ~Session() NOEXCEPT {} // Check if given session is valid. Function is_valid() performs a lightweight, local check while // check_valid() might communicate with the data store to perform this check. diff --git a/cdk/include/mysql/cdk/codec.h b/cdk/include/mysql/cdk/codec.h index 2a37b0097..d960ee5b4 100644 --- a/cdk/include/mysql/cdk/codec.h +++ b/cdk/include/mysql/cdk/codec.h @@ -371,7 +371,7 @@ class Codec Codec(const Format_info &fi) : Codec_base(fi) {} - virtual ~Codec() {} + virtual ~Codec() NOEXCEPT {} virtual size_t from_bytes(bytes buf, float &val); virtual size_t from_bytes(bytes buf, double &val); diff --git a/cdk/include/mysql/cdk/common.h b/cdk/include/mysql/cdk/common.h index d0da13e60..1620175c4 100644 --- a/cdk/include/mysql/cdk/common.h +++ b/cdk/include/mysql/cdk/common.h @@ -414,7 +414,7 @@ class JSON_processor virtual void num(double) =0; virtual void yesno(bool) =0; - virtual ~JSON_processor() {} + virtual ~JSON_processor() NOEXCEPT {} }; typedef api::Doc_base JSON; diff --git a/cdk/include/mysql/cdk/data_source.h b/cdk/include/mysql/cdk/data_source.h index 99ae17eb3..420cefda6 100644 --- a/cdk/include/mysql/cdk/data_source.h +++ b/cdk/include/mysql/cdk/data_source.h @@ -52,7 +52,7 @@ namespace ds { struct Attr_processor { - virtual ~Attr_processor() {} + virtual ~Attr_processor() NOEXCEPT {} virtual void attr(const string &key, const string &val)=0; }; @@ -90,7 +90,7 @@ class Options } } - virtual ~Options() {} + virtual ~Options() NOEXCEPT {} virtual const string& user() const { return m_usr; } virtual const std::string* password() const @@ -171,7 +171,7 @@ class TCPIP throw_error("invalid empty host name"); } - virtual ~TCPIP() {} + virtual ~TCPIP() NOEXCEPT {} virtual unsigned short port() const { return m_port; } virtual const std::string& host() const { return m_host; } @@ -346,7 +346,7 @@ class Unix_socket throw_error("invalid empty socket path"); } - virtual ~Unix_socket() {} + virtual ~Unix_socket() NOEXCEPT {} virtual const std::string& path() const { return m_path; } }; @@ -386,7 +386,7 @@ class TCPIP : public cdk::ds::mysqlx::TCPIP : cdk::ds::mysqlx::TCPIP(_host, _port) {} - virtual ~TCPIP() {} + virtual ~TCPIP() NOEXCEPT {} typedef ds::Options Options; }; diff --git a/cdk/include/mysql/cdk/foundation/async.h b/cdk/include/mysql/cdk/foundation/async.h index 482cbdf2b..1bad184b4 100644 --- a/cdk/include/mysql/cdk/foundation/async.h +++ b/cdk/include/mysql/cdk/foundation/async.h @@ -50,7 +50,7 @@ class Async_op_base : nocopy { public: - virtual ~Async_op_base() {} + virtual ~Async_op_base() NOEXCEPT {} virtual bool is_completed() const =0; diff --git a/cdk/include/mysql/cdk/foundation/codec.h b/cdk/include/mysql/cdk/foundation/codec.h index 5551574c0..40314c0f9 100644 --- a/cdk/include/mysql/cdk/foundation/codec.h +++ b/cdk/include/mysql/cdk/foundation/codec.h @@ -71,7 +71,7 @@ class String_codec { public: - virtual ~String_codec() {} + virtual ~String_codec() NOEXCEPT {} //virtual size_t measure(const string&) =0; virtual size_t from_bytes(bytes, string&) =0; @@ -165,7 +165,7 @@ class Number_codec { public: - virtual ~Number_codec() {} + virtual ~Number_codec() NOEXCEPT {} virtual size_t from_bytes(bytes buf, int8_t &val) =0; virtual size_t from_bytes(bytes buf, int16_t &val) =0; diff --git a/cdk/include/mysql/cdk/foundation/connection_tcpip.h b/cdk/include/mysql/cdk/foundation/connection_tcpip.h index 927c900c4..00a996719 100644 --- a/cdk/include/mysql/cdk/foundation/connection_tcpip.h +++ b/cdk/include/mysql/cdk/foundation/connection_tcpip.h @@ -107,7 +107,7 @@ class IO_error : public Error_class : Error_base(NULL, io_error(num)) {} - virtual ~IO_error() throw() {} + virtual ~IO_error() NOEXCEPT {} }; diff --git a/cdk/include/mysql/cdk/foundation/diagnostics.h b/cdk/include/mysql/cdk/foundation/diagnostics.h index 37ce41427..76abd671d 100644 --- a/cdk/include/mysql/cdk/foundation/diagnostics.h +++ b/cdk/include/mysql/cdk/foundation/diagnostics.h @@ -223,7 +223,7 @@ class Diagnostic_iterator : public api::Diagnostics::Iterator : m_entries(NULL), m_level(Severity::ERROR) {} - virtual ~Diagnostic_iterator() {} + virtual ~Diagnostic_iterator() NOEXCEPT {} const Entry& entry() { @@ -265,8 +265,10 @@ class Diagnostic_arena : m_it(m_entries, Severity::ERROR) {} - virtual ~Diagnostic_arena() - { clear(); } + virtual ~Diagnostic_arena() NOEXCEPT + { + try { clear(); } catch (...) {} + } /* diff --git a/cdk/include/mysql/cdk/foundation/error_category.h b/cdk/include/mysql/cdk/foundation/error_category.h index b38128c39..0d23c5c1c 100644 --- a/cdk/include/mysql/cdk/foundation/error_category.h +++ b/cdk/include/mysql/cdk/foundation/error_category.h @@ -144,7 +144,7 @@ const error_category& posix_error_category(); struct error_category_##EC : public cdk::foundation::error_category_base \ { \ error_category_##EC() {} \ - const char* name() const throw() { return "cdk-" #EC; } \ + const char* name() const NOEXCEPT { return "cdk-" #EC; } \ std::string message(int code) const \ { CDK_ERROR_SWITCH(NS, EC, code); } \ cdk::foundation::error_condition do_default_error_condition(int) const; \ diff --git a/cdk/include/mysql/cdk/foundation/opaque_impl.h b/cdk/include/mysql/cdk/foundation/opaque_impl.h index d074856c9..0f5d6fbc6 100644 --- a/cdk/include/mysql/cdk/foundation/opaque_impl.h +++ b/cdk/include/mysql/cdk/foundation/opaque_impl.h @@ -171,7 +171,7 @@ class opaque_impl protected: - virtual ~opaque_impl(); + virtual ~opaque_impl() NOEXCEPT; // Default constructor: uses default constructor of internal implementation type. diff --git a/cdk/include/mysql/cdk/foundation/opaque_impl.i b/cdk/include/mysql/cdk/foundation/opaque_impl.i index e62fda1c6..0ab2ffd40 100644 --- a/cdk/include/mysql/cdk/foundation/opaque_impl.i +++ b/cdk/include/mysql/cdk/foundation/opaque_impl.i @@ -129,7 +129,7 @@ namespace foundation { namespace cdk { \ namespace foundation { \ template<> \ - opaque_impl::~opaque_impl() { delete m_impl; } \ + opaque_impl::~opaque_impl() NOEXCEPT { delete m_impl; } \ }} // cdk::foundation #define IMPL_DEFAULT(X) \ diff --git a/cdk/include/mysql/cdk/foundation/stream.h b/cdk/include/mysql/cdk/foundation/stream.h index 1d2a6c037..f0533e22c 100644 --- a/cdk/include/mysql/cdk/foundation/stream.h +++ b/cdk/include/mysql/cdk/foundation/stream.h @@ -75,7 +75,7 @@ class Connection , public Output_stream { public: - virtual ~Connection() {} + virtual ~Connection() NOEXCEPT {} virtual void connect() =0; virtual void close() =0; virtual bool is_closed() const =0; diff --git a/cdk/include/mysql/cdk/foundation/variant.h b/cdk/include/mysql/cdk/foundation/variant.h index 03a105963..b7dcaa993 100644 --- a/cdk/include/mysql/cdk/foundation/variant.h +++ b/cdk/include/mysql/cdk/foundation/variant.h @@ -356,9 +356,9 @@ class variant return *this; } - ~variant() + ~variant() NOEXCEPT { - Base::destroy(); + try { Base::destroy(); } catch (...) {} } operator bool() diff --git a/cdk/include/mysql/cdk/mysqlx/common.h b/cdk/include/mysql/cdk/mysqlx/common.h index a1fd64e8b..9d7aa1f54 100644 --- a/cdk/include/mysql/cdk/mysqlx/common.h +++ b/cdk/include/mysql/cdk/mysqlx/common.h @@ -95,13 +95,13 @@ class Server_error typedef protocol::mysqlx::sql_state_t sql_state_t; - Server_error(unsigned num, sql_state_t, const string& desc = string()) throw() + Server_error(unsigned num, sql_state_t, const string& desc = string()) NOEXCEPT : Error_base(NULL, server_error(static_cast(num)), desc) { assert(num < (unsigned)std::numeric_limits::max()); } - virtual ~Server_error() throw() {} + virtual ~Server_error() NOEXCEPT {} }; @@ -115,7 +115,7 @@ class Server_prepare_error Server_prepare_error( unsigned num, sql_state_t sql_state, const string& desc = string() - ) throw() + ) NOEXCEPT : Error_base(NULL, num, sql_state , desc) {} }; @@ -128,7 +128,7 @@ class Server_expectation_error typedef protocol::mysqlx::sql_state_t sql_state_t; - Server_expectation_error(const string& desc) throw() + Server_expectation_error(const string& desc) NOEXCEPT : Error_base(NULL, 5168, sql_state_t("HY000") , desc) {} }; diff --git a/cdk/include/mysql/cdk/mysqlx/result.h b/cdk/include/mysql/cdk/mysqlx/result.h index ad4c5ebfe..0ffbaf016 100644 --- a/cdk/include/mysql/cdk/mysqlx/result.h +++ b/cdk/include/mysql/cdk/mysqlx/result.h @@ -446,12 +446,21 @@ class Stmt_op assert(m_session); } - virtual ~Stmt_op() + virtual ~Stmt_op() NOEXCEPT { - discard(); - wait(); - if (m_session) - m_session->deregister_stmt(this); + try + { + discard(); + wait(); + } + catch (...) {} + + try + { + if (m_session) + m_session->deregister_stmt(this); + } + catch (...) {} } Session& get_session() @@ -812,7 +821,7 @@ class Cursor public: Cursor(const std::shared_ptr &reply); - ~Cursor(); + ~Cursor() NOEXCEPT; void get_rows(mysqlx::Row_processor& rp); void get_rows(mysqlx::Row_processor& rp, row_count_t limit); diff --git a/cdk/include/mysql/cdk/mysqlx/session.h b/cdk/include/mysql/cdk/mysqlx/session.h index 6f9b5752d..85b8d962d 100755 --- a/cdk/include/mysql/cdk/mysqlx/session.h +++ b/cdk/include/mysql/cdk/mysqlx/session.h @@ -148,7 +148,7 @@ class SessionAuth public: SessionAuth(Session&, const char *method); - virtual ~SessionAuth() {} + virtual ~SessionAuth() NOEXCEPT {} /* Authentication data to be sent in the AuthenticateStart message, @@ -294,7 +294,7 @@ class Session */ Compression_type::value negotiate_compression(const std::vector& algorithms); - virtual ~Session(); + virtual ~Session() NOEXCEPT; /* Check if given session is valid. Function is_valid() performs diff --git a/cdk/include/mysql/cdk/protocol/mysqlx.h b/cdk/include/mysql/cdk/protocol/mysqlx.h index 18f345538..f10da5ca6 100644 --- a/cdk/include/mysql/cdk/protocol/mysqlx.h +++ b/cdk/include/mysql/cdk/protocol/mysqlx.h @@ -799,7 +799,7 @@ class Protocol::Stream Stream() {} - virtual ~Stream() + virtual ~Stream() NOEXCEPT {} virtual Op* read(const buffers&) =0; @@ -919,7 +919,7 @@ class Processor_base { public: - virtual ~Processor_base(){} + virtual ~Processor_base() NOEXCEPT {} typedef protocol::mysqlx::byte byte; typedef protocol::mysqlx::string string; @@ -1214,7 +1214,7 @@ class Update_processor virtual void target_path(const api::Doc_path&) = 0; virtual Expr_prc* update_op(update_op::value ) = 0; - virtual ~Update_processor() {} + virtual ~Update_processor() NOEXCEPT {} }; class Update_spec @@ -1282,7 +1282,7 @@ class Db_obj : public api::Db_obj return *this; } - virtual ~Db_obj() {} + virtual ~Db_obj() NOEXCEPT {} virtual const string& get_name() const { return m_name; }; diff --git a/cdk/include/mysql/cdk/protocol/mysqlx/expr.h b/cdk/include/mysql/cdk/protocol/mysqlx/expr.h index cda39ee10..43c8cbdfa 100644 --- a/cdk/include/mysql/cdk/protocol/mysqlx/expr.h +++ b/cdk/include/mysql/cdk/protocol/mysqlx/expr.h @@ -244,7 +244,7 @@ class Doc_path DOUBLE_ASTERISK = 5, }; - virtual ~Doc_path() {} + virtual ~Doc_path() NOEXCEPT {} // The "$" path which denotes the whole document. virtual bool is_whole_document() const = 0; diff --git a/cdk/include/mysql/cdk/session.h b/cdk/include/mysql/cdk/session.h index 6bd5e237c..bde0c3f2e 100644 --- a/cdk/include/mysql/cdk/session.h +++ b/cdk/include/mysql/cdk/session.h @@ -78,7 +78,7 @@ class Session const ds::Unix_socket::Options &options = ds::Unix_socket::Options()); #endif //_WIN32 - ~Session(); + ~Session() NOEXCEPT; // Core Session operations. diff --git a/cdk/mysqlx/converters.h b/cdk/mysqlx/converters.h index 3d378aa40..0e61c1a99 100644 --- a/cdk/mysqlx/converters.h +++ b/cdk/mysqlx/converters.h @@ -243,7 +243,7 @@ struct Expr_prc_converter_base //using Base::reset; //using Base::m_proc; - virtual ~Expr_prc_converter_base() {} + virtual ~Expr_prc_converter_base() NOEXCEPT {} Scalar_prc_converter m_scalar_conv; Args_prc* get_args_converter(Args_prc_to*); diff --git a/cdk/mysqlx/result.cc b/cdk/mysqlx/result.cc index 474e0c0e7..11bab8468 100644 --- a/cdk/mysqlx/result.cc +++ b/cdk/mysqlx/result.cc @@ -552,9 +552,9 @@ Cursor::Cursor(const std::shared_ptr &reply) } -Cursor::~Cursor() +Cursor::~Cursor() NOEXCEPT { - close(); + try { close(); } catch (...) {} } diff --git a/cdk/mysqlx/session.cc b/cdk/mysqlx/session.cc index 414d01ea2..fd97f7a89 100644 --- a/cdk/mysqlx/session.cc +++ b/cdk/mysqlx/session.cc @@ -660,7 +660,7 @@ void Session::authenticate(const Options &options, bool secure_conn) } -Session::~Session() +Session::~Session() NOEXCEPT { //TODO: add timeout to close session! try @@ -668,10 +668,7 @@ Session::~Session() close(); } catch (...) - { - // Something went wrong - do not try to use this session again. - m_isvalid = false; - } + {} } diff --git a/cdk/mysqlx/stmt.h b/cdk/mysqlx/stmt.h index c4f7176a7..4b265ff12 100644 --- a/cdk/mysqlx/stmt.h +++ b/cdk/mysqlx/stmt.h @@ -125,10 +125,15 @@ class Expectation } - ~Expectation() + ~Expectation() NOEXCEPT { - Base::discard(); - Base::wait(); + try + { + Base::discard(); + Base::wait(); + } + catch (...) + {} } @@ -791,7 +796,7 @@ class Order_prc_converter public: - virtual ~Order_prc_converter() {} + virtual ~Order_prc_converter() NOEXCEPT {} Expr_prc* sort_key(Sort_direction::value dir) { @@ -855,7 +860,7 @@ class Cmd_Select {} - virtual ~Cmd_Select() + virtual ~Cmd_Select() NOEXCEPT {} @@ -989,7 +994,7 @@ class Table_proj_prc_converter public: - virtual ~Table_proj_prc_converter() {} + virtual ~Table_proj_prc_converter() NOEXCEPT {} }; @@ -1125,7 +1130,7 @@ struct String_to_col_prc_converter m_proc->name(col); } - virtual ~String_to_col_prc_converter() + virtual ~String_to_col_prc_converter() NOEXCEPT {} }; @@ -1290,7 +1295,7 @@ class Cmd_ViewCrud view.process(*this); } - ~Cmd_ViewCrud() + ~Cmd_ViewCrud() NOEXCEPT { delete m_find; } @@ -1379,7 +1384,7 @@ class Update_prc_converter bool m_has_schema; string m_schema_name; - virtual ~Table() {} + virtual ~Table() NOEXCEPT {} //DB_OBJ const string& get_name() const @@ -1396,7 +1401,7 @@ class Update_prc_converter public: - virtual ~Update_prc_converter() {} + virtual ~Update_prc_converter() NOEXCEPT {} void set_data_model(cdk::protocol::mysqlx::Data_model dm) { diff --git a/cdk/protocol/mysqlx/builders.h b/cdk/protocol/mysqlx/builders.h index 36f7b3b20..d6f303a9e 100644 --- a/cdk/protocol/mysqlx/builders.h +++ b/cdk/protocol/mysqlx/builders.h @@ -285,7 +285,7 @@ struct Builder_base m_args_conv = conv; } - virtual ~Builder_base() {} + virtual ~Builder_base() NOEXCEPT {} }; @@ -1148,7 +1148,7 @@ class Placeholder_conv_imp unsigned m_offset = 0; public: - virtual ~Placeholder_conv_imp() {} + virtual ~Placeholder_conv_imp() NOEXCEPT {} void clear() { diff --git a/cdk/protocol/mysqlx/crud.cc b/cdk/protocol/mysqlx/crud.cc index 30bb27103..b3171d97b 100644 --- a/cdk/protocol/mysqlx/crud.cc +++ b/cdk/protocol/mysqlx/crud.cc @@ -708,9 +708,8 @@ class Update_builder , m_conv(conv) {} - ~Update_builder() - { - } + ~Update_builder() NOEXCEPT + {} virtual void target_name(const string &name) { diff --git a/cdk/protocol/mysqlx/protocol.cc b/cdk/protocol/mysqlx/protocol.cc index e09e416cc..6c5994305 100644 --- a/cdk/protocol/mysqlx/protocol.cc +++ b/cdk/protocol/mysqlx/protocol.cc @@ -163,7 +163,7 @@ Protocol_impl::Protocol_impl(Protocol::Stream *str, Protocol_side side) } -Protocol_impl::~Protocol_impl() +Protocol_impl::~Protocol_impl() NOEXCEPT { free(m_rd_buf); free(m_wr_buf); diff --git a/cdk/protocol/mysqlx/protocol.h b/cdk/protocol/mysqlx/protocol.h index b22939946..cfdf9d653 100644 --- a/cdk/protocol/mysqlx/protocol.h +++ b/cdk/protocol/mysqlx/protocol.h @@ -162,7 +162,7 @@ class Protocol_impl : public Processor_base protected: Protocol_impl(Protocol::Stream*, Protocol_side); - virtual ~Protocol_impl(); + virtual ~Protocol_impl() NOEXCEPT; public: @@ -973,12 +973,14 @@ class Msg_builder } } - ~Msg_builder() + ~Msg_builder() NOEXCEPT { if (m_stmt_id != 0) + try { Prepare_traits::release(m_prepare); } + catch (...) {} } diff --git a/cdk/protocol/mysqlx/protocol_compression.cc b/cdk/protocol/mysqlx/protocol_compression.cc index 95f38a1f2..ae3f18df6 100644 --- a/cdk/protocol/mysqlx/protocol_compression.cc +++ b/cdk/protocol/mysqlx/protocol_compression.cc @@ -137,7 +137,7 @@ size_t Compression_zlib::uncompress(byte *dst, } -Compression_zlib::~Compression_zlib() +Compression_zlib::~Compression_zlib() NOEXCEPT { if (m_zlib_inited) { @@ -256,7 +256,7 @@ size_t Compression_lz4::uncompress(byte *dst, } -Compression_lz4::~Compression_lz4() +Compression_lz4::~Compression_lz4() NOEXCEPT { if (m_dctx) LZ4F_freeDecompressionContext(m_dctx); @@ -338,7 +338,7 @@ size_t Compression_zstd::uncompress(byte *dst, } -Compression_zstd::~Compression_zstd() +Compression_zstd::~Compression_zstd() NOEXCEPT { if (m_u_zstd) ZSTD_freeDStream(m_u_zstd); @@ -456,7 +456,7 @@ void Protocol_compression::set_compression_type } -Protocol_compression::~Protocol_compression() +Protocol_compression::~Protocol_compression() NOEXCEPT { if (m_c_out_buf) free(m_c_out_buf); diff --git a/cdk/protocol/mysqlx/protocol_compression.h b/cdk/protocol/mysqlx/protocol_compression.h index a61b0f005..3a0f03047 100644 --- a/cdk/protocol/mysqlx/protocol_compression.h +++ b/cdk/protocol/mysqlx/protocol_compression.h @@ -67,7 +67,7 @@ class Compression_algorithm size_t compressed_size, size_t &bytes_consumed) = 0; - virtual ~Compression_algorithm() {} + virtual ~Compression_algorithm() NOEXCEPT {} }; @@ -88,7 +88,7 @@ class Compression_zlib : public Compression_algorithm size_t compress(byte *src, size_t len) override; size_t uncompress(byte *dst, size_t dest_size, size_t compressed_size, size_t &bytes_consumed) override; - ~Compression_zlib(); + ~Compression_zlib() NOEXCEPT; }; @@ -109,7 +109,7 @@ class Compression_lz4 : public Compression_algorithm size_t compress(byte *src, size_t len) override; size_t uncompress(byte *dst, size_t dest_size, size_t compressed_size, size_t &bytes_consumed) override; - ~Compression_lz4(); + ~Compression_lz4() NOEXCEPT; }; @@ -129,7 +129,7 @@ class Compression_zstd : public Compression_algorithm size_t compress(byte *src, size_t len) override; size_t uncompress(byte *dst, size_t dest_size, size_t compressed_size, size_t &bytes_consumed) override; - ~Compression_zstd(); + ~Compression_zstd() NOEXCEPT; }; @@ -159,7 +159,7 @@ class Protocol_compression Protocol_compression(); - ~Protocol_compression(); + ~Protocol_compression() NOEXCEPT; /* Returns pointer to internal buffer for compressed input diff --git a/common/op_impl.h b/common/op_impl.h index 86a0bf281..0c1d0d66b 100644 --- a/common/op_impl.h +++ b/common/op_impl.h @@ -141,11 +141,15 @@ class Op_base virtual ~Op_base() override { - // Let's aquire lock so that any remaingin replies are consumed on ~Reply - // and this way avoid race conditions with Client::close() - auto lock = m_sess->lock(); - release_stmt_id(); - m_reply.reset(); + try { + // Let's aquire lock so that any remaingin replies are consumed on ~Reply + // and this way avoid race conditions with Client::close() + auto lock = m_sess->lock(); + release_stmt_id(); + m_reply.reset(); + } + catch (...) + {} } cdk::Session& get_cdk_session() diff --git a/devapi/impl.h b/devapi/impl.h index e1056fa25..351e6a55a 100644 --- a/devapi/impl.h +++ b/devapi/impl.h @@ -369,7 +369,7 @@ class DbDoc::Impl friend Value::Access; public: - virtual ~Impl(){} + virtual ~Impl() NOEXCEPT {} }; diff --git a/devapi/result.cc b/devapi/result.cc index 9bd8d0f26..ca940490c 100644 --- a/devapi/result.cc +++ b/devapi/result.cc @@ -488,7 +488,7 @@ Result_detail::Result_detail(Result_init &init) } -Result_detail::~Result_detail() +Result_detail::~Result_detail() NOEXCEPT { try { if (m_owns_impl) diff --git a/devapi/session.cc b/devapi/session.cc index 7e8bc75af..6bf853836 100644 --- a/devapi/session.cc +++ b/devapi/session.cc @@ -370,7 +370,7 @@ mysqlx::string Session_detail::get_default_schema_name() */ -Query_src::~Query_src() +Query_src::~Query_src() NOEXCEPT { delete m_res; } diff --git a/include/mysqlx/common.h b/include/mysqlx/common.h index a52429d45..ac97ea710 100644 --- a/include/mysqlx/common.h +++ b/include/mysqlx/common.h @@ -44,6 +44,8 @@ kept in the common/ folder, either as headers or source files. */ +#define NOEXCEPT noexcept + #include "common_constants.h" #include "common/api.h" #include "common/error.h" diff --git a/include/mysqlx/common/op_if.h b/include/mysqlx/common/op_if.h index b17cb7bad..685a43342 100644 --- a/include/mysqlx/common/op_if.h +++ b/include/mysqlx/common/op_if.h @@ -100,7 +100,7 @@ struct Executable_if virtual Executable_if *clone() const = 0; - virtual ~Executable_if() {} + virtual ~Executable_if() NOEXCEPT {} }; diff --git a/include/mysqlx/devapi/detail/result.h b/include/mysqlx/devapi/detail/result.h index ad64dc7b7..83be19583 100644 --- a/include/mysqlx/devapi/detail/result.h +++ b/include/mysqlx/devapi/detail/result.h @@ -94,7 +94,7 @@ class PUBLIC_API Result_detail Result_detail& operator=(Result_detail&&); Result_detail() = default; - virtual ~Result_detail(); + virtual ~Result_detail() NOEXCEPT; Impl& get_impl(); diff --git a/include/mysqlx/devapi/detail/session.h b/include/mysqlx/devapi/detail/session.h index cf4f6d426..b15087062 100644 --- a/include/mysqlx/devapi/detail/session.h +++ b/include/mysqlx/devapi/detail/session.h @@ -85,7 +85,7 @@ class PUBLIC_API Db_obj_base : m_sess(sess), m_name(name) {} - virtual ~Db_obj_base() + virtual ~Db_obj_base() NOEXCEPT {} }; @@ -144,7 +144,7 @@ struct PUBLIC_API Query_src Query_src(const Query_src&) = delete; - virtual ~Query_src(); + virtual ~Query_src() NOEXCEPT; virtual void iterator_start() { @@ -247,6 +247,9 @@ using SQL_statement_cmd = Executable; struct SQL_statement : public Bind_placeholders< SQL_statement_cmd > { + ~SQL_statement() NOEXCEPT + {} + SQL_statement(Session *sess, const string &query) { assert(sess); @@ -372,7 +375,7 @@ struct PUBLIC_API Session_detail Session_detail(common::Settings_impl&); Session_detail(common::Shared_session_pool&); - virtual ~Session_detail() + virtual ~Session_detail() NOEXCEPT { try { if (m_impl) diff --git a/include/mysqlx/devapi/executable.h b/include/mysqlx/devapi/executable.h index 22f7e763a..2d0fb0536 100644 --- a/include/mysqlx/devapi/executable.h +++ b/include/mysqlx/devapi/executable.h @@ -121,7 +121,7 @@ class Executable operator=(std::move(other)); } - virtual ~Executable() {} + virtual ~Executable() NOEXCEPT {} Executable& operator=(const Executable &other) From be5257a4fd99e78bce802357af370b4532371a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Thu, 12 Dec 2024 13:28:25 +0100 Subject: [PATCH 20/43] Bug#37096144 Errors shown when un-installing RPM packages See https://bugzilla.redhat.com/show_bug.cgi?id=1673912 --- packaging/mysql-connector-c++.spec.in | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packaging/mysql-connector-c++.spec.in b/packaging/mysql-connector-c++.spec.in index 71d79aedb..73c8b3880 100644 --- a/packaging/mysql-connector-c++.spec.in +++ b/packaging/mysql-connector-c++.spec.in @@ -215,11 +215,14 @@ mv -v %{buildroot}%{_libdir}/plugin/* %{buildroot}%{plugin_dir} rm -rf %{buildroot}%{_libdir}/{plugin,private} -%post -p /sbin/ldconfig +%post +/sbin/ldconfig -%postun -p /sbin/ldconfig +%postun +/sbin/ldconfig -%post jdbc -p /sbin/ldconfig +%post jdbc +/sbin/ldconfig %postun jdbc /sbin/ldconfig From 47cf0e9bc0f903aeb5db75d0c9d39f7ef361241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Thu, 12 Dec 2024 15:40:57 +0100 Subject: [PATCH 21/43] Bug#36795664 Upgrading with DNF/RPM from 8.4.0 fails due to conflict --- packaging/mysql-connector-c++.spec.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/mysql-connector-c++.spec.in b/packaging/mysql-connector-c++.spec.in index 73c8b3880..206d6ddaa 100644 --- a/packaging/mysql-connector-c++.spec.in +++ b/packaging/mysql-connector-c++.spec.in @@ -214,6 +214,8 @@ mkdir -p %{buildroot}%{plugin_dir} mv -v %{buildroot}%{_libdir}/plugin/* %{buildroot}%{plugin_dir} rm -rf %{buildroot}%{_libdir}/{plugin,private} +%pretrans devel +test -L /usr/include/mysql-cppconn && rm -f /usr/include/mysql-cppconn %post /sbin/ldconfig From 0881538e82dc34851267a18a3282d241884b03ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Thu, 12 Dec 2024 09:15:32 +0100 Subject: [PATCH 22/43] Bug#37179475 MSI installer should not install cmake configuration script in "Typical" profile --- buildinfo.cmake | 4 +-- packaging/WiX/connector-cpp.wxs.in | 45 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/buildinfo.cmake b/buildinfo.cmake index db73ce5bf..7a791671f 100644 --- a/buildinfo.cmake +++ b/buildinfo.cmake @@ -42,10 +42,10 @@ function(generate_cmake_config) ) install( - FILES + FILES "${CMAKE_BINARY_DIR}/mysql-concpp${suffix}.cmake" DESTINATION . - COMPONENT Readme + COMPONENT DevCommon ) endforeach() diff --git a/packaging/WiX/connector-cpp.wxs.in b/packaging/WiX/connector-cpp.wxs.in index fbb9fbaf4..9aa4ec2fc 100644 --- a/packaging/WiX/connector-cpp.wxs.in +++ b/packaging/WiX/connector-cpp.wxs.in @@ -115,8 +115,26 @@ - + + + + + + @@ -125,8 +143,10 @@ + + @@ -136,8 +156,10 @@ + + @@ -147,27 +169,6 @@ - - - - - - - - From 1630c83862239241fa9043671f86624564e8483b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Fri, 13 Dec 2024 12:38:30 +0100 Subject: [PATCH 23/43] packaging: Use cmake GUUID generator (no need for uuidgen utility) --- packaging/WiX/CMakeLists.txt | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/packaging/WiX/CMakeLists.txt b/packaging/WiX/CMakeLists.txt index 16e0b7ba6..ee7517a3d 100644 --- a/packaging/WiX/CMakeLists.txt +++ b/packaging/WiX/CMakeLists.txt @@ -514,33 +514,21 @@ function(make_wix_identifier STR VAR) set(${VAR} "${STR}.${out}" PARENT_SCOPE) endfunction() + # # Generate UUIDs # -find_program(UUIDGEN_COMMAND uuidgen) - -if(NOT UUIDGEN_COMMAND) - message(FATAL_ERROR "Could not find uuidgen executable") -endif() - function(generate_guid VAR) - EXECUTE_PROCESS( - COMMAND ${UUIDGEN_COMMAND} -c - RESULT_VARIABLE res - OUTPUT_VARIABLE guid - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if(res) - message(FATAL_ERROR "Could not generate UUID: ${res}") - endif() - + string(RANDOM x) + string(UUID guid NAMESPACE "96122528-4F58-40F8-AB22-96F9853460F8" NAME "${x}" TYPE MD5 UPPER) + # message(STATUS "generated guid: ${guid}") set(${VAR} ${guid} PARENT_SCOPE) endfunction() + # # Convert path into a list # From b20056f5015c9a7f86432a193f01c28d315cdd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Fri, 13 Dec 2024 13:43:38 +0100 Subject: [PATCH 24/43] doc: Fix wrong cmake command name `find_module()` --- doc/usage.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/usage.txt b/doc/usage.txt index 2f6d9cb58..cc331857b 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -6,7 +6,7 @@ uses Connector/C++ it is enough to link that target with the `mysql::concpp` target defined after loading the `mysql-concpp` module into the project, as in this example: ~~~~~~ - find_module(mysql-concpp REQUIRED) + find_package(mysql-concpp REQUIRED) add_executable(my-target ...) target_link_libraries(my-target mysql::concpp) @@ -14,14 +14,14 @@ in this example: This ensures correct compiler and linker flags when building `my-target` so that connector public headers, the libraries and their dependencies are found when compiling and linking the target. See the CMake documentation -for more information on `find_module()` command and on using CMake modules. +for more information on `find_package()` command and on using CMake modules. We focus here on the scenario where Connector/C++ is installed from a package published by MySQL. There are two variants of this scenario. Either the connector is installed system-wide via package manager such as RPM or DEB, or it is installed locally from TGZ or ZIP package. In case of system-wide installation connector components are installed to default locations and things -are expected to work out-of-the-box. In this case `find_module(mysql-concpp)` +are expected to work out-of-the-box. In this case `find_package(mysql-concpp)` command should work without any further configuration. In case of local installation you need to tell CMake where to look for @@ -29,7 +29,7 @@ the `mysql-concpp` module. This can be done by setting the `mysql-concpp_DIR` variable to the top-level Connector/C++ install location: ~~~~~~ set(mysql-concpp_DIR "/path/to/concpp/install") - find_module(mysql-concpp) + find_package(mysql-concpp) ~~~~~~ (Alternatively the variable can be set when invoking `cmake` using `-Dmysql-concpp_DIR=/path/to/concpp/install` option). @@ -193,7 +193,7 @@ When loading the `mysql-concpp` module a "debug" component can be required so that cmake will report error if debug variants of connector libraries are not found: ~~~~~~ - find_module(mysql-concpp REQUIRE debug) + find_package(mysql-concpp REQUIRE debug) ~~~~~~ Regardless of whether the "debug" component was required or not, the module will set variable `MYSQL_CONCPP_DEBUG_FOUND` to true if debug libraries were @@ -218,7 +218,7 @@ For example: find_package(mysql-concpp) ~~~~ Note that `mysql::openssl` target must be defined before invoking -`find_module(mysql-concpp)` in order to replace the default OpenSSL instance +`find_package(mysql-concpp)` in order to replace the default OpenSSL instance used by the module. From ab7a978b96ec946046473ee58abb6aa31a544251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 16 Dec 2024 08:41:48 +0100 Subject: [PATCH 25/43] Bug#36795664 Upgrading with DNF/RPM from 8.4.0 fails due to conflict -- post push fix The scriplet must always succeed --- packaging/mysql-connector-c++.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/mysql-connector-c++.spec.in b/packaging/mysql-connector-c++.spec.in index 206d6ddaa..c2bffc469 100644 --- a/packaging/mysql-connector-c++.spec.in +++ b/packaging/mysql-connector-c++.spec.in @@ -215,7 +215,7 @@ mv -v %{buildroot}%{_libdir}/plugin/* %{buildroot}%{plugin_dir} rm -rf %{buildroot}%{_libdir}/{plugin,private} %pretrans devel -test -L /usr/include/mysql-cppconn && rm -f /usr/include/mysql-cppconn +test -L /usr/include/mysql-cppconn && rm -f /usr/include/mysql-cppconn || true %post /sbin/ldconfig From cf828d47496452deab86683d032c2ef9dbd22112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 16 Dec 2024 13:39:21 +0100 Subject: [PATCH 26/43] Bug#37179475 MSI installer should not install cmake configuration script in "Typical" profile -- post push fix The new "DevCommon" component must be added to ZIP package specs. --- packaging/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index 55223d834..7a86eed8e 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -190,6 +190,7 @@ cpack_add_component_group(main) cpack_add_component_group(tests) cpack_add_component_group(debug) +cpack_add_component(DevCommon GROUP main) cpack_add_component(XDevAPIDev GROUP main) cpack_add_component(XDevAPIDll GROUP main) cpack_add_component(JDBCDev GROUP main) From 192c94992556d4e51986ee81e5c440e3626c2ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 16 Dec 2024 16:57:58 +0100 Subject: [PATCH 27/43] WL#16321: Let CMake configuration script handle debug-only installs -- post push fix Add handling of `jdbc` component; now that our package handles components. --- mysql-concpp-config.cmake.in | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/mysql-concpp-config.cmake.in b/mysql-concpp-config.cmake.in index 6592d2014..7e04f0221 100644 --- a/mysql-concpp-config.cmake.in +++ b/mysql-concpp-config.cmake.in @@ -46,8 +46,9 @@ # Also, the following variables are set: # # - Xxx_FOUND -# - Xxx_DEBUG_FOUND, Xxx_debug_FOUND -- (1) -# - Xxx_RELEASE_FOUND, Xxx_release_FOUND -- (1) +# - Xxx_JDBC_FOUND, Xxx_jdbc_FOUND -- (1a) +# - Xxx_DEBUG_FOUND, Xxx_debug_FOUND -- (1b) +# - Xxx_RELEASE_FOUND, Xxx_release_FOUND -- (1b) # - Xxx_VERSION, Xxx_VERSION_CC # - Xxx_ROOT_DIR -- (2) # - Xxx_RUNTIME_LIBRARY_DIRS, Xxx_RUNTIME_LIBRARY_DIR -- (2,3) @@ -58,7 +59,11 @@ # In these variable names Xxx is either `MYSQL_CONCPP` or `mysql-concpp`, # CC is version component: one of `MAJOR`, `MINOR` or `PATCH`. # -# Note (1): These are set to true if debug/release libraries are available +# Note (1a): Set to true if the classic JDBC connector libraries were found and +# the -jdbc targets are defined. It must be the case if `REQUIRE jdbc` clause +# was used in the cmake `find_package()` command. +# +# Note (1b): These are set to true if debug/release libraries are available # (see below). # # Note (2): Set only in case of a monolithic install (TGZ, ZIP, MSI). @@ -357,7 +362,11 @@ macro(main) add_library(mysql::concpp${suffix} ALIAS mysql::concpp-xdevapi${suffix}) endif() - endforeach() + if(TARGET mysql::concpp-jdbc${suffix}) + set(MYSQL_CONCPP_JDBC_FOUND 1) + endif() + +endforeach() # Build the NOT_FOUND message. @@ -388,6 +397,7 @@ macro(main) # Note: The _FOUND variable name expected by FPHSA for component CCC # is mysql-concpp_CCC_FOUND + set(mysql-concpp_jdbc_FOUND ${MYSQL_CONCPP_JDBC_FOUND}) set(mysql-concpp_debug_FOUND ${MYSQL_CONCPP_DEBUG_FOUND}) set(mysql-concpp_release_FOUND ${MYSQL_CONCPP_RELEASE_FOUND}) @@ -403,6 +413,7 @@ macro(main) # Set alternative variables + set(MYSQL_CONCPP_jdbc_FOUND ${MYSQL_CONCPP_JDBC_FOUND}) set(MYSQL_CONCPP_debug_FOUND ${MYSQL_CONCPP_DEBUG_FOUND}) set(MYSQL_CONCPP_release_FOUND ${MYSQL_CONCPP_RELEASE_FOUND}) @@ -412,6 +423,7 @@ macro(main) RUNTIME_LIBRARY_DIR_DEBUG RUNTIME_LIBRARY_DIRS_DEBUG RUNTIME_LIBRARY_DIR_RELEASE RUNTIME_LIBRARY_DIRS_RELEASE DEBUG_FOUND debug_FOUND RELEASE_FOUND release_FOUND + JDBC_FOUND jdbc_FOUND ) if(NOT DEFINED MYSQL_CONCPP_${var}) From edb2876d936492132c1fe881ae69017bc12eb002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Tue, 17 Dec 2024 08:57:15 +0100 Subject: [PATCH 28/43] packaging: Update compat.patch --- packaging/compat.patch | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packaging/compat.patch b/packaging/compat.patch index 03583b884..be2cdc0bd 100644 --- a/packaging/compat.patch +++ b/packaging/compat.patch @@ -32,8 +32,21 @@ index 8b960402..37fac11d 100644 # # Set higher warning level for the main connector code. +diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg +index 7bf32bcf..870d6ada 100644 +--- a/doc/doxygen.cfg ++++ b/doc/doxygen.cfg +@@ -66,7 +66,7 @@ PROJECT_NAME = "MySQL Connector/C++" + # could be handy for archiving the generated documentation or if some version + # control system is used. + +-PROJECT_NUMBER = 8.0.23 ++PROJECT_NUMBER = 9.2.0 + + # Using the PROJECT_BRIEF tag one can provide an optional one line description + # for a project that appears at the top of each page and should give viewer a diff --git a/version.cmake b/version.cmake -index 53f8f540..4d32f5ee 100644 +index 53f8f540..54bc21b2 100644 --- a/version.cmake +++ b/version.cmake @@ -34,8 +34,8 @@ set(COPYRIGHT_YEAR "2024" CACHE INTERNAL "version info") @@ -43,7 +56,7 @@ index 53f8f540..4d32f5ee 100644 -set(CONCPP_VERSION_MAJOR 8 CACHE INTERNAL "version info") -set(CONCPP_VERSION_MINOR 4 CACHE INTERNAL "version info") +set(CONCPP_VERSION_MAJOR 9 CACHE INTERNAL "version info") -+set(CONCPP_VERSION_MINOR 1 CACHE INTERNAL "version info") ++set(CONCPP_VERSION_MINOR 2 CACHE INTERNAL "version info") set(CONCPP_VERSION_MICRO 0 CACHE INTERNAL "version info") # Level is "-alpha", "-beta", empty if GA set(CONCPP_VERSION_LEVEL "" CACHE INTERNAL "version info") From c97b2467c374dd7d9b3914fdb6033eca9f69c888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Tue, 17 Dec 2024 09:35:55 +0100 Subject: [PATCH 29/43] Update copytight year used for binary files version information (on Windows) --- version.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cmake b/version.cmake index 2ec78a02e..1e24bb325 100644 --- a/version.cmake +++ b/version.cmake @@ -28,7 +28,7 @@ # Note: To be used in copyright notes of generated files -set(COPYRIGHT_YEAR "2024" CACHE INTERNAL "version info") +set(COPYRIGHT_YEAR "2025" CACHE INTERNAL "version info") # # Connector/C++ version From 9eee70277bfc536e8a7616f13188ea1a905e6cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Wed, 18 Dec 2024 12:08:45 +0100 Subject: [PATCH 30/43] WL#16601: -Werror builds --- CMakeLists.txt | 43 +++++++++++++++++++++++++++++-- cdk/cmake/dependency.cmake | 3 ++- cdk/extra/lz4/CMakeLists.txt | 4 +++ cdk/extra/protobuf/CMakeLists.txt | 4 +++ cdk/extra/zlib/CMakeLists.txt | 3 +++ cdk/extra/zstd/CMakeLists.txt | 4 +++ 6 files changed, 58 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e87a67076..bfb1a5535 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,11 +271,35 @@ endif() # TODO: Fix these warnings. # +# TODO: Also cover linker warnings + +add_config_option(WERROR BOOL ADVANCED DEFAULT OFF + "Turn compile warnings into errors" +) + +# +# Note: If WERROR is enabled we change its value to be the actual compiler +# option to be used on the current platform. That is used for easier +# propagation to external builds. +# +# Note: In more recent cmake there is CMAKE_COMPILE_WARNING_AS_ERROR variable +# but at the moment we can't ensure using that recent cmake. +# + +if(WERROR) + set(WERROR -Werror) +endif() + if(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) if(CXX_FRONTEND_MSVC) + + if(WERROR) + set(WERROR /WX) # MSVC equivalent of -Werror + endif() + # Disable MSVC unreachable code warnings unless requested. add_compile_options(/wd4702) @@ -283,12 +307,14 @@ if(MSVC) # Seehttps://connect.microsoft.com/VisualStudio/feedback/details/897611/incorrect-warning-of-c4297-for-destructor-with-try-catch-statement add_compile_options(/wd4297) + endif() -endif() +elseif(SUNPRO) + # Note: For simplicity we do not handle WERROR on SunOS -if(SUNPRO) + set(WERROR) add_compile_options( -errtags=yes -erroff=hidevf,wvarhidemem @@ -296,6 +322,19 @@ if(SUNPRO) endif() +if(NOT WERROR) + # clear if WERROR was set to something like OFF or FALSE + # message(STATUS "WERROR: cleared") + unset(WERROR CACHE) +else() + # overwrite cache entry with changed value + set(WERROR "${WERROR}" CACHE INTERNAL "WERROR flags" FORCE) +endif() + +# message(STATUS "WERROR: ${WERROR}") +add_compile_options(${WERROR}) + + if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0) # Silence a warning produced by a regression in GCC 12.0 and newer # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106199 diff --git a/cdk/cmake/dependency.cmake b/cdk/cmake/dependency.cmake index e3fec4ee2..1f4410329 100644 --- a/cdk/cmake/dependency.cmake +++ b/cdk/cmake/dependency.cmake @@ -60,6 +60,7 @@ set(EXT_FWD CMAKE_SYSTEM_PROCESSOR CMAKE_C_COMPILER CMAKE_CXX_COMPILER MSVC + WERROR ) set(EXT_DIR ${CMAKE_CURRENT_LIST_DIR}/ext CACHE INTERNAL "external project utils location") @@ -129,7 +130,7 @@ function(add_ext NAME HEADER) "${EXT_LIB} library name" ) - + #show_config_options() # Handle non-path value of WITH_X option diff --git a/cdk/extra/lz4/CMakeLists.txt b/cdk/extra/lz4/CMakeLists.txt index 7e5db8567..ebcf76173 100644 --- a/cdk/extra/lz4/CMakeLists.txt +++ b/cdk/extra/lz4/CMakeLists.txt @@ -34,6 +34,10 @@ include(platform) enable_pic() +if(WERROR) + add_compile_options(${WERROR}) +endif() + add_library(lz4 STATIC lib/lz4.c lib/lz4frame.c diff --git a/cdk/extra/protobuf/CMakeLists.txt b/cdk/extra/protobuf/CMakeLists.txt index adc19f55d..b2e72d863 100644 --- a/cdk/extra/protobuf/CMakeLists.txt +++ b/cdk/extra/protobuf/CMakeLists.txt @@ -73,6 +73,10 @@ SET(PROTO_SRC_DIR "${PROJECT_SOURCE_DIR}/protobuf-3.19.6") enable_pic() enable_cxx17() +if(WERROR) + add_compile_options(${WERROR}) +endif() + # -O3 using GCC on SPARC leds to segfault on protoc if(SPARC AND GCC) foreach(LANG C CXX) diff --git a/cdk/extra/zlib/CMakeLists.txt b/cdk/extra/zlib/CMakeLists.txt index b3ebd214d..a5c43c952 100644 --- a/cdk/extra/zlib/CMakeLists.txt +++ b/cdk/extra/zlib/CMakeLists.txt @@ -9,6 +9,9 @@ set(VERSION "1.3.1") project(zlib VERSION ${VERSION} LANGUAGES C) option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON) +if(WERROR) + add_compile_options(${WERROR}) +endif() IF(DISABLE_THESE_LINES) set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") diff --git a/cdk/extra/zstd/CMakeLists.txt b/cdk/extra/zstd/CMakeLists.txt index 0ed58f630..bf3e174ff 100644 --- a/cdk/extra/zstd/CMakeLists.txt +++ b/cdk/extra/zstd/CMakeLists.txt @@ -15,6 +15,10 @@ include(platform) enable_pic() +if(WERROR) + add_compile_options(${WERROR}) +endif() + SET(ZSTD_LIB_DIR "${PROJECT_SOURCE_DIR}/lib") From eb8aa607de22c26813ccee878717106cb5d51334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Tue, 7 Jan 2025 10:38:31 +0100 Subject: [PATCH 31/43] testapp: Make WITH_SSL option support using bundled OpenSSL libraries. If OpenSSL libraries are bundled with connector install then passing config option WITH_SSL=bundled will use these libraries to buld test application (if needed). Also, WITH_SSL can now point directly at OpenSSL library location rather than at the top-level OpenSSL install location. --- testapp/CMakeLists.txt | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/testapp/CMakeLists.txt b/testapp/CMakeLists.txt index ef6f691cd..d70939162 100644 --- a/testapp/CMakeLists.txt +++ b/testapp/CMakeLists.txt @@ -60,14 +60,42 @@ PROJECT(MySQL_CONCPP_TEST) # ======================================================================== # Dependencies +function(find_openssl where) + + if(where STREQUAL "bundled") + if(mysql-concpp_DIR) + set(WITH_SSL "${mysql-concpp_DIR}") + else() + message(WARNING + "A request to use bundled OpenSSL libraries was made but" + " Connector/C++ install location was not explicitly given" + " via mysql-concpp_DIR or WITH_CONCPP setting." + ) + return() + endif() + endif() -if(WITH_SSL) + find_library(openssl + NAMES ssl + PATHS "${WITH_SSL}" + PATH_SUFFIXES "" "lib" "lib64" + NO_DEFAULT_PATH + NO_CACHE + ) + + if(NOT openssl) + message(WARNING + "OpenSSL libraries not found at specified location: ${WITH_SSL}" + ) + return() + endif() + get_filename_component(WITH_SSL "${openssl}" DIRECTORY CACHE) message(STATUS "Using custom OpenSSL libraries at: ${WITH_SSL}") add_library(openssl INTERFACE) # TODO: Is this path correct also on non-Win platforms? - target_link_directories(openssl INTERFACE "${WITH_SSL}/lib") + target_link_directories(openssl INTERFACE "${WITH_SSL}") if(WIN32) set(ssl_libs libssl libcrypto) @@ -78,12 +106,16 @@ if(WITH_SSL) target_link_libraries(openssl INTERFACE ${ssl_libs}) add_library(mysql::openssl ALIAS openssl) -endif() +endfunction() + if(NOT DEFINED mysql-concpp_DIR AND DEFINED WITH_CONCPP) set(mysql-concpp_DIR "${WITH_CONCPP}") endif() +if(WITH_SSL) + find_openssl("${WITH_SSL}") +endif() find_package(mysql-concpp REQUIRED ${REQUIRED_COMPONENTS}) From 2aafdf7ffaef054833b52469942214805678cb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Fri, 10 Jan 2025 16:04:49 +0100 Subject: [PATCH 32/43] Fix dependency of the classic JDBC coneector on the MySQL client library or its dependencies Note: This change also ensures that the openSSL library bundled with the server is used (if available) not the one that was found and used for building the XDevAPI connector. --- jdbc/CMakeLists.txt | 23 +++++------------------ jdbc/cmake/DepFindMySQL.cmake | 6 +++--- jdbc/test/CMakeLists.txt | 3 --- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/jdbc/CMakeLists.txt b/jdbc/CMakeLists.txt index 60e36e42d..854764808 100644 --- a/jdbc/CMakeLists.txt +++ b/jdbc/CMakeLists.txt @@ -266,25 +266,12 @@ add_version_info(connector-jdbc "Implements MySQL Connector/C++ legacy JDBC API." ) +# Note: The MySQL::client target works (and is needed) both when linking +# to the MySQL client library dynamically and statically. In the latter case +# it brings additional linker options that are required (e.g. to resolve +# dependencies of the client library code). - -# Note: When connector links statically to the client library, targets using -# the connector must be able to find dependencies of the client library, such -# as openssl libs. The MYSQL_EXTERNAL_SEARCHPATH variable set by DepFindMySQL. -# cmake stores detected locations where client library dependencies that -# are bundled with it can be found. We add it here as interface property -# so that other targets that link with the connector will have library search -# path correctly set in the compile line. -# -# TODO: Modify merge_libraries() logic to autmatically detect transitive link -# directory path properties of merged targets and then set them on the merged -# library target. - -if(MYSQLCLIENT_STATIC_LINKING) - target_link_directories(connector-jdbc INTERFACE - ${MYSQL_EXTERNAL_SEARCHPATH} - ) -endif() +target_link_libraries(connector-jdbc PUBLIC MySQL::client) # diff --git a/jdbc/cmake/DepFindMySQL.cmake b/jdbc/cmake/DepFindMySQL.cmake index 971bfd58c..c94b770cd 100644 --- a/jdbc/cmake/DepFindMySQL.cmake +++ b/jdbc/cmake/DepFindMySQL.cmake @@ -297,7 +297,6 @@ function(main) if(MYSQL_LIB_STATIC) target_link_libraries(mysql-client-if INTERFACE MySQL::client-static) - target_link_libraries(mysql-client-if INTERFACE OpenSSL::SSL) else() target_link_libraries(mysql-client-if INTERFACE MySQL::client-shared) endif() @@ -379,7 +378,7 @@ function(main) # # If external dependencies were found, add them to the static target - # as any code that liks to static library should also link with the + # as any code that links to static library should also link with the # external dependencies. # @@ -531,7 +530,8 @@ function(use_mysql_config) # option. if(NOT lib MATCHES - "(mysqlclient|libmysql|^stdc|^gcc|^CrunG3|^c$|^statomic|^ssl|^crypto)" + "(mysqlclient|libmysql|^stdc|^gcc|^CrunG3|^c$|^statomic)" + #|^ssl|^crypto)" ) list(APPEND MYSQL_EXTERNAL_DEPENDENCIES ${lib}) diff --git a/jdbc/test/CMakeLists.txt b/jdbc/test/CMakeLists.txt index a35b906fc..c8259b973 100644 --- a/jdbc/test/CMakeLists.txt +++ b/jdbc/test/CMakeLists.txt @@ -79,9 +79,6 @@ IF(MSBUILD) ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS") ENDIF() -if(NOT MYSQLCLIENT_STATIC_LINKING) - list(APPEND MY_TARGET_LINK_LIBRARIES MySQL::client) -endif() IF(CMAKE_COMPILER_IS_GNUCC AND MYSQLCPPCONN_GCOV_ENABLE) SET(MY_GCOV_LINK_LIBRARIES gcov) From 5b1aa873bca82f38409bd222d580c639f2b0a7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 13 Jan 2025 11:01:34 +0100 Subject: [PATCH 33/43] cmake: Fix finding of bundled openSSL library in package configuration script --- mysql-concpp-config.cmake.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-concpp-config.cmake.in b/mysql-concpp-config.cmake.in index 7e04f0221..772410bdd 100644 --- a/mysql-concpp-config.cmake.in +++ b/mysql-concpp-config.cmake.in @@ -918,7 +918,7 @@ function(find_deps) unset(ssl_lib CACHE) find_library(ssl_lib NAMES ssl libssl - PATHS ${LIB_PATH} + PATHS ${LIBRARY_DIR} PATH_SUFFIXES private ${vs_suffix} NO_DEFAULT_PATH NO_CACHE @@ -927,7 +927,7 @@ function(find_deps) unset(ssl_crypto CACHE) find_library(ssl_crypto NAMES crypto libcrypto - PATHS ${LIB_PATH} + PATHS ${LIBRARY_DIR} PATH_SUFFIXES private ${vs_suffix} NO_DEFAULT_PATH NO_CACHE From 57d570a940735d351a90d89d47be6eaf79708adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Fri, 7 Mar 2025 12:54:46 +0100 Subject: [PATCH 34/43] WL#11226: Clear all compile warnings --- CMakeLists.txt | 5 +++-- cdk/CMakeLists.txt | 2 +- cdk/cmake/DepFindProtobuf.cmake | 2 +- cdk/cmake/compiler/MSVC.cmake | 10 ++++++++++ cdk/cmake/gtest.cmake | 11 ++++++++--- cdk/cmake/testing.cmake | 11 +++-------- cdk/extra/protobuf/CMakeLists.txt | 14 ++++++++++++-- cdk/extra/zlib/CMakeLists.txt | 25 ++++++++++++++++++++++--- cdk/extra/zstd/CMakeLists.txt | 6 ++++++ cdk/mysqlx/CMakeLists.txt | 8 -------- common/tests/CMakeLists.txt | 8 -------- devapi/tests/CMakeLists.txt | 7 ------- include/mysqlx/common_constants.h | 2 +- include/mysqlx/devapi/document.h | 3 +++ include/mysqlx/devapi/result.h | 3 +++ jdbc/cppconn/callback.h | 4 ++++ jdbc/extra/otel/CMakeLists.txt | 8 ++++++++ testing/CMakeLists.txt | 18 +++--------------- xapi/tests/CMakeLists.txt | 6 ------ xapi/tests/xapi-t.cc | 9 +++++---- xapi/tests/xapi_crud-t.cc | 2 +- 21 files changed, 94 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bfb1a5535..180498a39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -335,7 +335,7 @@ endif() add_compile_options(${WERROR}) -if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0) +if (GCC AND GCC VERSION_GREATER 11) # Silence a warning produced by a regression in GCC 12.0 and newer # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106199 # Note: The stringop-overflow warnings are shown also during linking phase @@ -422,7 +422,8 @@ if(MAINTAINER_MODE) # (and this is the case for MSVC 2015). # See: http://en.cppreference.com/w/cpp/language/copy_assignment - add_compile_options(/W4 /wd4512 /wd4127) + set_warnings_level(4) + add_compile_options(/wd4512 /wd4127) elseif(SUNPRO) else() diff --git a/cdk/CMakeLists.txt b/cdk/CMakeLists.txt index dc8e3adc6..ca524c022 100644 --- a/cdk/CMakeLists.txt +++ b/cdk/CMakeLists.txt @@ -150,7 +150,7 @@ IF(MSVC) # TODO: move to /Wall when code base is ready for this - add_compile_options(/W4) + set_warnings_level(4) # Note: We disable warnings related to C++11 language because we want this # to be pure C++ code. diff --git a/cdk/cmake/DepFindProtobuf.cmake b/cdk/cmake/DepFindProtobuf.cmake index 1fc785e31..6e020fc87 100644 --- a/cdk/cmake/DepFindProtobuf.cmake +++ b/cdk/cmake/DepFindProtobuf.cmake @@ -115,7 +115,7 @@ function(mysqlx_protobuf_generate_cpp SRCS HDRS) ELSEIF(MSVC) set_source_files_properties(${srcs} APPEND_STRING PROPERTY COMPILE_FLAGS - "/W1 /wd4018 /wd4996 /wd4244 /wd4267" + "/wd4018 /wd4996 /wd4244 /wd4267" ) ENDIF() diff --git a/cdk/cmake/compiler/MSVC.cmake b/cdk/cmake/compiler/MSVC.cmake index 5a6d3d80d..71e8e10c6 100644 --- a/cdk/cmake/compiler/MSVC.cmake +++ b/cdk/cmake/compiler/MSVC.cmake @@ -89,6 +89,16 @@ function(set_visibility) endfunction() +function(set_warnings_level N) + + # Note: The /Wn flag must be set only once, otherwise msvc shows warnings + + string(REGEX REPLACE "/W[123456789]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W${N}") + +endfunction() + + function(set_msvcrt TYPE) if(TYPE MATCHES "^(STATIC|Static|static)$") diff --git a/cdk/cmake/gtest.cmake b/cdk/cmake/gtest.cmake index 3a79ad3a3..3e53ba29a 100644 --- a/cdk/cmake/gtest.cmake +++ b/cdk/cmake/gtest.cmake @@ -32,9 +32,6 @@ # Set up gtest for use by targets in given folder and its sub-folders. # MACRO(SETUP_GTEST) - IF (WITH_GTEST) - INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS}) - ENDIF (WITH_GTEST) ENDMACRO(SETUP_GTEST) @@ -135,6 +132,14 @@ MESSAGE("gtest_main location: ${gtest_main_location}") add_library(gtest STATIC IMPORTED) add_library(gtest_main STATIC IMPORTED) +target_include_directories(gtest INTERFACE ${GTEST_INCLUDE_DIRS}) + +# See: https://stackoverflow.com/questions/42847103/stdtr1-with-visual-studio-2017 + +target_compile_definitions(gtest INTERFACE + -DGTEST_LANG_CXX11=1 +) + set_target_properties(gtest PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" IMPORTED_LOCATION "${gtest_location}" diff --git a/cdk/cmake/testing.cmake b/cdk/cmake/testing.cmake index bfdc8d92c..662fba98d 100644 --- a/cdk/cmake/testing.cmake +++ b/cdk/cmake/testing.cmake @@ -144,6 +144,7 @@ IF(WITH_TESTS) set_global(test_tests ${test_tests}) add_library(${TEST} OBJECT ${ARGN}) + target_link_libraries(${TEST} gtest) set_target_properties(${TEST} PROPERTIES FOLDER "Tests") target_include_directories(${TEST} PRIVATE ${test_includes}) @@ -153,12 +154,11 @@ IF(WITH_TESTS) if (MSVC) target_compile_definitions(${TEST} PRIVATE + -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING ) target_compile_options(${TEST} PRIVATE - /W3 /wd4244 /wd4267 /wd4701 @@ -166,8 +166,6 @@ IF(WITH_TESTS) /wd4456 # declaration of hides previous local declaration ) - target_compile_options(${TEST} PUBLIC /std:c++14) - if(STATIC_TESTS_MSVCRT) target_compile_options(${TEST} PRIVATE $<$:/MTd> @@ -295,10 +293,7 @@ IF(WITH_TESTS) if (MSVC) - target_compile_definitions(${target_run_unit_tests} PRIVATE - -D_SCL_SECURE_NO_WARNINGS - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) + set_warnings_level(3) target_compile_options(${target_run_unit_tests} PRIVATE /wd4244 diff --git a/cdk/extra/protobuf/CMakeLists.txt b/cdk/extra/protobuf/CMakeLists.txt index b2e72d863..19ae299ff 100644 --- a/cdk/extra/protobuf/CMakeLists.txt +++ b/cdk/extra/protobuf/CMakeLists.txt @@ -94,8 +94,18 @@ endif() set_visibility(hidden) -if(NOT TOOLSET_MSVC AND NOT APPLE) - add_compile_options(-Wno-stringop-overflow -Wno-stringop-overread) +if(GCC AND GCC VERSION_GREATER 11) + # See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106199 + add_compile_options(-Wno-stringop-overflow) + add_compile_options(-Wno-stringop-overread) +endif() + +if(NOT MSVC OR CLANG) + add_compile_options(-Wno-unused-const-variable) +endif() + +if(WIN32) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS) endif() if(APPLE) diff --git a/cdk/extra/zlib/CMakeLists.txt b/cdk/extra/zlib/CMakeLists.txt index a5c43c952..2c6928d25 100644 --- a/cdk/extra/zlib/CMakeLists.txt +++ b/cdk/extra/zlib/CMakeLists.txt @@ -7,12 +7,33 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) set(VERSION "1.3.1") project(zlib VERSION ${VERSION} LANGUAGES C) +include(../setup.cmake) +include(platform) + +enable_pic() -option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON) if(WERROR) add_compile_options(${WERROR}) endif() +if(WIN32) + + add_compile_definitions(_CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS) + + # warning triggered by one of the sources: + # The POSIX name for this item is deprecated. Instead, use the ISO C and C++ + # conformant name: _open. See online help for details. + + if(CLANG) + add_compile_options(-Wno-deprecated-declarations) + else() + add_compile_options(/wd4996) + endif() + +endif() + +option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" OFF) + IF(DISABLE_THESE_LINES) set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") @@ -151,8 +172,6 @@ file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) -add_compile_options(-fPIC) - add_library(zlib STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) target_include_directories(zlib PUBLIC diff --git a/cdk/extra/zstd/CMakeLists.txt b/cdk/extra/zstd/CMakeLists.txt index bf3e174ff..28015efef 100644 --- a/cdk/extra/zstd/CMakeLists.txt +++ b/cdk/extra/zstd/CMakeLists.txt @@ -19,6 +19,12 @@ if(WERROR) add_compile_options(${WERROR}) endif() +if(WIN32 AND CLANG) + # This warning shows only when building with clang on Win (clang 18): + # lib\compress\huf_compress.c(519,16): error : unused function 'HUF_isSorted' + add_compile_options(-Wno-unused-function) +endif() + SET(ZSTD_LIB_DIR "${PROJECT_SOURCE_DIR}/lib") diff --git a/cdk/mysqlx/CMakeLists.txt b/cdk/mysqlx/CMakeLists.txt index aa358f039..871740b82 100644 --- a/cdk/mysqlx/CMakeLists.txt +++ b/cdk/mysqlx/CMakeLists.txt @@ -31,14 +31,6 @@ ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN -DNOGDI) ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DSIZEOF_LONG=${SIZEOF_LONG} -DSIZEOF_LONG_LONG=${SIZEOF_LONG_LONG}) -# TODO: Fix compile warnings in auth_mysql41.cc - -if(MSVC) - set_property(SOURCE auth_hash.cc - PROPERTY COMPILE_FLAGS "/W3" - ) -endif() - file(GLOB HEADERS *.h) ADD_LIBRARY(cdk_mysqlx STATIC diff --git a/common/tests/CMakeLists.txt b/common/tests/CMakeLists.txt index a70e13164..aac020043 100644 --- a/common/tests/CMakeLists.txt +++ b/common/tests/CMakeLists.txt @@ -36,14 +36,6 @@ set_property( PROPERTY COMPILE_DEFINITIONS "" ) -if(WIN32) - add_definitions( - -D_CRT_SECURE_NO_WARNINGS - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - -endif() - #Add cdk includes because we are using their source tests add_test_includes(${PROJECT_SOURCE_DIR}/cdk/include) add_test_includes(${PROJECT_SOURCE_DIR}/cdk/extra/rapidjson/include) diff --git a/devapi/tests/CMakeLists.txt b/devapi/tests/CMakeLists.txt index 6c71501d4..d1201867f 100644 --- a/devapi/tests/CMakeLists.txt +++ b/devapi/tests/CMakeLists.txt @@ -38,13 +38,6 @@ set_property( PROPERTY COMPILE_DEFINITIONS "" ) -if(WIN32) - add_definitions( - -D_CRT_SECURE_NO_WARNINGS - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - -endif() # # If linking with connector statically, define macro that indicates this diff --git a/include/mysqlx/common_constants.h b/include/mysqlx/common_constants.h index 1ae1c48fd..34cc567f8 100644 --- a/include/mysqlx/common_constants.h +++ b/include/mysqlx/common_constants.h @@ -31,7 +31,7 @@ #ifndef MYSQL_COMMON_CONSTANTS_H #define MYSQL_COMMON_CONSTANTS_H -#include "version_info.h" +#include #define DEFAULT_MYSQL_PORT 3306 #define DEFAULT_MYSQLX_PORT 33060 diff --git a/include/mysqlx/devapi/document.h b/include/mysqlx/devapi/document.h index 442dab71c..3f84697ed 100644 --- a/include/mysqlx/devapi/document.h +++ b/include/mysqlx/devapi/document.h @@ -172,6 +172,8 @@ DLL_WARNINGS_POP virtual Iterator begin(); virtual Iterator end(); + virtual ~DbDoc() {} + friend Impl; friend DocResult; friend Value; @@ -360,6 +362,7 @@ class Value CATCH_AND_WRAP } + virtual ~Value() {} public: diff --git a/include/mysqlx/devapi/result.h b/include/mysqlx/devapi/result.h index 3c9e4f971..904636e74 100644 --- a/include/mysqlx/devapi/result.h +++ b/include/mysqlx/devapi/result.h @@ -484,6 +484,9 @@ class Column public: + virtual ~Column() + {} + friend RowResult; struct INTERNAL Access; friend Access; diff --git a/jdbc/cppconn/callback.h b/jdbc/cppconn/callback.h index af555326b..0ff7f3aa1 100644 --- a/jdbc/cppconn/callback.h +++ b/jdbc/cppconn/callback.h @@ -133,6 +133,8 @@ class WebAuthn_Callback ActionRequested(msg); } + virtual ~WebAuthn_Callback() {} + }; @@ -188,6 +190,8 @@ class Fido_Callback FidoActionRequested(msg); } + virtual ~Fido_Callback() {} + friend class mysql::MySQL_Connection; friend class mysql::MySQL_Driver; }; diff --git a/jdbc/extra/otel/CMakeLists.txt b/jdbc/extra/otel/CMakeLists.txt index bbed9bdf4..0d3708fa7 100644 --- a/jdbc/extra/otel/CMakeLists.txt +++ b/jdbc/extra/otel/CMakeLists.txt @@ -19,6 +19,14 @@ if(NOT (WIN32 OR APPLE OR CMAKE_SYSTEM_NAME MATCHES "SunOS")) if(WIN32) # Note: warning C4996 is triggered by OTel headers (as of version 1.10.0) target_compile_definitions(otel_api INTERFACE _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING) + + else() + + # Note: warning triggered by OTel headers reported by clang 18: + # builtin __has_trivial_copy is deprecated; use __is_trivially_copyable instead + + target_compile_options(otel_api INTERFACE -Wno-deprecated-builtins) + endif() endif() diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index 73c901b69..b8d76e616 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -49,25 +49,13 @@ endif() add_library(test_harness STATIC test_harness.cc) set_target_properties(test_harness PROPERTIES FOLDER "Tests") +target_link_libraries(test_harness PUBLIC gtest) + add_test_libraries(test_harness connector) add_test_includes(${CMAKE_CURRENT_SOURCE_DIR}) -if(MSVC) - - set(TEST_COMPILE_FLAGS - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - -D_CRT_SECURE_NO_WARNINGS - -D_SCL_SECURE_NO_WARNINGS - ) - - target_compile_definitions(test_harness PUBLIC - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) - - target_compile_options(test_harness PUBLIC /std:c++14) - -else() +if(NOT MSVC) set(TEST_COMPILE_FLAGS -Wno-sign-compare diff --git a/xapi/tests/CMakeLists.txt b/xapi/tests/CMakeLists.txt index 1beda2812..5b1220455 100644 --- a/xapi/tests/CMakeLists.txt +++ b/xapi/tests/CMakeLists.txt @@ -36,12 +36,6 @@ set_property( PROPERTY COMPILE_DEFINITIONS "" ) -IF(WIN32) - add_definitions( - -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING - ) -ENDIF() - if(BUILD_STATIC) add_definitions(-DSTATIC_CONCPP) endif() diff --git a/xapi/tests/xapi-t.cc b/xapi/tests/xapi-t.cc index 11d22dcb4..95b2ec206 100644 --- a/xapi/tests/xapi-t.cc +++ b/xapi/tests/xapi-t.cc @@ -67,13 +67,15 @@ void check_compress(mysqlx_session_t *sess) buf_len = 65536; memset(buf, 0, buf_len); - EXPECT_NE(nullptr, row = mysqlx_row_fetch_one(res)); + row = mysqlx_row_fetch_one(res); + EXPECT_FALSE(nullptr == row); EXPECT_EQ(RESULT_OK, mysqlx_get_bytes(row, 0, 0, buf, &buf_len)); test_row("Test ", buf); buf_len = 65536; memset(buf, 0, buf_len); - EXPECT_NE(nullptr, row = mysqlx_row_fetch_one(res)); + row = mysqlx_row_fetch_one(res); + EXPECT_FALSE(nullptr == row); EXPECT_EQ(RESULT_OK, mysqlx_get_bytes(row, 0, 0, buf, &buf_len)); test_row("0123 ", buf); @@ -2552,7 +2554,6 @@ TEST_F(xapi, dns_srv) //Specifying a port number with DNS SRV lookup is not allowed. { - EXPECT_EQ(nullptr, mysqlx_get_client_from_url("mysqlx+srv://root@_mysqlx._tcp.localhost:33060", nullptr, &error)); std::cout << "Expected Error: " << mysqlx_error_message(error) << std::endl; @@ -2949,7 +2950,7 @@ TEST_F(xapi, tls_ver_ciphers) error = NULL; sess = mysqlx_get_session_from_options(opt, &error); mysqlx_free(error); - EXPECT_NE(NULL, sess); + EXPECT_FALSE(NULL == sess); mysqlx_session_close(sess); diff --git a/xapi/tests/xapi_crud-t.cc b/xapi/tests/xapi_crud-t.cc index 211ab8e50..82809858f 100644 --- a/xapi/tests/xapi_crud-t.cc +++ b/xapi/tests/xapi_crud-t.cc @@ -754,7 +754,7 @@ TEST_F(xapi, basic) const char *col_schema = mysqlx_column_get_schema(res, i); const char *col_cat = mysqlx_column_get_catalog(res, i); - EXPECT_NE(nullptr, col_cat); + EXPECT_FALSE(nullptr == col_cat); printf("\n Column # %d", i + 1); printf("\n * name: %s, orig name: %s, table: %s, orig table: %s, schema: %s, catalog: %s", From 47e509778b4830dbbbe16647f6d1c4607ee82122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 10 Mar 2025 16:42:58 +0100 Subject: [PATCH 35/43] cmake: Check if compiler flags are supported before adding them --- cdk/cmake/platform.cmake | 11 +++++++++++ cdk/extra/protobuf/CMakeLists.txt | 8 ++++---- cdk/extra/zlib/CMakeLists.txt | 2 +- cdk/extra/zstd/CMakeLists.txt | 2 +- jdbc/CMakeLists.txt | 6 ++---- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cdk/cmake/platform.cmake b/cdk/cmake/platform.cmake index e76a45e7c..fc3fe6c00 100644 --- a/cdk/cmake/platform.cmake +++ b/cdk/cmake/platform.cmake @@ -115,6 +115,17 @@ macro(add_flags LANG) set(CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS}" PARENT_SCOPE) endmacro() +include(CheckCXXCompilerFlag) + +# Set single compiler flag only if it is supported, ignore otherwise + +macro(set_compiler_flag FLAG) + unset(flag_supported CACHE) + CHECK_CXX_COMPILER_FLAG(${FLAG} flag_supported) + if(flag_supported) + add_compile_options(${FLAG}) + endif() +endmacro() # ----------------------------------------------------------------- diff --git a/cdk/extra/protobuf/CMakeLists.txt b/cdk/extra/protobuf/CMakeLists.txt index 19ae299ff..a787985f5 100644 --- a/cdk/extra/protobuf/CMakeLists.txt +++ b/cdk/extra/protobuf/CMakeLists.txt @@ -96,12 +96,12 @@ set_visibility(hidden) if(GCC AND GCC VERSION_GREATER 11) # See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106199 - add_compile_options(-Wno-stringop-overflow) - add_compile_options(-Wno-stringop-overread) + set_compiler_flag(-Wno-stringop-overflow) + set_compiler_flag(-Wno-stringop-overread) endif() if(NOT MSVC OR CLANG) - add_compile_options(-Wno-unused-const-variable) + set_compiler_flag(-Wno-unused-const-variable) endif() if(WIN32) @@ -109,7 +109,7 @@ if(WIN32) endif() if(APPLE) - add_compile_options(-Wno-deprecated-declarations) + set_compiler_flag(-Wno-deprecated-declarations) endif() diff --git a/cdk/extra/zlib/CMakeLists.txt b/cdk/extra/zlib/CMakeLists.txt index 2c6928d25..6b7fe2450 100644 --- a/cdk/extra/zlib/CMakeLists.txt +++ b/cdk/extra/zlib/CMakeLists.txt @@ -25,7 +25,7 @@ if(WIN32) # conformant name: _open. See online help for details. if(CLANG) - add_compile_options(-Wno-deprecated-declarations) + set_compiler_flag(-Wno-deprecated-declarations) else() add_compile_options(/wd4996) endif() diff --git a/cdk/extra/zstd/CMakeLists.txt b/cdk/extra/zstd/CMakeLists.txt index 28015efef..af505f3b0 100644 --- a/cdk/extra/zstd/CMakeLists.txt +++ b/cdk/extra/zstd/CMakeLists.txt @@ -22,7 +22,7 @@ endif() if(WIN32 AND CLANG) # This warning shows only when building with clang on Win (clang 18): # lib\compress\huf_compress.c(519,16): error : unused function 'HUF_isSorted' - add_compile_options(-Wno-unused-function) + set_compiler_flag(-Wno-unused-function) endif() diff --git a/jdbc/CMakeLists.txt b/jdbc/CMakeLists.txt index 854764808..9a03bb628 100644 --- a/jdbc/CMakeLists.txt +++ b/jdbc/CMakeLists.txt @@ -215,10 +215,8 @@ if(NOT SHOW_JDBC_WARNINGS) else() - add_compile_options( - -Wno-unused-parameter - -Wno-deprecated-declarations - ) + set_compiler_flag(-Wno-unused-parameter) + set_compiler_flag(-Wno-deprecated-declarations) endif() From 0388a3c4cc5d2c28a380f414d96a70670d3b21b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Tue, 11 Mar 2025 08:52:20 +0100 Subject: [PATCH 36/43] Bump connector version to 9.3.0 --- doc/doxygen.cfg | 2 +- version.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index 2468e4ff0..495d48568 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -75,7 +75,7 @@ PROJECT_NAME = "MySQL Connector/C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 9.2.0 +PROJECT_NUMBER = 9.3.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/version.cmake b/version.cmake index 1e24bb325..11a196aad 100644 --- a/version.cmake +++ b/version.cmake @@ -35,7 +35,7 @@ set(COPYRIGHT_YEAR "2025" CACHE INTERNAL "version info") # set(CONCPP_VERSION_MAJOR 9 CACHE INTERNAL "version info") -set(CONCPP_VERSION_MINOR 2 CACHE INTERNAL "version info") +set(CONCPP_VERSION_MINOR 3 CACHE INTERNAL "version info") set(CONCPP_VERSION_MICRO 0 CACHE INTERNAL "version info") # Level is "-alpha", "-beta", empty if GA set(CONCPP_VERSION_LEVEL "" CACHE INTERNAL "version info") From 595ab61b6c66f90fa10038082bccb70b5e404526 Mon Sep 17 00:00:00 2001 From: Bogdan Degtyariov Date: Fri, 14 Mar 2025 17:52:46 +1100 Subject: [PATCH 37/43] Bug#37094209 - JDBC: Pluggable authentication not working on MacOS Change-Id: I4193a31a5263d3888227a6a876a8c9019dda7c55 --- jdbc/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/jdbc/CMakeLists.txt b/jdbc/CMakeLists.txt index 9a03bb628..11fc3e4e1 100644 --- a/jdbc/CMakeLists.txt +++ b/jdbc/CMakeLists.txt @@ -558,6 +558,18 @@ function(bundle_lib lib) DESTINATION "${INSTALL_LIB_DIR}" COMPONENT JDBCDll ) + # Symlinks need to be created to allow authenticating + # plugins to load dependencies in MacOS + # + # NOTE: in Linux the dependencies are adressed in + # a different way + install(CODE " + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink ../${lib_name} ${lib_name} + WORKING_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}/plugin\" + ) + ") + else() install(FILES ${lib} DESTINATION "${INSTALL_LIB_DIR}/private" @@ -648,6 +660,26 @@ macro(bundle_libs to_bundle ignored) endforeach() + if(APPLE) + # Create symlinks for OpenSSL dependencies in MacOS. + # The actual OpenSSL libraries should already be + # installed with XDevAPI connector. + # Other dependencies such as fido2 already have symlinks + # created at this stage. + install(CODE " + foreach(openssl_lib ssl crypto) + file(GLOB found_libs \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}/lib\${openssl_lib}.*dylib\") + foreach(lib_file \${found_libs}) + get_filename_component(openssl_lib_name \${lib_file} NAME) + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink ../\${openssl_lib_name} \${openssl_lib_name} + WORKING_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}/plugin\" + ) + endforeach(lib_file) + endforeach(openssl_lib) + ") + endif() + endmacro(bundle_libs) From 89e2bce3476acaf3e0f355cd85484e4ae6e6147e Mon Sep 17 00:00:00 2001 From: Prashant Tekriwal Date: Mon, 17 Mar 2025 08:39:05 +0100 Subject: [PATCH 38/43] Updated the LICENSE files --- LICENSE.txt | 150 ++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 76 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 0603db9cc..8256a84c6 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Connector/C++ 9.2.0 Community +MySQL Connector/C++ 9.3.0 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Connector/C++ 9.2.0 Community. + MySQL Connector/C++ 9.3.0 Community. - Last updated: November 2024 + Last updated: March 2025 Licensing Information - This release of MySQL Connector/C++ 9.2.0 Community is brought to you + This release of MySQL Connector/C++ 9.3.0 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Connector/C++ 9.2.0 Community is designed to + This distribution of MySQL Connector/C++ 9.3.0 Community 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 the license documentation. Without limiting your rights @@ -34,7 +34,7 @@ Licensing Information a copy of which is reproduced below and can also be found along with its FAQ at http://oss.oracle.com/licenses/universal-foss-exception. - Copyright (c) 2008, 2024, Oracle and/or its affiliates. + Copyright (c) 2008, 2025, Oracle and/or its affiliates. Election of GPLv2 @@ -2142,49 +2142,20 @@ but the Oracle program might not operate properly or at all without it. // SPDX-License-Identifier: Apache-2.0 LICENSE: - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ -A copy of the Apache License v2.0, January 2004 license can be found -in the 'Standard Licenses' section. - - -4th party code included -======================= -exporters/etw -------------- -TraceLogging Dynamic for Windows - -Copyright (c) Microsoft Corporation. All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ +A copy of the Apache License v2.0, January 2004 license can be found +in the 'Standard Licenses' section. -4th Party Libraries -=================== +4th Party Dependencies +====================== opentelemetry-proto ------------------- // Copyright 2019, OpenTelemetry Authors -// Copyright 2020, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -2198,48 +2169,75 @@ opentelemetry-proto // See the License for the specific language governing permissions and // limitations under the License. -Apache License Text as listed above +Some files include +// Copyright 2020, OpenTelemetry Authors +(same license header) + +A copy of the Apache License v2.0, January 2004 license can be found +in the 'Standard Licenses' section. + +================================================================================ +== ------------------------------------------------------------------------------- protobuf -------- +COPYRIGHT AND PERMISSION NOTICE -Copyright 2008 Google Inc. All rights reserved. +Copyright (c) 1996 - 2024, Daniel Stenberg, , and many +contributors, see the THANKS file. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +All rights reserved. - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. -Code generated by the Protocol Buffer compiler is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. + +Protobuf dependency - abseil-cpp +-------------------------------- +=== Header in source files: +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file contains C++11 versions of standard header +// abstractions available within C++14 and C++17, and are designed to be drop-in +// replacement for code compliant with C++14 and C++17. + +=== License File + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + +A copy of the Apache License v2.0, January 2004 license can be found +in the 'Standard Licenses' section. +================================================================================ +== ------------------------------------------------------------------------------- json (nlohmann) ---- + MIT License Copyright (c) 2013-2022 Niels Lohmann @@ -2262,14 +2260,14 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- - +================================================================================ +== curl ---- COPYRIGHT AND PERMISSION NOTICE -Copyright (c) 1996 - 2023, Daniel Stenberg, , and many +Copyright (c) 1996 - 2024, Daniel Stenberg, , and many contributors, see the THANKS file. All rights reserved. From 172c7ac9ceaba0624f14162f1f4f2895c464b6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 17 Mar 2025 15:27:18 +0100 Subject: [PATCH 39/43] WL#11226: Clear all compile warnings -- post push fixes - do not add virtual ~DbDoc() dtor to not change the ABI - add _CRT_SECURE_NO_WARNINGS on Win also when using clang compiler - do not use set_compile_flag() for plain C compiler flags --- CMakeLists.txt | 2 +- cdk/extra/zlib/CMakeLists.txt | 2 +- include/mysqlx/devapi/document.h | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 180498a39..3abc8ce7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -290,7 +290,7 @@ if(WERROR) set(WERROR -Werror) endif() -if(MSVC) +if(MSVC OR TOOLSET_MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) diff --git a/cdk/extra/zlib/CMakeLists.txt b/cdk/extra/zlib/CMakeLists.txt index 6b7fe2450..2c6928d25 100644 --- a/cdk/extra/zlib/CMakeLists.txt +++ b/cdk/extra/zlib/CMakeLists.txt @@ -25,7 +25,7 @@ if(WIN32) # conformant name: _open. See online help for details. if(CLANG) - set_compiler_flag(-Wno-deprecated-declarations) + add_compile_options(-Wno-deprecated-declarations) else() add_compile_options(/wd4996) endif() diff --git a/include/mysqlx/devapi/document.h b/include/mysqlx/devapi/document.h index 3f84697ed..95c29358f 100644 --- a/include/mysqlx/devapi/document.h +++ b/include/mysqlx/devapi/document.h @@ -172,8 +172,6 @@ DLL_WARNINGS_POP virtual Iterator begin(); virtual Iterator end(); - virtual ~DbDoc() {} - friend Impl; friend DocResult; friend Value; From dc79b166ac1e6ff7f130fb069046abc3a0df2ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 17 Mar 2025 15:28:00 +0100 Subject: [PATCH 40/43] cmake: Make sure that ABI check is done only when using MSVC compiler --- testing/tests.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/testing/tests.cmake b/testing/tests.cmake index 5258ce48a..edd8b7e3e 100644 --- a/testing/tests.cmake +++ b/testing/tests.cmake @@ -191,7 +191,12 @@ if(NOT DEFINED ABI_CHECK AND MSVC AND MAINTAINER_MODE) set(ABI_CHECK 1) endif() -if(ABI_CHECK) +# Note: The machinery we use to perform ABI checks works only +# with the original MSVC compiler which can produce required +# export map file, not with clang-cl (for which MSVC is also +# defined) + +if(ABI_CHECK AND MSVC AND NOT CLANG) add_abi_check() endif() From de988dba94675a8e543ffbb66d09db7cca8cfdfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Mon, 17 Mar 2025 16:06:11 +0100 Subject: [PATCH 41/43] WL#11226: Clear all compile warnings -- post push fixes --- cdk/CMakeLists.txt | 4 ++-- common/CMakeLists.txt | 27 ++++++++++++++++++++------- include/mysqlx/common_constants.h | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/cdk/CMakeLists.txt b/cdk/CMakeLists.txt index ca524c022..1e0fb41a7 100644 --- a/cdk/CMakeLists.txt +++ b/cdk/CMakeLists.txt @@ -28,9 +28,9 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.8) +CMAKE_MINIMUM_REQUIRED(VERSION 3.15) -cmake_policy(VERSION 3.0) +cmake_policy(VERSION 3.15) if(POLICY CMP0022) cmake_policy(SET CMP0022 NEW) # consistently use INTERFACE_LINK_LIBRARIES property diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 587340e3e..2114b6ede 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -29,6 +29,26 @@ file(GLOB HEADERS *.h) +#TODO: Remove -Wno-delete-non-abstract-non-virtual-dtor when bumping ABI and +# adding virtual destructor for DbDoc, Value and Column_detail + +if(CLANG) + +set_compiler_flag(-Wno-delete-non-abstract-non-virtual-dtor) + + # Note: GCC/clang and MSVC compilers have different rules for resolving + # relative paths in #include "..." directives [1]. The clang-cl compiler + # understands both conventions but gives warning when using MSVC rules. Since + # headers included by this code trigger the warning we disable it here (this + # is about version_info.h included from nysqlx/common_constants.h) + # + # [1] https://stackoverflow.com/questions/48538707/include-search-paths-from-included-header-varies-for-different-compilers + + set_compiler_flag(-Wno-microsoft-include) + +endif() + + add_library(common STATIC session.cc result.cc collection.cc value.cc ${HEADERS} @@ -36,13 +56,6 @@ add_library(common STATIC target_link_libraries(common cdk) -#TODO: Remove -Wno-delete-non-abstract-non-virtual-dtor when bumping ABI and - # adding virtual destructor for DbDoc, Value and Column_detail -if(CLANG) - target_compile_options(common PRIVATE - -Wno-delete-non-abstract-non-virtual-dtor - ) -endif() # # Note: generated version_info.h is placed in the build location diff --git a/include/mysqlx/common_constants.h b/include/mysqlx/common_constants.h index 34cc567f8..1ae1c48fd 100644 --- a/include/mysqlx/common_constants.h +++ b/include/mysqlx/common_constants.h @@ -31,7 +31,7 @@ #ifndef MYSQL_COMMON_CONSTANTS_H #define MYSQL_COMMON_CONSTANTS_H -#include +#include "version_info.h" #define DEFAULT_MYSQL_PORT 3306 #define DEFAULT_MYSQLX_PORT 33060 From 1d07819a5c30b61347acb63d23ef8369998e3bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Somla?= Date: Thu, 20 Mar 2025 10:37:26 +0100 Subject: [PATCH 42/43] packaging: Update compat.patch --- packaging/compat.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/compat.patch b/packaging/compat.patch index be2cdc0bd..5b4befee7 100644 --- a/packaging/compat.patch +++ b/packaging/compat.patch @@ -33,7 +33,7 @@ index 8b960402..37fac11d 100644 # # Set higher warning level for the main connector code. diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg -index 7bf32bcf..870d6ada 100644 +index 7bf32bcf..b3f2bee6 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -66,7 +66,7 @@ PROJECT_NAME = "MySQL Connector/C++" @@ -41,12 +41,12 @@ index 7bf32bcf..870d6ada 100644 # control system is used. -PROJECT_NUMBER = 8.0.23 -+PROJECT_NUMBER = 9.2.0 ++PROJECT_NUMBER = 9.3.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/version.cmake b/version.cmake -index 53f8f540..54bc21b2 100644 +index 53f8f540..7e589341 100644 --- a/version.cmake +++ b/version.cmake @@ -34,8 +34,8 @@ set(COPYRIGHT_YEAR "2024" CACHE INTERNAL "version info") @@ -56,7 +56,7 @@ index 53f8f540..54bc21b2 100644 -set(CONCPP_VERSION_MAJOR 8 CACHE INTERNAL "version info") -set(CONCPP_VERSION_MINOR 4 CACHE INTERNAL "version info") +set(CONCPP_VERSION_MAJOR 9 CACHE INTERNAL "version info") -+set(CONCPP_VERSION_MINOR 2 CACHE INTERNAL "version info") ++set(CONCPP_VERSION_MINOR 3 CACHE INTERNAL "version info") set(CONCPP_VERSION_MICRO 0 CACHE INTERNAL "version info") # Level is "-alpha", "-beta", empty if GA set(CONCPP_VERSION_LEVEL "" CACHE INTERNAL "version info") From 9aa75cf2f6337a1f69e87be7ded9402f5b6b87c9 Mon Sep 17 00:00:00 2001 From: Lenny <1378684171@qq.com> Date: Thu, 13 Mar 2025 20:59:14 +0800 Subject: [PATCH 43/43] Bug#37734620: Contribution: Do not use NO_CACHE option of cmake find_xxx() commands --- mysql-concpp-config.cmake.in | 14 ++++++++------ testapp/CMakeLists.txt | 3 ++- testing/find_package/CMakeLists.txt | 20 +++++++++++--------- testing/find_package/run_test.cmake | 4 ++-- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/mysql-concpp-config.cmake.in b/mysql-concpp-config.cmake.in index 772410bdd..a6cbf3b8f 100644 --- a/mysql-concpp-config.cmake.in +++ b/mysql-concpp-config.cmake.in @@ -479,11 +479,12 @@ function(find_includes) #message(STATUS "Looking for headers at: ${INCLUDE_DIR}") + unset(MYSQL_CONCPP_INCLUDE_DIR CACHE) find_path(MYSQL_CONCPP_INCLUDE_DIR NAMES mysqlx/xdevapi.h PATHS ${INCLUDE_DIR} NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE # Note: requires cmake 3.21 ) if(NOT MYSQL_CONCPP_INCLUDE_DIR) @@ -697,7 +698,7 @@ function(add_connector_target which tgt base_name) find_library(lib_path NAMES ${lib_name} ${find_lib_paths} ${win_opts} - NO_CACHE + # NO_CACHE ) if(lib_path) @@ -740,7 +741,7 @@ function(add_connector_target which tgt base_name) PATHS "${LIBRARY_DIR}/debug" ${win_opts} NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE ) if(lib_path_debug) @@ -880,12 +881,13 @@ function(find_imp_lib var base_name path) set(CMAKE_FIND_LIBRARY_SUFFIXES .lib) #message("!!! Looking for import library for: ${path}") + unset(${var} CACHE) find_library(${var} NAMES ${base_name} PATHS ${base_path} PATH_SUFFIXES ${vs_suffix} NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE ) if(NOT ${var}) @@ -921,7 +923,7 @@ function(find_deps) PATHS ${LIBRARY_DIR} PATH_SUFFIXES private ${vs_suffix} NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE ) unset(ssl_crypto CACHE) @@ -930,7 +932,7 @@ function(find_deps) PATHS ${LIBRARY_DIR} PATH_SUFFIXES private ${vs_suffix} NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE ) if(NOT ssl_lib OR NOT ssl_crypto) diff --git a/testapp/CMakeLists.txt b/testapp/CMakeLists.txt index d70939162..2942c7693 100644 --- a/testapp/CMakeLists.txt +++ b/testapp/CMakeLists.txt @@ -75,12 +75,13 @@ function(find_openssl where) endif() endif() + unset(openssl CACHE) find_library(openssl NAMES ssl PATHS "${WITH_SSL}" PATH_SUFFIXES "" "lib" "lib64" NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE # Note: requires cmake 3.21 ) if(NOT openssl) diff --git a/testing/find_package/CMakeLists.txt b/testing/find_package/CMakeLists.txt index e92ea2127..7135f04d3 100644 --- a/testing/find_package/CMakeLists.txt +++ b/testing/find_package/CMakeLists.txt @@ -124,11 +124,12 @@ macro(add_version_tests) if(WITH_CONCPP) - find_file(INFO_SRC + unset(INFO_SRC CACHE) + find_file(INFO_SRC NAME INFO_SRC PATHS ${WITH_CONCPP} NO_DEFAULT_PATH - NO_CACHE + #NO_CACHE # Note: requires cmake 3.21 ) else() @@ -210,7 +211,7 @@ macro(add_version_tests) # Prepare options for run_test.cmake - set(test_opts + set(test_opts "-DVERSION=${VERSION_${A}}" "-DWITH_DEBUG=${WITH_DEBUG}" ) @@ -256,12 +257,13 @@ macro(add_tests) if(WITH_SSL) + unset(openssl_lib CACHE) find_library(openssl_lib NAMES ssl libssl PATHS ${WITH_SSL} PATH_SUFFIXES lib NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE ) endif() @@ -287,8 +289,8 @@ macro(add_tests) # Note: On Windows scenarios which build in Debug mode with static # connector library are added only if debug package is available. - if(WIN32 - AND A STREQUAL "static" + if(WIN32 + AND A STREQUAL "static" AND B STREQUAL "Debug" AND NOT WITH_DEBUG ) @@ -332,7 +334,7 @@ macro(add_tests) # # They are implemented by run_test.cmake -- see there. - add_test("config_${name_suffix}" + add_test("config_${name_suffix}" ${CMAKE_COMMAND} "-DCDK_DIR=${CDK_DIR}" "-DCONCPP_SRC_DIR=${HOME_DIR}/../.." @@ -347,7 +349,7 @@ macro(add_tests) FIXTURES_SETUP "${name_suffix}_configured" ) - add_test("build_${name_suffix}" + add_test("build_${name_suffix}" ${CMAKE_COMMAND} "-DCDK_DIR=${CDK_DIR}" "-DCONCPP_SRC_DIR=${HOME_DIR}/../.." @@ -365,7 +367,7 @@ macro(add_tests) message(STATUS "# added test: build_${name_suffix}") - add_test("check_${name_suffix}" + add_test("check_${name_suffix}" ${CMAKE_COMMAND} "-DCDK_DIR=${CDK_DIR}" "-DCONCPP_SRC_DIR=${HOME_DIR}/../.." diff --git a/testing/find_package/run_test.cmake b/testing/find_package/run_test.cmake index d4a2e0550..f3ca4b7bf 100644 --- a/testing/find_package/run_test.cmake +++ b/testing/find_package/run_test.cmake @@ -182,11 +182,11 @@ function(action_check) foreach(exec devapi_test xapi_test jdbc_test) set(exec_path) - find_program(exec_path + find_program(exec_path NAMES ${exec} PATHS "config_test/${out_dir}" NO_DEFAULT_PATH - NO_CACHE + # NO_CACHE # note: requires cmake 3.21 ) if(NOT EXISTS "${exec_path}")