connectivity/source/drivers/mysqlc/mysqlc_connection.cxx | 3 connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx | 2 connectivity/source/drivers/mysqlc/mysqlc_statement.cxx | 104 +++++++--- connectivity/source/drivers/mysqlc/mysqlc_statement.hxx | 1 4 files changed, 81 insertions(+), 29 deletions(-)
New commits: commit 86c86719782243275b65f1f7f2cfdcc0e56c8cd4 Author: Lionel Elie Mamane <lio...@mamane.lu> AuthorDate: Sat May 9 14:24:03 2020 +0200 Commit: Lionel Elie Mamane <lio...@mamane.lu> CommitDate: Sun May 10 00:11:47 2020 +0200 tdf#112423: mysql-sdbc: implement XMultipleResults Thanks to Julien Nabet for the pointers to MySQL's multiple results API documentation: https://dev.mysql.com/doc/refman/8.0/en/c-api-multiple-queries.html Change-Id: Ia6e7f52752ad895210cc415f71bb48d678f3f0ec Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93686 Tested-by: Lionel Elie Mamane <lio...@mamane.lu> Reviewed-by: Lionel Elie Mamane <lio...@mamane.lu> diff --git a/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx b/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx index 045da3b41a77..600e131b89b1 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx @@ -175,7 +175,8 @@ void OConnection::construct(const OUString& url, const Sequence<PropertyValue>& // flags can also be passed as last parameter if (!mysql_real_connect(&m_mysql, host_str.getStr(), user_str.getStr(), pass_str.getStr(), - schema_str.getStr(), nPort, socket_str.getStr(), 0)) + schema_str.getStr(), nPort, socket_str.getStr(), + CLIENT_MULTI_STATEMENTS)) mysqlc_sdbc_driver::throwSQLExceptionWithMsg( mysql_error(&m_mysql), mysql_sqlstate(&m_mysql), mysql_errno(&m_mysql), *this, getConnectionEncoding()); diff --git a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx index 960b6c8875fc..db9b5c6e6b55 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx @@ -271,7 +271,7 @@ sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByUnrelated() { return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleTransactions() { return true; } -sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleResultSets() { return false; } +sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleResultSets() { return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsLikeEscapeClause() { return true; } diff --git a/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx b/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx index c6dab15c4b53..b7073be5e6ec 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx @@ -18,6 +18,7 @@ */ #include <sal/config.h> +#include <sal/log.hxx> #include "mysqlc_connection.hxx" #include "mysqlc_propertyids.hxx" @@ -118,6 +119,9 @@ sal_Bool SAL_CALL OCommonStatement::execute(const OUString& sql) MutexGuard aGuard(m_aMutex); checkDisposed(rBHelper.bDisposed); + closeResultSet(); + m_nAffectedRows = -1; + OString toExec = OUStringToOString(sql, m_xConnection->getConnectionSettings().encoding); MYSQL* pMySql = m_xConnection->getMysqlConnection(); @@ -127,41 +131,28 @@ sal_Bool SAL_CALL OCommonStatement::execute(const OUString& sql) // toExec = mysqlc_sdbc_driver::escapeSql(toExec); int failure = mysql_real_query(pMySql, toExec.getStr(), toExec.getLength()); - if (failure) + if (failure || mysql_errno(pMySql)) mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_sqlstate(pMySql), mysql_errno(pMySql), *this, m_xConnection->getConnectionEncoding()); - m_nAffectedRows = mysql_affected_rows(pMySql); - return !failure; + return getResult(); } Reference<XResultSet> SAL_CALL OCommonStatement::executeQuery(const OUString& sql) { - MutexGuard aGuard(m_aMutex); - checkDisposed(rBHelper.bDisposed); - const OUString sSqlStatement = sql; // TODO m_xConnection->transFormPreparedStatement( sql ); - OString toExec - = OUStringToOString(sSqlStatement, m_xConnection->getConnectionSettings().encoding); - - MYSQL* pMySql = m_xConnection->getMysqlConnection(); - // toExec = mysqlc_sdbc_driver::escapeSql(toExec); - int failure = mysql_real_query(pMySql, toExec.getStr(), toExec.getLength()); - if (failure) - mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_sqlstate(pMySql), - mysql_errno(pMySql), *this, - m_xConnection->getConnectionEncoding()); + bool isRS(execute(sql)); + // if a MySQL error occurred, it was already thrown and the below is not executed + assert(isRS == m_xResultSet.is()); + if (!isRS) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg( + "executeQuery called on SQL command that does not return a ResultSet", "02000", 0, + *this); + if (!m_xResultSet.is()) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg( + "internal MySQL-SDBC error: executeQuery: no ResultSet after execute() returned true.", + "02000", 0, *this); - MYSQL_RES* pMysqlResult = mysql_store_result(pMySql); - if (pMysqlResult == nullptr) - { - mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_sqlstate(pMySql), - mysql_errno(pMySql), *this, - m_xConnection->getConnectionEncoding()); - } - - m_xResultSet = new OResultSet(*getOwnConnection(), this, pMysqlResult, - m_xConnection->getConnectionEncoding()); return m_xResultSet; } @@ -219,9 +210,68 @@ Reference<XResultSet> SAL_CALL OCommonStatement::getResultSet() return m_xResultSet; } +sal_Bool OCommonStatement::getResult() +{ + // all callers already reset that + assert(!m_xResultSet.is()); + assert(m_nAffectedRows == -1); + + MYSQL* pMySql = m_xConnection->getMysqlConnection(); + MYSQL_RES* pMysqlResult = mysql_store_result(pMySql); + if (pMysqlResult != nullptr) + { + // MariaDB/MySQL will return the number of rows in the ResultSet from mysql_affected_rows(); + // sdbc mandates -1 when the command (query) returns a ResultSet + assert(m_nAffectedRows == -1); + m_xResultSet = new OResultSet(*getOwnConnection(), this, pMysqlResult, + m_xConnection->getConnectionEncoding()); + return true; + } + else if (mysql_field_count(pMySql) == 0) + { + m_nAffectedRows = mysql_affected_rows(pMySql); + return false; + } + else + { + mysqlc_sdbc_driver::throwSQLExceptionWithMsg( + "mysql_store_result indicated success and SQL command was supposed to return a " + "ResultSet, but did not.", + "02000", 0, *this); + } + //unreachable + assert(false); + // keep -Werror=return-type happy + return false; +} + sal_Bool SAL_CALL OCommonStatement::getMoreResults() { - return false; // TODO IMPL + MutexGuard aGuard(m_aMutex); + checkDisposed(rBHelper.bDisposed); + + closeResultSet(); + m_nAffectedRows = -1; + + MYSQL* pMySql = m_xConnection->getMysqlConnection(); + int status = mysql_next_result(pMySql); + + if (status > 0 || mysql_errno(pMySql)) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_sqlstate(pMySql), + mysql_errno(pMySql), *this, + m_xConnection->getConnectionEncoding()); + + if (status == -1) + return false; + + if (status != 0) + { + const OUString errMsg("mysql_next_result returned unexpected value: " + + OUString::number(status)); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(errMsg, "02000", 0, *this); + } + + return getResult(); } Any SAL_CALL OCommonStatement::getWarnings() diff --git a/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx b/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx index 2ce417259b24..d74e0a6456ce 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx @@ -71,6 +71,7 @@ protected: protected: void closeResultSet(); + sal_Bool getResult(); // OPropertyArrayUsageHelper ::cppu::IPropertyArrayHelper* createArrayHelper() const override; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits