summaryrefslogtreecommitdiff
path: root/connectivity
diff options
context:
space:
mode:
authorLionel Elie Mamane <lionel@mamane.lu>2020-05-09 14:24:03 +0200
committerLionel Elie Mamane <lionel@mamane.lu>2020-05-10 00:11:47 +0200
commit86c86719782243275b65f1f7f2cfdcc0e56c8cd4 (patch)
treec222bed31cc11d5a43ba6bd947afcc879b7ac12a /connectivity
parent3cf259ac4ef3fae79e7d67d886dc7a16426ca996 (diff)
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 <lionel@mamane.lu> Reviewed-by: Lionel Elie Mamane <lionel@mamane.lu>
Diffstat (limited to 'connectivity')
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_connection.cxx3
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx2
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_statement.cxx104
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_statement.hxx1
4 files changed, 81 insertions, 29 deletions
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;