diff options
author | Tamas Bunth <tamas.bunth@collabora.co.uk> | 2018-06-17 18:09:43 +0200 |
---|---|---|
committer | Tamás Bunth <btomi96@gmail.com> | 2018-08-12 23:15:21 +0200 |
commit | 3478d7453a3d65b3d8d164e8f898a0b79f005c58 (patch) | |
tree | 9443239e076b735e2def217b66d7c305e8eaf254 /mysqlc | |
parent | f465685aecf508be987ae199e77667af896a5e8f (diff) |
Switch from mysql to MariaDB C API
In order to get rid of the MySQL C++ Connector, the sdbc driver should
be implemented using the MariaDB C connector instead. MariaDB
Connector/C is LGPL licensed, so later it can be used in the
connectivity module. This way mysqlc won't be an extension, so it could
be maintained easier.
Change-Id: I99c13ccf154b33b145d34b1e06eec85946dc82a0
Reviewed-on: https://gerrit.libreoffice.org/55960
Reviewed-by: Tamás Bunth <btomi96@gmail.com>
Tested-by: Tamás Bunth <btomi96@gmail.com>
Diffstat (limited to 'mysqlc')
-rw-r--r-- | mysqlc/Library_mysqlc.mk | 3 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_connection.cxx | 140 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_connection.hxx | 19 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_databasemetadata.cxx | 1127 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_databasemetadata.hxx | 4 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_driver.cxx | 2 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_general.cxx | 266 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_general.hxx | 65 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_prepared_resultset.cxx | 1097 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_prepared_resultset.hxx | 248 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_preparedstatement.cxx | 510 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_preparedstatement.hxx | 24 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_resultset.cxx | 497 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_resultset.hxx | 20 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_resultsetmetadata.cxx | 247 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_resultsetmetadata.hxx | 17 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_statement.cxx | 103 | ||||
-rw-r--r-- | mysqlc/source/mysqlc_statement.hxx | 12 |
18 files changed, 2724 insertions, 1677 deletions
diff --git a/mysqlc/Library_mysqlc.mk b/mysqlc/Library_mysqlc.mk index 97f2b63500a2..39c6230d2f05 100644 --- a/mysqlc/Library_mysqlc.mk +++ b/mysqlc/Library_mysqlc.mk @@ -12,12 +12,14 @@ $(eval $(call gb_Library_Library,mysqlc)) $(eval $(call gb_Library_use_externals,mysqlc,\ boost_headers \ mysql-connector-cpp \ + mariadb-connector-c \ )) ifeq ($(SYSTEM_MYSQL_CONNECTOR_CPP),) $(eval $(call gb_Library_add_libs,mysqlc,\ $(if $(filter-out WNT,$(OS)),$(if $(filter MACOSX SOLARIS,$(OS)),-lz -lm,\ -rdynamic -lz -lcrypt -lm)) \ + $(if $(filter LINUX,$(OS)),-lpthread -ldl,) \ )) endif @@ -46,6 +48,7 @@ $(eval $(call gb_Library_add_exception_objects,mysqlc,\ mysqlc/source/mysqlc_services \ mysqlc/source/mysqlc_connection \ mysqlc/source/mysqlc_resultset \ + mysqlc/source/mysqlc_prepared_resultset \ mysqlc/source/mysqlc_resultsetmetadata \ mysqlc/source/mysqlc_statement \ mysqlc/source/mysqlc_preparedstatement \ diff --git a/mysqlc/source/mysqlc_connection.cxx b/mysqlc/source/mysqlc_connection.cxx index c9b4c6d2e471..73581734a293 100644 --- a/mysqlc/source/mysqlc_connection.cxx +++ b/mysqlc/source/mysqlc_connection.cxx @@ -61,12 +61,25 @@ using ::osl::MutexGuard; #define MYSQLC_URI_PREFIX "sdbc:mysqlc:" -OConnection::OConnection(MysqlCDriver& _rDriver, sql::Driver * _cppDriver) +namespace +{ + void lcl_executeUpdate(MYSQL* pMySql, const rtl::OString& sql) + { + mysql_real_query(pMySql, sql.getStr(), sql.getLength()); + // TODO handle error + } +} + +OConnection::OConnection(MysqlCDriver& _rDriver) :OMetaConnection_BASE(m_aMutex) ,m_xMetaData(nullptr) ,m_xDriver(&_rDriver) - ,cppDriver(_cppDriver) { + mysql_init(&m_mysql); + + // use TCP as connection + mysql_protocol_type protocol = MYSQL_PROTOCOL_TCP; + mysql_options(&m_mysql, MYSQL_OPT_PROTOCOL, reinterpret_cast<int*>(&protocol)); } OConnection::~OConnection() @@ -144,29 +157,22 @@ void OConnection::construct(const rtl::OUString& url, const Sequence< PropertyVa } if (!bEmbedded) { - try { - sql::ConnectOptionsMap connProps; - std::string host_str = rtl::OUStringToOString(aHostName, m_settings.encoding).getStr(); - std::string user_str = rtl::OUStringToOString(aUser, m_settings.encoding).getStr(); - std::string pass_str = rtl::OUStringToOString(aPass, m_settings.encoding).getStr(); - std::string schema_str = rtl::OUStringToOString(aDbName, m_settings.encoding).getStr(); - connProps["hostName"] = sql::ConnectPropertyVal(host_str); - connProps["userName"] = sql::ConnectPropertyVal(user_str); - connProps["password"] = sql::ConnectPropertyVal(pass_str); - connProps["schema"] = sql::ConnectPropertyVal(schema_str); - connProps["port"] = sql::ConnectPropertyVal(static_cast<int>(nPort)); - if (unixSocketPassed) { - sql::SQLString socket_str = rtl::OUStringToOString(sUnixSocket, m_settings.encoding).getStr(); - connProps["socket"] = socket_str; - } else if (namedPipePassed) { - sql::SQLString pipe_str = rtl::OUStringToOString(sNamedPipe, m_settings.encoding).getStr(); - connProps["socket"] = pipe_str; - } - - m_settings.cppConnection.reset(cppDriver->connect(connProps)); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); + rtl::OString host_str = rtl::OUStringToOString(aHostName, m_settings.encoding); + rtl::OString user_str = rtl::OUStringToOString(aUser, m_settings.encoding); + rtl::OString pass_str = rtl::OUStringToOString(aPass, m_settings.encoding); + rtl::OString schema_str = rtl::OUStringToOString(aDbName, m_settings.encoding); + rtl::OString socket_str; + if (unixSocketPassed) { + socket_str = rtl::OUStringToOString(sUnixSocket, m_settings.encoding); + } else if (namedPipePassed) { + socket_str = rtl::OUStringToOString(sNamedPipe, m_settings.encoding); } + + // 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)) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), + mysql_errno(&m_mysql),*this, getConnectionEncoding()); } else { // TODO: support for embedded server } @@ -182,9 +188,9 @@ void OConnection::construct(const rtl::OUString& url, const Sequence< PropertyVa 0, Any()); } - std::unique_ptr<sql::Statement> stmt(m_settings.cppConnection->createStatement()); - stmt->executeUpdate("SET session sql_mode='ANSI_QUOTES'"); - stmt->executeUpdate("SET NAMES utf8"); + + lcl_executeUpdate(&m_mysql, rtl::OString{"SET session sql_mode='ANSI_QUOTES'"}); + lcl_executeUpdate(&m_mysql, rtl::OString{"SET NAMES utf8"}); } rtl::OUString OConnection::getImplementationName() @@ -213,7 +219,7 @@ Reference< XStatement > SAL_CALL OConnection::createStatement() Reference< XStatement > xReturn; // the statement can only be executed once try { - xReturn = new OStatement(this, m_settings.cppConnection->createStatement()); + xReturn = new OStatement(this); m_aStatements.push_back(WeakReferenceHelper(xReturn)); return xReturn; } catch (const sql::SQLException & e) { @@ -226,18 +232,20 @@ Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement(const rtl { MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); - const rtl::OUString sSqlStatement = transFormPreparedStatement( _sSql ); + const rtl::OString sSqlStatement = rtl::OUStringToOString( + _sSql, getConnectionEncoding()); // FIXME transform statement ? + + MYSQL_STMT* pStmt = mysql_stmt_init(&m_mysql); + mysql_stmt_prepare(pStmt, sSqlStatement.getStr(), sSqlStatement.getLength()); + + unsigned int nErrorNum = mysql_errno(&m_mysql); + if(nErrorNum != 0) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), + nErrorNum,*this, getConnectionEncoding()); Reference< XPreparedStatement > xStatement; - try { - // create a statement - // the statement can only be executed more than once - xStatement = new OPreparedStatement(this, - m_settings.cppConnection->prepareStatement(rtl::OUStringToOString(sSqlStatement, getConnectionEncoding()).getStr())); - m_aStatements.push_back( WeakReferenceHelper( xStatement ) ); - } catch (const sql::SQLException & e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); - } + xStatement = new OPreparedStatement(this, pStmt); + m_aStatements.push_back( WeakReferenceHelper( xStatement ) ); return xStatement; } @@ -269,11 +277,8 @@ void SAL_CALL OConnection::setAutoCommit(sal_Bool autoCommit) { MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); - try { - m_settings.cppConnection->setAutoCommit(autoCommit); - } catch (const sql::SQLException & e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); - } + if(!mysql_autocommit(&m_mysql, autoCommit)) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql), *this, getConnectionEncoding()); } sal_Bool SAL_CALL OConnection::getAutoCommit() @@ -281,6 +286,7 @@ sal_Bool SAL_CALL OConnection::getAutoCommit() // you have to distinguish which if you are in autocommit mode or not // at normal case true should be fine here + // TODO use SELECT @@autocommit query for that MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); @@ -297,22 +303,18 @@ void SAL_CALL OConnection::commit() { MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); - try { - m_settings.cppConnection->commit(); - } catch (const sql::SQLException & e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); - } + + if(!mysql_commit(&m_mysql)) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql), *this, getConnectionEncoding()); } void SAL_CALL OConnection::rollback() { MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); - try { - m_settings.cppConnection->rollback(); - } catch (const sql::SQLException & e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); - } + + if(!mysql_rollback(&m_mysql)) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql), *this, getConnectionEncoding()); } sal_Bool SAL_CALL OConnection::isClosed() @@ -329,12 +331,9 @@ Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData() checkDisposed(OConnection_BASE::rBHelper.bDisposed); Reference< XDatabaseMetaData > xMetaData = m_xMetaData; - if (!xMetaData.is()) { - try { - xMetaData = new ODatabaseMetaData(*this); // need the connection because it can return it - } catch (const sql::SQLException & e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); - } + if (!xMetaData.is()) + { + xMetaData = new ODatabaseMetaData(*this, &m_mysql); m_xMetaData = xMetaData; } @@ -363,6 +362,7 @@ void SAL_CALL OConnection::setCatalog(const rtl::OUString& catalog) MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); + // TODO How? try { // m_settings.cppConnection->setCatalog(rtl::OUStringToOString(catalog, m_settings.encoding).getStr()); m_settings.cppConnection->setSchema(rtl::OUStringToOString(catalog, getConnectionEncoding()).getStr()); @@ -376,6 +376,7 @@ rtl::OUString SAL_CALL OConnection::getCatalog() MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); + // TODO How? rtl::OUString catalog; try { catalog = mysqlc_sdbc_driver::convert(m_settings.cppConnection->getSchema(), getConnectionEncoding()); @@ -467,6 +468,7 @@ void SAL_CALL OConnection::close() MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); } + mysql_close(&m_mysql); dispose(); } @@ -507,15 +509,8 @@ sal_Int32 OConnection::getMysqlVersion() MutexGuard aGuard(m_aMutex); checkDisposed(OConnection_BASE::rBHelper.bDisposed); - sal_Int32 version(0); - try { - version = 10000 * m_settings.cppConnection->getMetaData()->getDatabaseMajorVersion(); - version += 100 * m_settings.cppConnection->getMetaData()->getDatabaseMinorVersion(); - version += m_settings.cppConnection->getMetaData()->getDatabasePatchVersion(); - } catch (const sql::SQLException & e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, getConnectionEncoding()); - } - return version; + unsigned long version = mysql_get_server_version(&m_mysql); + return static_cast<sal_Int32>(version); } rtl::OUString OConnection::transFormPreparedStatement(const rtl::OUString& _sSQL) @@ -539,13 +534,4 @@ rtl::OUString OConnection::transFormPreparedStatement(const rtl::OUString& _sSQL } -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_connection.hxx b/mysqlc/source/mysqlc_connection.hxx index a305d6a9ab89..72af3c89e886 100644 --- a/mysqlc/source/mysqlc_connection.hxx +++ b/mysqlc/source/mysqlc_connection.hxx @@ -43,6 +43,8 @@ #include <rtl/string.hxx> #include <rtl/ref.hxx> +#include <mysql.h> + #include <map> @@ -85,6 +87,8 @@ namespace connectivity class OConnection final : public OBase_Mutex, public OConnection_BASE { + private: + MYSQL m_mysql; ConnectionSettings m_settings; css::uno::Reference< css::container::XNameAccess > m_typeMap; css::uno::Reference< css::util::XStringSubstitution > m_xParameterSubstitution; @@ -98,9 +102,9 @@ namespace connectivity // for this Connection rtl::Reference<MysqlCDriver> m_xDriver; // Pointer to the owning driver object - sql::Driver* cppDriver; - public: + MYSQL* getMysqlConnection() { return &m_mysql; } + /// @throws SQLException /// @throws RuntimeException sal_Int32 getMysqlVersion(); @@ -108,7 +112,7 @@ namespace connectivity /// @throws SQLException void construct(const rtl::OUString& url,const css::uno::Sequence< css::beans::PropertyValue >& info); - OConnection(MysqlCDriver& _rDriver, sql::Driver * cppDriver); + OConnection(MysqlCDriver& _rDriver ); virtual ~OConnection(); rtl_TextEncoding getConnectionEncoding() const { return m_settings.encoding; } @@ -184,13 +188,4 @@ namespace connectivity } /* connectivity */ #endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_CONNECTION_HXX -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_databasemetadata.cxx b/mysqlc/source/mysqlc_databasemetadata.cxx index 68dad0cbcf84..0f9e539e6df3 100644 --- a/mysqlc/source/mysqlc_databasemetadata.cxx +++ b/mysqlc/source/mysqlc_databasemetadata.cxx @@ -29,7 +29,7 @@ #include <com/sun/star/sdbc/ColumnType.hpp> #include <com/sun/star/lang/XInitialization.hpp> - +#include <rtl/ustrbuf.hxx> #include "mysqlc_general.hxx" #include "mysqlc_statement.hxx" #include "mysqlc_driver.hxx" @@ -44,12 +44,6 @@ using namespace com::sun::star::beans; using namespace com::sun::star::sdbc; using mysqlc_sdbc_driver::getStringFromAny; -#include <cppconn/connection.h> -#include <cppconn/resultset.h> -#include <cppconn/metadata.h> -#include <cppconn/statement.h> -#include <cppconn/prepared_statement.h> - #include <sal/macros.h> static std::string wild("%"); @@ -76,9 +70,9 @@ void lcl_setRows_throw(const Reference< XResultSet >& _xResultSet,sal_Int32 _nTy xIni->initialize(aArgs); } -ODatabaseMetaData::ODatabaseMetaData(OConnection& _rCon) +ODatabaseMetaData::ODatabaseMetaData(OConnection& _rCon, MYSQL* pMySql) :m_rConnection(_rCon) - ,meta(_rCon.getConnectionSettings().cppConnection->getMetaData()) + ,m_pMySql(pMySql) ,identifier_quote_string_set(false) { } @@ -87,564 +81,477 @@ ODatabaseMetaData::~ODatabaseMetaData() { } -rtl::OUString ODatabaseMetaData::impl_getStringMetaData(const sal_Char* _methodName, const sql::SQLString& (sql::DatabaseMetaData::*Method)() ) -{ - rtl::OUString stringMetaData; - try { - stringMetaData = mysqlc_sdbc_driver::convert((meta->*Method)(), m_rConnection.getConnectionEncoding()); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException(_methodName, *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException(_methodName, *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - return stringMetaData; -} - -rtl::OUString ODatabaseMetaData::impl_getStringMetaData(const sal_Char* _methodName, sql::SQLString (sql::DatabaseMetaData::*Method)() ) -{ - rtl::OUString stringMetaData; - try { - stringMetaData = mysqlc_sdbc_driver::convert((meta->*Method)(), m_rConnection.getConnectionEncoding()); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException(_methodName, *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException(_methodName, *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - return stringMetaData; -} - -sal_Int32 ODatabaseMetaData::impl_getInt32MetaData(const sal_Char* _methodName, unsigned int (sql::DatabaseMetaData::*Method)() ) -{ - sal_Int32 int32MetaData(0); - try { - int32MetaData = (meta->*Method)(); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException(_methodName, *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException(_methodName, *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - return int32MetaData; -} - -bool ODatabaseMetaData::impl_getBoolMetaData(const sal_Char* _methodName, bool (sql::DatabaseMetaData::*Method)() ) -{ - bool boolMetaData(false); - try { - boolMetaData = (meta->*Method)(); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException(_methodName, *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException(_methodName, *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - return boolMetaData; -} - -bool ODatabaseMetaData::impl_getBoolMetaData(const sal_Char* _methodName, bool (sql::DatabaseMetaData::*Method)(int), sal_Int32 _arg ) -{ - bool boolMetaData(false); - try { - boolMetaData = (meta->*Method)( _arg ); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException(_methodName, *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException(_methodName, *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - return boolMetaData; -} - -bool ODatabaseMetaData::impl_getRSTypeMetaData(const sal_Char* _methodName, bool (sql::DatabaseMetaData::*Method)(int), sal_Int32 _resultSetType ) -{ - int resultSetType(sql::ResultSet::TYPE_FORWARD_ONLY); - switch ( _resultSetType ) { - case ResultSetType::SCROLL_INSENSITIVE: resultSetType = sql::ResultSet::TYPE_SCROLL_INSENSITIVE; break; - case ResultSetType::SCROLL_SENSITIVE: resultSetType = sql::ResultSet::TYPE_SCROLL_SENSITIVE; break; - } - - return impl_getBoolMetaData(_methodName, Method, resultSetType); -} - rtl::OUString SAL_CALL ODatabaseMetaData::getCatalogSeparator() { - return impl_getStringMetaData("getCatalogSeparator", &sql::DatabaseMetaData::getCatalogSeparator); + return rtl::OUString(); } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxBinaryLiteralLength() { - return impl_getInt32MetaData("getMaxBinaryLiteralLength", &sql::DatabaseMetaData::getMaxBinaryLiteralLength); + return 16777208L; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxRowSize() { - return impl_getInt32MetaData("getMaxRowSize", &sql::DatabaseMetaData::getMaxRowSize); + return 2147483647L - 8; // Max buffer size - HEADER } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCatalogNameLength() { - return impl_getInt32MetaData("getMaxCatalogNameLength", &sql::DatabaseMetaData::getMaxCatalogNameLength); + return 32; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCharLiteralLength() { - return impl_getInt32MetaData("getMaxCharLiteralLength", &sql::DatabaseMetaData::getMaxCharLiteralLength); + return 16777208; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnNameLength() { - return impl_getInt32MetaData("getMaxColumnNameLength", &sql::DatabaseMetaData::getMaxColumnNameLength); + return 64; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInIndex() { - return impl_getInt32MetaData("getMaxColumnsInIndex", &sql::DatabaseMetaData::getMaxColumnsInIndex); + return 16; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCursorNameLength() { - return impl_getInt32MetaData("getMaxCursorNameLength", &sql::DatabaseMetaData::getMaxCursorNameLength); + return 64; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxConnections() { - return impl_getInt32MetaData("getMaxConnections", &sql::DatabaseMetaData::getMaxConnections); + // TODO + // SELECT @@max_connections + return 100; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInTable() { - return impl_getInt32MetaData("getMaxColumnsInTable", &sql::DatabaseMetaData::getMaxColumnsInTable); + return 512; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatementLength() { - return impl_getInt32MetaData("getMaxStatementLength", &sql::DatabaseMetaData::getMaxStatementLength); + // TODO + // "SHOW VARIABLES LIKE 'max_allowed_packet'" + return 32767; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTableNameLength() { - return impl_getInt32MetaData("getMaxTableNameLength", &sql::DatabaseMetaData::getMaxTableNameLength); + return 64; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTablesInSelect() { - return impl_getInt32MetaData("getMaxTablesInSelect", &sql::DatabaseMetaData::getMaxTablesInSelect); + return 256; } sal_Bool SAL_CALL ODatabaseMetaData::doesMaxRowSizeIncludeBlobs() { - return impl_getBoolMetaData("doesMaxRowSizeIncludeBlobs", &sql::DatabaseMetaData::doesMaxRowSizeIncludeBlobs); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseQuotedIdentifiers() { - return impl_getBoolMetaData("storesLowerCaseQuotedIdentifiers", &sql::DatabaseMetaData::storesLowerCaseQuotedIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseIdentifiers() { - return impl_getBoolMetaData("storesLowerCaseIdentifiers", &sql::DatabaseMetaData::storesLowerCaseIdentifiers); + //TODO; + return false; } sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseQuotedIdentifiers() { - return impl_getBoolMetaData("storesMixedCaseQuotedIdentifiers", &sql::DatabaseMetaData::storesMixedCaseQuotedIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseIdentifiers() { - return impl_getBoolMetaData("storesMixedCaseIdentifiers", &sql::DatabaseMetaData::storesMixedCaseIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseQuotedIdentifiers() { - return impl_getBoolMetaData("storesUpperCaseQuotedIdentifiers", &sql::DatabaseMetaData::storesUpperCaseQuotedIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseIdentifiers() { - return impl_getBoolMetaData("storesUpperCaseIdentifiers", &sql::DatabaseMetaData::storesUpperCaseIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsAlterTableWithAddColumn() { - return impl_getBoolMetaData("supportsAlterTableWithAddColumn", &sql::DatabaseMetaData::supportsAlterTableWithAddColumn); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsAlterTableWithDropColumn() { - return impl_getBoolMetaData("supportsAlterTableWithDropColumn", &sql::DatabaseMetaData::supportsAlterTableWithDropColumn); + return true; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxIndexLength() { - return impl_getInt32MetaData("getMaxIndexLength", &sql::DatabaseMetaData::getMaxIndexLength); + return 256; } sal_Bool SAL_CALL ODatabaseMetaData::supportsNonNullableColumns() { - return impl_getBoolMetaData("supportsNonNullableColumns", &sql::DatabaseMetaData::supportsNonNullableColumns); + return true; } rtl::OUString SAL_CALL ODatabaseMetaData::getCatalogTerm() { - return impl_getStringMetaData("getCatalogTerm", &sql::DatabaseMetaData::getCatalogTerm); + return rtl::OUString("n/a"); } rtl::OUString SAL_CALL ODatabaseMetaData::getIdentifierQuoteString() { - if (!identifier_quote_string_set) { - identifier_quote_string = impl_getStringMetaData("getIdentifierQuoteString", &sql::DatabaseMetaData::getIdentifierQuoteString); - identifier_quote_string_set = true; - } - return identifier_quote_string; + return rtl::OUString("\""); } rtl::OUString SAL_CALL ODatabaseMetaData::getExtraNameCharacters() { - return impl_getStringMetaData("getExtraNameCharacters", &sql::DatabaseMetaData::getExtraNameCharacters); + return rtl::OUString("#@"); } sal_Bool SAL_CALL ODatabaseMetaData::supportsDifferentTableCorrelationNames() { - return impl_getBoolMetaData("supportsDifferentTableCorrelationNames", &sql::DatabaseMetaData::supportsDifferentTableCorrelationNames); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::isCatalogAtStart() { - return impl_getBoolMetaData("isCatalogAtStart", &sql::DatabaseMetaData::isCatalogAtStart); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionIgnoredInTransactions() { - return impl_getBoolMetaData("dataDefinitionIgnoredInTransactions", &sql::DatabaseMetaData::dataDefinitionIgnoredInTransactions); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionCausesTransactionCommit() { - return impl_getBoolMetaData("dataDefinitionCausesTransactionCommit", &sql::DatabaseMetaData::dataDefinitionCausesTransactionCommit); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsDataManipulationTransactionsOnly() { - return impl_getBoolMetaData("supportsDataManipulationTransactionsOnly", &sql::DatabaseMetaData::supportsDataManipulationTransactionsOnly); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions() { - return impl_getBoolMetaData("supportsDataDefinitionAndDataManipulationTransactions", &sql::DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedDelete() { - return impl_getBoolMetaData("supportsPositionedDelete", &sql::DatabaseMetaData::supportsPositionedDelete); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedUpdate() { - return impl_getBoolMetaData("supportsPositionedUpdate", &sql::DatabaseMetaData::supportsPositionedUpdate); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossRollback() { - return impl_getBoolMetaData("supportsOpenStatementsAcrossRollback", &sql::DatabaseMetaData::supportsOpenStatementsAcrossRollback); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossCommit() { - return impl_getBoolMetaData("supportsOpenStatementsAcrossCommit", &sql::DatabaseMetaData::supportsOpenStatementsAcrossCommit); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossCommit() { - return impl_getBoolMetaData("supportsOpenCursorsAcrossCommit", &sql::DatabaseMetaData::supportsOpenCursorsAcrossCommit); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossRollback() { - return impl_getBoolMetaData("supportsOpenCursorsAcrossRollback", &sql::DatabaseMetaData::supportsOpenCursorsAcrossRollback); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactionIsolationLevel(sal_Int32 level) +sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactionIsolationLevel(sal_Int32 /*level*/) { - return impl_getBoolMetaData("supportsTransactionIsolationLevel", &sql::DatabaseMetaData::supportsTransactionIsolationLevel, level); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInDataManipulation() { - return impl_getBoolMetaData("supportsSchemasInDataManipulation", &sql::DatabaseMetaData::supportsSchemasInDataManipulation); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92FullSQL() { - return impl_getBoolMetaData("supportsANSI92FullSQL", &sql::DatabaseMetaData::supportsANSI92FullSQL); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92EntryLevelSQL() { - return impl_getBoolMetaData("supportsANSI92EntryLevelSQL", &sql::DatabaseMetaData::supportsANSI92EntryLevelSQL); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsIntegrityEnhancementFacility() { - return impl_getBoolMetaData("supportsIntegrityEnhancementFacility", &sql::DatabaseMetaData::supportsIntegrityEnhancementFacility); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInIndexDefinitions() { - return impl_getBoolMetaData("supportsSchemasInIndexDefinitions", &sql::DatabaseMetaData::supportsSchemasInIndexDefinitions); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInTableDefinitions() { - return impl_getBoolMetaData("supportsSchemasInTableDefinitions", &sql::DatabaseMetaData::supportsSchemasInTableDefinitions); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInTableDefinitions() { - return impl_getBoolMetaData("supportsCatalogsInTableDefinitions", &sql::DatabaseMetaData::supportsCatalogsInTableDefinitions); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInIndexDefinitions() { - return impl_getBoolMetaData("supportsCatalogsInIndexDefinitions", &sql::DatabaseMetaData::supportsCatalogsInIndexDefinitions); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInDataManipulation() { - return impl_getBoolMetaData("supportsCatalogsInDataManipulation", &sql::DatabaseMetaData::supportsCatalogsInDataManipulation); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsOuterJoins() { - return impl_getBoolMetaData("supportsOuterJoins", &sql::DatabaseMetaData::supportsOuterJoins); + return true; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatements() { - return impl_getInt32MetaData("getMaxStatements", &sql::DatabaseMetaData::getMaxStatements); + return 0; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxProcedureNameLength() { - return impl_getInt32MetaData("getMaxProcedureNameLength", &sql::DatabaseMetaData::getMaxProcedureNameLength); + return 64; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxSchemaNameLength() { - return impl_getInt32MetaData("getMaxSchemaNameLength", &sql::DatabaseMetaData::getMaxSchemaNameLength); + return 64; } sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactions() { - return impl_getBoolMetaData("supportsTransactions", &sql::DatabaseMetaData::supportsTransactions); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::allProceduresAreCallable() { - return impl_getBoolMetaData("allProceduresAreCallable", &sql::DatabaseMetaData::allProceduresAreCallable); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsStoredProcedures() { - return impl_getBoolMetaData("supportsStoredProcedures", &sql::DatabaseMetaData::supportsStoredProcedures); + return m_rConnection.getMysqlVersion() >= 50000; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSelectForUpdate() { - return impl_getBoolMetaData("supportsSelectForUpdate", &sql::DatabaseMetaData::supportsSelectForUpdate); + return m_rConnection.getMysqlVersion() >= 40000; } sal_Bool SAL_CALL ODatabaseMetaData::allTablesAreSelectable() { - return impl_getBoolMetaData("allTablesAreSelectable", &sql::DatabaseMetaData::allTablesAreSelectable); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::isReadOnly() { - return impl_getBoolMetaData("isReadOnly", &sql::DatabaseMetaData::isReadOnly); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFiles() { - return impl_getBoolMetaData("usesLocalFiles", &sql::DatabaseMetaData::usesLocalFiles); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFilePerTable() { - return impl_getBoolMetaData("usesLocalFilePerTable", &sql::DatabaseMetaData::usesLocalFilePerTable); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsTypeConversion() { - return impl_getBoolMetaData("supportsTypeConversion", &sql::DatabaseMetaData::supportsTypeConversion); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::nullPlusNonNullIsNull() { - return impl_getBoolMetaData("nullPlusNonNullIsNull", &sql::DatabaseMetaData::nullPlusNonNullIsNull); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsColumnAliasing() { - return impl_getBoolMetaData("supportsColumnAliasing", &sql::DatabaseMetaData::supportsColumnAliasing); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsTableCorrelationNames() { - return impl_getBoolMetaData("supportsTableCorrelationNames", &sql::DatabaseMetaData::supportsTableCorrelationNames); + return true; } -sal_Bool SAL_CALL ODatabaseMetaData::supportsConvert(sal_Int32 /* fromType */, sal_Int32 /* toType */) +sal_Bool SAL_CALL ODatabaseMetaData::supportsConvert(sal_Int32 /*fromType*/, sal_Int32 /*toType*/) { - try { - /* ToDo -> use supportsConvert( fromType, toType) */ - return meta->supportsConvert(); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::supportsConvert", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::supportsConvert", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } + // TODO return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsExpressionsInOrderBy() { - return impl_getBoolMetaData("supportsExpressionsInOrderBy", &sql::DatabaseMetaData::supportsExpressionsInOrderBy); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupBy() { - return impl_getBoolMetaData("supportsGroupBy", &sql::DatabaseMetaData::supportsGroupBy); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByBeyondSelect() { - return impl_getBoolMetaData("supportsGroupByBeyondSelect", &sql::DatabaseMetaData::supportsGroupByBeyondSelect); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByUnrelated() { - return impl_getBoolMetaData("supportsGroupByUnrelated", &sql::DatabaseMetaData::supportsGroupByUnrelated); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleTransactions() { - return impl_getBoolMetaData("supportsMultipleTransactions", &sql::DatabaseMetaData::supportsMultipleTransactions); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleResultSets() { - return impl_getBoolMetaData("supportsMultipleResultSets", &sql::DatabaseMetaData::supportsMultipleResultSets); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsLikeEscapeClause() { - return impl_getBoolMetaData("supportsLikeEscapeClause", &sql::DatabaseMetaData::supportsLikeEscapeClause); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsOrderByUnrelated() { - return impl_getBoolMetaData("supportsOrderByUnrelated", &sql::DatabaseMetaData::supportsOrderByUnrelated); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsUnion() { - return impl_getBoolMetaData("supportsUnion", &sql::DatabaseMetaData::supportsUnion); + return m_rConnection.getMysqlVersion() >= 40000; } sal_Bool SAL_CALL ODatabaseMetaData::supportsUnionAll() { - return impl_getBoolMetaData("supportsUnionAll", &sql::DatabaseMetaData::supportsUnionAll); + return m_rConnection.getMysqlVersion() >= 40000; } sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseIdentifiers() { - return impl_getBoolMetaData("supportsMixedCaseIdentifiers", &sql::DatabaseMetaData::supportsMixedCaseIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseQuotedIdentifiers() { - return impl_getBoolMetaData("supportsMixedCaseQuotedIdentifiers", &sql::DatabaseMetaData::supportsMixedCaseQuotedIdentifiers); + // TODO + return false; } sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtEnd() { - return impl_getBoolMetaData("nullsAreSortedAtEnd", &sql::DatabaseMetaData::nullsAreSortedAtEnd); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtStart() { - return impl_getBoolMetaData("nullsAreSortedAtStart", &sql::DatabaseMetaData::nullsAreSortedAtStart); + return m_rConnection.getMysqlVersion() > 40001 && m_rConnection.getMysqlVersion() < 40011; } sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedHigh() { - return impl_getBoolMetaData("nullsAreSortedHigh", &sql::DatabaseMetaData::nullsAreSortedHigh); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedLow() { - return impl_getBoolMetaData("nullsAreSortedLow", &sql::DatabaseMetaData::nullsAreSortedLow); + return !nullsAreSortedHigh(); } sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInProcedureCalls() { - return impl_getBoolMetaData("supportsSchemasInProcedureCalls", &sql::DatabaseMetaData::supportsSchemasInProcedureCalls); + return m_rConnection.getMysqlVersion() >= 32200; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInPrivilegeDefinitions() { - return impl_getBoolMetaData("supportsSchemasInPrivilegeDefinitions", &sql::DatabaseMetaData::supportsSchemasInPrivilegeDefinitions); + return m_rConnection.getMysqlVersion() >= 32200; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInProcedureCalls() { - return impl_getBoolMetaData("supportsCatalogsInProcedureCalls", &sql::DatabaseMetaData::supportsCatalogsInProcedureCalls); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInPrivilegeDefinitions() { - return impl_getBoolMetaData("supportsCatalogsInPrivilegeDefinitions", &sql::DatabaseMetaData::supportsCatalogsInPrivilegeDefinitions); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCorrelatedSubqueries() { - return impl_getBoolMetaData("supportsCorrelatedSubqueries", &sql::DatabaseMetaData::supportsCorrelatedSubqueries); + return m_rConnection.getMysqlVersion() >= 40100; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInComparisons() { - return impl_getBoolMetaData("supportsSubqueriesInComparisons", &sql::DatabaseMetaData::supportsSubqueriesInComparisons); + return m_rConnection.getMysqlVersion() >= 40100; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInExists() { - return impl_getBoolMetaData("supportsSubqueriesInExists", &sql::DatabaseMetaData::supportsSubqueriesInExists); + return m_rConnection.getMysqlVersion() >= 40100; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInIns() { - return impl_getBoolMetaData("supportsSubqueriesInIns", &sql::DatabaseMetaData::supportsSubqueriesInIns); + return m_rConnection.getMysqlVersion() >= 40100; } sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInQuantifieds() { - return impl_getBoolMetaData("supportsSubqueriesInQuantifieds", &sql::DatabaseMetaData::supportsSubqueriesInQuantifieds); + return m_rConnection.getMysqlVersion() >= 40100; } sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92IntermediateSQL() { - return impl_getBoolMetaData("supportsANSI92IntermediateSQL", &sql::DatabaseMetaData::supportsANSI92IntermediateSQL); + return false; } rtl::OUString SAL_CALL ODatabaseMetaData::getURL() @@ -654,7 +561,8 @@ rtl::OUString SAL_CALL ODatabaseMetaData::getURL() rtl::OUString SAL_CALL ODatabaseMetaData::getUserName() { - return impl_getStringMetaData("getUserName", &sql::DatabaseMetaData::getUserName); + // TODO execute "SELECT USER()" + return rtl::OUString(); } rtl::OUString SAL_CALL ODatabaseMetaData::getDriverName() @@ -669,199 +577,236 @@ rtl::OUString SAL_CALL ODatabaseMetaData::getDriverVersion() rtl::OUString SAL_CALL ODatabaseMetaData::getDatabaseProductVersion() { - return impl_getStringMetaData("getDatabaseProductVersion", &sql::DatabaseMetaData::getDatabaseProductVersion); + return rtl::OStringToOUString(mysql_get_server_info(m_pMySql), + m_rConnection.getConnectionEncoding()); } rtl::OUString SAL_CALL ODatabaseMetaData::getDatabaseProductName() { - return impl_getStringMetaData("getDatabaseProductName", &sql::DatabaseMetaData::getDatabaseProductName); + return rtl::OUString("MySQL"); } rtl::OUString SAL_CALL ODatabaseMetaData::getProcedureTerm() { - return impl_getStringMetaData("getProcedureTerm", &sql::DatabaseMetaData::getProcedureTerm); + return rtl::OUString("procedure"); } rtl::OUString SAL_CALL ODatabaseMetaData::getSchemaTerm() { - return impl_getStringMetaData("getSchemaTerm", &sql::DatabaseMetaData::getSchemaTerm); + return rtl::OUString("database"); } sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMajorVersion() { + // TODO return MARIADBC_VERSION_MAJOR; } sal_Int32 SAL_CALL ODatabaseMetaData::getDefaultTransactionIsolation() { - try { - switch (meta->getDefaultTransactionIsolation()) { - case sql::TRANSACTION_SERIALIZABLE: return TransactionIsolation::SERIALIZABLE; - case sql::TRANSACTION_REPEATABLE_READ: return TransactionIsolation::REPEATABLE_READ; - case sql::TRANSACTION_READ_COMMITTED: return TransactionIsolation::READ_COMMITTED; - case sql::TRANSACTION_READ_UNCOMMITTED: return TransactionIsolation::READ_UNCOMMITTED; - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getDriverMajorVersion", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getDriverMajorVersion", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - return TransactionIsolation::NONE; + return m_rConnection.getMysqlVersion() >= 32336 ? TransactionIsolation::READ_COMMITTED : + TransactionIsolation::NONE; } sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMinorVersion() { + // TODO return MARIADBC_VERSION_MINOR; } rtl::OUString SAL_CALL ODatabaseMetaData::getSQLKeywords() { - return impl_getStringMetaData("getSQLKeywords", &sql::DatabaseMetaData::getSQLKeywords); + return rtl::OUString( + "ACCESSIBLE, ADD, ALL,"\ + "ALTER, ANALYZE, AND, AS, ASC, ASENSITIVE, BEFORE,"\ + "BETWEEN, BIGINT, BINARY, BLOB, BOTH, BY, CALL,"\ + "CASCADE, CASE, CHANGE, CHAR, CHARACTER, CHECK,"\ + "COLLATE, COLUMN, CONDITION, CONNECTION, CONSTRAINT,"\ + "CONTINUE, CONVERT, CREATE, CROSS, CURRENT_DATE,"\ + "CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,"\ + "DATABASE, DATABASES, DAY_HOUR, DAY_MICROSECOND,"\ + "DAY_MINUTE, DAY_SECOND, DEC, DECIMAL, DECLARE,"\ + "DEFAULT, DELAYED, DELETE, DESC, DESCRIBE,"\ + "DETERMINISTIC, DISTINCT, DISTINCTROW, DIV, DOUBLE,"\ + "DROP, DUAL, EACH, ELSE, ELSEIF, ENCLOSED,"\ + "ESCAPED, EXISTS, EXIT, EXPLAIN, FALSE, FETCH,"\ + "FLOAT, FLOAT4, FLOAT8, FOR, FORCE, FOREIGN, FROM,"\ + "FULLTEXT, GRANT, GROUP, HAVING, HIGH_PRIORITY,"\ + "HOUR_MICROSECOND, HOUR_MINUTE, HOUR_SECOND, IF,"\ + "IGNORE, IN, INDEX, INFILE, INNER, INOUT,"\ + "INSENSITIVE, INSERT, INT, INT1, INT2, INT3, INT4,"\ + "INT8, INTEGER, INTERVAL, INTO, IS, ITERATE, JOIN,"\ + "KEY, KEYS, KILL, LEADING, LEAVE, LEFT, LIKE,"\ + "LOCALTIMESTAMP, LOCK, LONG, LONGBLOB, LONGTEXT,"\ + "LOOP, LOW_PRIORITY, MATCH, MEDIUMBLOB, MEDIUMINT,"\ + "MEDIUMTEXT, MIDDLEINT, MINUTE_MICROSECOND,"\ + "MINUTE_SECOND, MOD, MODIFIES, NATURAL, NOT,"\ + "NO_WRITE_TO_BINLOG, NULL, NUMERIC, ON, OPTIMIZE,"\ + "OPTION, OPTIONALLY, OR, ORDER, OUT, OUTER,"\ + "OUTFILE, PRECISION, PRIMARY, PROCEDURE, PURGE,"\ + "RANGE, READ, READS, READ_ONLY, READ_WRITE, REAL,"\ + "REFERENCES, REGEXP, RELEASE, RENAME, REPEAT,"\ + "REPLACE, REQUIRE, RESTRICT, RETURN, REVOKE, RIGHT,"\ + "RLIKE, SCHEMA, SCHEMAS, SECOND_MICROSECOND, SELECT,"\ + "SENSITIVE, SEPARATOR, SET, SHOW, SMALLINT, SPATIAL,"\ + "SPECIFIC, SQL, SQLEXCEPTION, SQLSTATE, SQLWARNING,"\ + "SQL_BIG_RESULT, SQL_CALC_FOUND_ROWS, SQL_SMALL_RESULT,"\ + "SSL, STARTING, STRAIGHT_JOIN, TABLE, TERMINATED,"\ + "THEN, TINYBLOB, TINYINT, TINYTEXT, TO, TRAILING,"\ + "TRIGGER, TRUE, UNDO, UNION, UNIQUE, UNLOCK,"\ + "UNSIGNED, UPDATE, USAGE, USE, USING, UTC_DATE,"\ + "UTC_TIME, UTC_TIMESTAMP, VALUES, VARBINARY, VARCHAR,"\ + "VARCHARACTER, VARYING, WHEN, WHERE, WHILE, WITH,"\ + "WRITE, X509, XOR, YEAR_MONTH, ZEROFILL" \ + "GENERAL, IGNORE_SERVER_IDS, MASTER_HEARTBEAT_PERIOD," \ + "MAXVALUE, RESIGNAL, SIGNAL, SLOW"); } rtl::OUString SAL_CALL ODatabaseMetaData::getSearchStringEscape() { - return impl_getStringMetaData("getSearchStringEscape", &sql::DatabaseMetaData::getSearchStringEscape); + return rtl::OUString("\\"); } rtl::OUString SAL_CALL ODatabaseMetaData::getStringFunctions() { - return impl_getStringMetaData("getStringFunctions", &sql::DatabaseMetaData::getStringFunctions); + return rtl::OUString( + "ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT," + "CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT," + "INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD," + "LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION," + "QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX," + "SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING," + "SUBSTRING_INDEX,TRIM,UCASE,UPPER"); } rtl::OUString SAL_CALL ODatabaseMetaData::getTimeDateFunctions() { - return impl_getStringMetaData("getTimeDateFunctions", &sql::DatabaseMetaData::getTimeDateFunctions); + return rtl::OUString( + "DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME," + "MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD," + "PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT," + "CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE," + "CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME," + "SEC_TO_TIME,TIME_TO_SEC"); } rtl::OUString SAL_CALL ODatabaseMetaData::getSystemFunctions() { - return impl_getStringMetaData("getSystemFunctions", &sql::DatabaseMetaData::getSystemFunctions); + return rtl::OUString( + "DATABASE,USER,SYSTEM_USER," + "SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION"); } rtl::OUString SAL_CALL ODatabaseMetaData::getNumericFunctions() { - return impl_getStringMetaData("getNumericFunctions", &sql::DatabaseMetaData::getNumericFunctions); + return rtl::OUString("ABS,ACOS,ASIN,ATAN,ATAN2,BIT_COUNT,CEILING,COS," + "COT,DEGREES,EXP,FLOOR,LOG,LOG10,MAX,MIN,MOD,PI,POW," + "POWER,RADIANS,RAND,ROUND,SIN,SQRT,TAN,TRUNCATE"); } sal_Bool SAL_CALL ODatabaseMetaData::supportsExtendedSQLGrammar() { - return impl_getBoolMetaData("supportsExtendedSQLGrammar", &sql::DatabaseMetaData::supportsExtendedSQLGrammar); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsCoreSQLGrammar() { - return impl_getBoolMetaData("supportsCoreSQLGrammar", &sql::DatabaseMetaData::supportsCoreSQLGrammar); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsMinimumSQLGrammar() { - return impl_getBoolMetaData("supportsMinimumSQLGrammar", &sql::DatabaseMetaData::supportsMinimumSQLGrammar); + return true; } sal_Bool SAL_CALL ODatabaseMetaData::supportsFullOuterJoins() { - return impl_getBoolMetaData("supportsFullOuterJoins", &sql::DatabaseMetaData::supportsFullOuterJoins); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsLimitedOuterJoins() { - return impl_getBoolMetaData("supportsLimitedOuterJoins", &sql::DatabaseMetaData::supportsLimitedOuterJoins); + return true; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInGroupBy() { - return impl_getInt32MetaData("getMaxColumnsInGroupBy", &sql::DatabaseMetaData::getMaxColumnsInGroupBy); + return 64; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInOrderBy() { - return impl_getInt32MetaData("getMaxColumnsInOrderBy", &sql::DatabaseMetaData::getMaxColumnsInOrderBy); + return 64; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInSelect() { - return impl_getInt32MetaData("getMaxColumnsInSelect", &sql::DatabaseMetaData::getMaxColumnsInSelect); + return 256; } sal_Int32 SAL_CALL ODatabaseMetaData::getMaxUserNameLength() { - return impl_getInt32MetaData("getMaxUserNameLength", &sql::DatabaseMetaData::getMaxUserNameLength); + return 16; } sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetType(sal_Int32 setType) { - return impl_getRSTypeMetaData("supportsResultSetType", &sql::DatabaseMetaData::supportsResultSetType, setType); + return setType == ResultSetType::SCROLL_SENSITIVE; } -sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetConcurrency(sal_Int32 setType, sal_Int32 concurrency) +sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetConcurrency(sal_Int32 /*setType*/, sal_Int32 /*concurrency*/) { - /* TODO: Check this out */ - try { - return meta->supportsResultSetConcurrency(setType, concurrency==css::sdbc::TransactionIsolation::READ_COMMITTED? - sql::TRANSACTION_READ_COMMITTED: - (concurrency == css::sdbc::TransactionIsolation::SERIALIZABLE? - sql::TRANSACTION_SERIALIZABLE:sql::TRANSACTION_SERIALIZABLE)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::supportsResultSetConcurrency", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::supportsResultSetConcurrency", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } return false; } -sal_Bool SAL_CALL ODatabaseMetaData::ownUpdatesAreVisible(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::ownUpdatesAreVisible(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("ownUpdatesAreVisible", &sql::DatabaseMetaData::ownUpdatesAreVisible, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::ownDeletesAreVisible(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::ownDeletesAreVisible(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("ownDeletesAreVisible", &sql::DatabaseMetaData::ownDeletesAreVisible, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::ownInsertsAreVisible(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::ownInsertsAreVisible(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("ownInsertsAreVisible", &sql::DatabaseMetaData::ownInsertsAreVisible, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::othersUpdatesAreVisible(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::othersUpdatesAreVisible(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("othersUpdatesAreVisible", &sql::DatabaseMetaData::othersUpdatesAreVisible, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::othersDeletesAreVisible(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::othersDeletesAreVisible(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("othersDeletesAreVisible", &sql::DatabaseMetaData::othersDeletesAreVisible, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::othersInsertsAreVisible(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::othersInsertsAreVisible(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("othersInsertsAreVisible", &sql::DatabaseMetaData::othersInsertsAreVisible, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::updatesAreDetected(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::updatesAreDetected(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("updatesAreDetected", &sql::DatabaseMetaData::updatesAreDetected, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::deletesAreDetected(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::deletesAreDetected(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("deletesAreDetected", &sql::DatabaseMetaData::deletesAreDetected, setType); + return false; } -sal_Bool SAL_CALL ODatabaseMetaData::insertsAreDetected(sal_Int32 setType) +sal_Bool SAL_CALL ODatabaseMetaData::insertsAreDetected(sal_Int32 /*setType*/) { - return impl_getRSTypeMetaData("insertsAreDetected", &sql::DatabaseMetaData::insertsAreDetected, setType); + return false; } sal_Bool SAL_CALL ODatabaseMetaData::supportsBatchUpdates() { - return impl_getBoolMetaData("supportsBatchUpdates", &sql::DatabaseMetaData::supportsBatchUpdates); + return true; } Reference< XConnection > SAL_CALL ODatabaseMetaData::getConnection() @@ -937,29 +882,6 @@ Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() Reference< XResultSet > SAL_CALL ODatabaseMetaData::getCatalogs() { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); - std::vector< std::vector< Any > > rRows; - - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getCatalogs()); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getCatalogs", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getCatalogs", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - - lcl_setRows_throw(xResultSet, 0, rRows); return xResultSet; } @@ -968,31 +890,32 @@ Reference< XResultSet > SAL_CALL ODatabaseMetaData::getSchemas() Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getSchemas()); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - bool informationSchema = false; - for (sal_uInt32 i = 1; i <= columns; i++) { - sql::SQLString columnStringValue = rset->getString(i); - if (i == 1) { // TABLE_SCHEM - informationSchema = (0 == columnStringValue.compare("information_schema")); - } - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(columnStringValue, encoding))); - } - if (!informationSchema ) { - rRows.push_back(aRow); + rtl::OUString sSql = m_rConnection.getMysqlVersion() > 49999? + rtl::OUString{"SELECT SCHEMA_NAME AS TABLE_SCHEM, CATALOG_NAME AS TABLE_CATALOG FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY SCHEMA_NAME"}: + rtl::OUString{"SHOW DATABASES"}; + + Reference< XStatement > statement = m_rConnection.createStatement(); + Reference< XInterface > executed = statement->executeQuery(sSql); + Reference< XResultSet > rs( executed, UNO_QUERY_THROW); + Reference< XResultSetMetaDataSupplier > supp( executed, UNO_QUERY_THROW); + Reference< XResultSetMetaData > rs_meta = supp->getMetaData(); + + Reference< XRow > xRow( rs, UNO_QUERY_THROW ); + sal_uInt32 columns = rs_meta->getColumnCount(); + while( rs->next() ) + { + std::vector< Any > aRow { Any() }; + bool informationSchema = false; + for (sal_uInt32 i = 1; i <= columns; i++) { + rtl::OUString columnStringValue = xRow->getString(i); + if (i == 1) { // TABLE_SCHEM + informationSchema = (0 == columnStringValue.equalsIgnoreAsciiCase("information_schema")); } + aRow.push_back(makeAny(columnStringValue)); + } + if (!informationSchema ) { + rRows.push_back(aRow); } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getSchemas", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getSchemas", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); } lcl_setRows_throw(xResultSet, 1, rRows); @@ -1000,142 +923,169 @@ Reference< XResultSet > SAL_CALL ODatabaseMetaData::getSchemas() } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumnPrivileges( - const Any& catalog, + const Any& /*catalog*/, const rtl::OUString& schema, const rtl::OUString& table, const rtl::OUString& columnNamePattern) { - Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); - std::vector< std::vector< Any > > rRows; + rtl::OUString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS " + "TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, NULL AS GRANTOR, " + "GRANTEE, PRIVILEGE_TYPE AS PRIVILEGE, IS_GRANTABLE FROM " + "INFORMATION_SCHEMA.COLUMN_PRIVILEGES WHERE TABLE_SCHEMA LIKE " + "'?' AND TABLE_NAME='?' AND COLUMN_NAME LIKE '?' ORDER BY " + "COLUMN_NAME, PRIVILEGE_TYPE"); - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sch(rtl::OUStringToOString(schema, m_rConnection.getConnectionEncoding()).getStr()), - tab(rtl::OUStringToOString(table, m_rConnection.getConnectionEncoding()).getStr()), - cNamePattern(rtl::OUStringToOString(columnNamePattern, m_rConnection.getConnectionEncoding()).getStr()); - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getColumnPrivileges(cat, sch, tab, cNamePattern.compare("")? cNamePattern:wild)); - - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getColumnPrivileges", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getColumnPrivileges", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } + query = query.replaceFirst("?", schema); + query = query.replaceFirst("?", table); + query = query.replaceFirst("?", columnNamePattern); - lcl_setRows_throw(xResultSet, 2, rRows); - return xResultSet; + Reference<XStatement> statement = m_rConnection.createStatement(); + Reference<XResultSet> rs = statement->executeQuery(query); + return rs; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( - const Any& catalog, - const rtl::OUString& schemaPattern, + const Any& /*catalog*/, + const rtl::OUString& /*schemaPattern*/, const rtl::OUString& tableNamePattern, const rtl::OUString& columnNamePattern) { - Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); - std::vector< std::vector< Any > > rRows; - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sPattern(rtl::OUStringToOString(schemaPattern, m_rConnection.getConnectionEncoding()).getStr()), - tNamePattern(rtl::OUStringToOString(tableNamePattern, m_rConnection.getConnectionEncoding()).getStr()), - cNamePattern(rtl::OUStringToOString(columnNamePattern, m_rConnection.getConnectionEncoding()).getStr()); - - try { - std::unique_ptr< sql::ResultSet> rset( meta->getColumns(cat, - sPattern.compare("")? sPattern:wild, - tNamePattern.compare("")? tNamePattern:wild, - cNamePattern.compare("")? cNamePattern:wild)); - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - if (i == 5) { // ColumnType - sal_Int32 sdbc_type = mysqlc_sdbc_driver::mysqlToOOOType(atoi(rset->getString(i).c_str())); - aRow.push_back(makeAny(sdbc_type)); - } else { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getColumns", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getColumns", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); + rtl::OUStringBuffer queryBuf("SELECT TABLE_CATALOG AS TABLE_CAT, " // 1 + "TABLE_SCHEMA AS TABLE_SCHEM, " // 2 + "TABLE_NAME, " // 3 + "COLUMN_NAME, " // 4 + "DATA_TYPE, " // 5 + // TYPE_NAME missing + "CHARACTER_MAXIMUM_LENGTH, " // 6 + "NUMERIC_PRECISION, " // 7 + // buffer length missing + "NUMERIC_SCALE AS DECIMAL_DIGITS, " // 8 + // NUM_PREC_RADIX missing + // NULLABLE missing + "COLUMN_COMMENT AS REMARKS, " // 9 + "COLUMN_DEFAULT AS COLUMN_DEF," // 10 + "CHARACTER_OCTET_LENGTH, " // 11 + "ORDINAL_POSITION, " // 12 + "IS_NULLABLE, " // 13 + "COLUMN_TYPE " // 14 + "FROM INFORMATION_SCHEMA.COLUMNS " + "WHERE (1 = 1) "); + + if (!tableNamePattern.isEmpty()) + { + rtl::OUString sAppend; + if (tableNamePattern.match("%")) + sAppend = "AND TABLE_NAME LIKE '%' "; + else + sAppend = "AND TABLE_NAME = '%' "; + queryBuf.append(sAppend.replaceAll("%", tableNamePattern)); + } + if (!columnNamePattern.isEmpty()) + { + rtl::OUString sAppend; + if (columnNamePattern.match("%")) + sAppend = "AND COLUMN_NAME LIKE '%' "; + else + sAppend = "AND COLUMN_NAME = '%' "; + queryBuf.append(sAppend.replaceAll("%", columnNamePattern)); } - lcl_setRows_throw(xResultSet, 3, rRows); + + rtl::OUString query = queryBuf.makeStringAndClear(); + Reference<XStatement> statement = m_rConnection.createStatement(); + Reference<XResultSet> rs = statement->executeQuery(query.getStr()); + Reference<XRow> xRow( rs, UNO_QUERY_THROW ); + + Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance( + "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); + std::vector< std::vector< Any > > aRows; + while( rs->next() ) + { + std::vector< Any > aRow { Any() }; // 0. element is unused + + // catalog name + aRow.push_back(makeAny(xRow->getString(1))); + // schema name + aRow.push_back(makeAny(xRow->getString(2))); + // table name + aRow.push_back(makeAny(xRow->getString(3))); + // column name + aRow.push_back(makeAny(xRow->getString(4))); + // data type + rtl::OUString sDataType = xRow->getString(5); + aRow.push_back(makeAny(mysqlc_sdbc_driver::mysqlStrToOOOType(sDataType))); + // type name + aRow.push_back(makeAny(sDataType)); // TODO + // column size + sal_Int32 nColumnSize = 0; + rtl::OUString sColumnType = xRow->getString(14); + sal_Int32 nCharMaxLen = xRow->getShort(6); + bool bIsCharMax = !xRow->wasNull(); + if( sDataType.equalsIgnoreAsciiCase("year") ) + nColumnSize = sColumnType.copy(6, 1).toInt32(); // 'year(' length is 5 + else if(sDataType.equalsIgnoreAsciiCase("date")) + nColumnSize = 10; + else if(sDataType.equalsIgnoreAsciiCase("date")) + nColumnSize = 8; + else if(sDataType.equalsIgnoreAsciiCase("datetime") + || sDataType.equalsIgnoreAsciiCase("timestamp")) + nColumnSize = 19; + else if(!bIsCharMax) + nColumnSize = xRow->getShort(7); // numeric precision + else + nColumnSize = nCharMaxLen; + aRow.push_back(makeAny(nColumnSize)); + aRow.push_back( Any() ); // buffer length - unused + // decimal digits (scale) + aRow.push_back(makeAny(xRow->getShort(8))); + // num_prec_radix + aRow.push_back(makeAny(sal_Int32(10))); + // nullable + rtl::OUString sIsNullable = xRow->getString(13); + if(xRow->wasNull()) + aRow.push_back(makeAny(ColumnValue::NULLABLE_UNKNOWN)); + else if(sIsNullable.equalsIgnoreAsciiCase("YES")) + aRow.push_back(makeAny(ColumnValue::NULLABLE)); + else + aRow.push_back(makeAny(ColumnValue::NO_NULLS)); + // remarks + aRow.push_back(makeAny(xRow->getString(9))); + // default + aRow.push_back(makeAny(xRow->getString(10))); + + aRow.push_back( Any{} ); // sql_data_type - unused + aRow.push_back( Any{} ); // sql_datetime_sub - unused + + // character octet length + aRow.push_back(makeAny(xRow->getString(11))); + // ordinal position + aRow.push_back(makeAny(xRow->getString(12))); + // is nullable + aRow.push_back(makeAny(sIsNullable)); + aRows.push_back(aRow); + } + lcl_setRows_throw(xResultSet, 1, aRows); return xResultSet; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTables( - const Any& catalog, + const Any& /*catalog*/, const rtl::OUString& schemaPattern, const rtl::OUString& tableNamePattern, - const Sequence< rtl::OUString >& types ) + const Sequence< rtl::OUString >& /*types */) { - sal_Int32 nLength = types.getLength(); + rtl::OUString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME," + "IF(STRCMP(TABLE_TYPE,'BASE TABLE'), TABLE_TYPE, 'TABLE') AS TABLE_TYPE, TABLE_COMMENT AS REMARKS " + "FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA LIKE '?' AND TABLE_NAME LIKE '?' " + "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME"); - Reference< XResultSet > xResultSet(getOwnConnection(). - getDriver().getFactory()->createInstance( - "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); - std::vector< std::vector< Any > > rRows; + // TODO use prepared stmt instead + // TODO escape schema, table name ? + query = query.replaceFirst("?", schemaPattern); + query = query.replaceFirst("?", tableNamePattern); - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sPattern(rtl::OUStringToOString(schemaPattern, m_rConnection.getConnectionEncoding()).getStr()), - tNamePattern(rtl::OUStringToOString(tableNamePattern, m_rConnection.getConnectionEncoding()).getStr()); - - std::list<sql::SQLString> tabTypes; - for (const rtl::OUString *pStart = types.getConstArray(), *p = pStart, *pEnd = pStart + nLength; p != pEnd; ++p) { - tabTypes.push_back(rtl::OUStringToOString(*p, m_rConnection.getConnectionEncoding()).getStr()); - } - - try { - std::unique_ptr< sql::ResultSet> rset( meta->getTables(cat, - sPattern.compare("")? sPattern:wild, - tNamePattern.compare("")? tNamePattern:wild, - tabTypes)); - - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - bool informationSchema = false; - for (sal_uInt32 i = 1; (i <= columns) && !informationSchema; ++i) { - sql::SQLString columnStringValue = rset->getString(i); - if (i == 2) { // TABLE_SCHEM - informationSchema = ( 0 == columnStringValue.compare("information_schema")); - } - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(columnStringValue, encoding))); - } - if (!informationSchema) { - rRows.push_back(aRow); - } - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getTables", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getTables", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - - lcl_setRows_throw(xResultSet, 4, rRows); - return xResultSet; + Reference<XStatement> statement = m_rConnection.createStatement(); + Reference<XResultSet> rs = statement->executeQuery(query); + return rs; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedureColumns( @@ -1149,41 +1099,13 @@ Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedureColumns( } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedures( - const Any& catalog, - const rtl::OUString& schemaPattern, - const rtl::OUString& procedureNamePattern) + const Any& /*catalog*/, + const rtl::OUString& /*schemaPattern*/, + const rtl::OUString& /*procedureNamePattern*/) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sPattern(rtl::OUStringToOString(schemaPattern, m_rConnection.getConnectionEncoding()).getStr()), - procNamePattern(rtl::OUStringToOString(procedureNamePattern, m_rConnection.getConnectionEncoding()).getStr()); - - - try { - std::unique_ptr< sql::ResultSet> rset( meta->getProcedures(cat, - sPattern.compare("")? sPattern:wild, - procNamePattern.compare("")? procNamePattern:wild)); - - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getProcedures", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getProcedures", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO IMPL lcl_setRows_throw(xResultSet, 7,rRows); return xResultSet; } @@ -1200,283 +1122,101 @@ Reference< XResultSet > SAL_CALL ODatabaseMetaData::getVersionColumns( } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getExportedKeys( - const Any& catalog , - const rtl::OUString& schema , - const rtl::OUString& table ) + const Any& /*catalog */, + const rtl::OUString& /*schema */, + const rtl::OUString& /*table */) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sch(rtl::OUStringToOString(schema, m_rConnection.getConnectionEncoding()).getStr()), - tab(rtl::OUStringToOString(table, m_rConnection.getConnectionEncoding()).getStr()); - - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getExportedKeys(cat, sch, tab)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getExportedKeys", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getExportedKeys", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO implement lcl_setRows_throw(xResultSet, 8, rRows); return xResultSet; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getImportedKeys( - const Any& catalog, - const rtl::OUString& schema, - const rtl::OUString& table) + const Any& /*catalog*/, + const rtl::OUString& /*schema*/, + const rtl::OUString& /*table*/) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sch(rtl::OUStringToOString(schema, m_rConnection.getConnectionEncoding()).getStr()), - tab(rtl::OUStringToOString(table, m_rConnection.getConnectionEncoding()).getStr()); - - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getImportedKeys(cat, sch, tab)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getImportedKeys", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getImportedKeys", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO implement lcl_setRows_throw(xResultSet,9,rRows); return xResultSet; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getPrimaryKeys( - const Any& catalog, + const Any& /*catalog*/, const rtl::OUString& schema, const rtl::OUString& table) { - Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); - std::vector< std::vector< Any > > rRows; - - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sch(rtl::OUStringToOString(schema, m_rConnection.getConnectionEncoding()).getStr()), - tab(rtl::OUStringToOString(table, m_rConnection.getConnectionEncoding()).getStr()); + rtl::OUString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA " + "AS TABLE_SCHEM, TABLE_NAME, " "COLUMN_NAME, SEQ_IN_INDEX AS KEY_SEQ," + "INDEX_NAME AS PK_NAME FROM INFORMATION_SCHEMA.STATISTICS " + "WHERE TABLE_SCHEMA LIKE '?' AND TABLE_NAME LIKE '?' AND INDEX_NAME='PRIMARY' " + "ORDER BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX"); - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getPrimaryKeys(cat, sch, tab)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getPrimaryKeys", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getPrimaryKeys", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } + // TODO use prepared stmt instead + // TODO escape schema, table name ? + query = query.replaceFirst("?", schema); + query = query.replaceFirst("?", table); - lcl_setRows_throw(xResultSet, 10, rRows); - return xResultSet; + Reference<XStatement> statement = m_rConnection.createStatement(); + Reference<XResultSet> rs = statement->executeQuery(query); + return rs; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getIndexInfo( - const Any& catalog, - const rtl::OUString& schema, - const rtl::OUString& table, - sal_Bool unique, - sal_Bool approximate) + const Any& /*catalog*/, + const rtl::OUString& /*schema*/, + const rtl::OUString& /*table*/, + sal_Bool /*unique*/, + sal_Bool /*approximate*/) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sch(rtl::OUStringToOString(schema, m_rConnection.getConnectionEncoding()).getStr()), - tab(rtl::OUStringToOString(table, m_rConnection.getConnectionEncoding()).getStr()); - - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getIndexInfo(cat, sch, tab, unique, approximate)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getIndexInfo", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getIndexInfo", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO lcl_setRows_throw(xResultSet, 11, rRows); return xResultSet; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getBestRowIdentifier( - const Any& catalog, - const rtl::OUString& schema, - const rtl::OUString& table, - sal_Int32 scope, - sal_Bool nullable) + const Any& /*catalog*/, + const rtl::OUString& /*schema*/, + const rtl::OUString& /*table*/, + sal_Int32 /*scope*/, + sal_Bool /*nullable*/) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sch(rtl::OUStringToOString(schema, m_rConnection.getConnectionEncoding()).getStr()), - tab(rtl::OUStringToOString(table, m_rConnection.getConnectionEncoding()).getStr()); - - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getBestRowIdentifier(cat, sch, tab, scope, nullable)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getBestRowIdentifier", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getBestRowIdentifier", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO lcl_setRows_throw(xResultSet, 15, rRows); return xResultSet; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTablePrivileges( - const Any& catalog, - const rtl::OUString& schemaPattern, - const rtl::OUString& tableNamePattern) + const Any& /*catalog*/, + const rtl::OUString& /*schemaPattern*/, + const rtl::OUString& /*tableNamePattern*/) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - - std::string cat(catalog.hasValue()? rtl::OUStringToOString(getStringFromAny(catalog), m_rConnection.getConnectionEncoding()).getStr():""), - sPattern(rtl::OUStringToOString(schemaPattern, m_rConnection.getConnectionEncoding()).getStr()), - tPattern(rtl::OUStringToOString(tableNamePattern, m_rConnection.getConnectionEncoding()).getStr()); - - try { - static bool fakeTablePrivileges = false; - if (fakeTablePrivileges) { - static const sal_Char* allPrivileges[] = { - "ALTER", "DELETE", "DROP", "INDEX", "INSERT", "LOCK TABLES", "SELECT", "UPDATE" - }; - Any userName; userName <<= getUserName(); - for (size_t i = 0; i < SAL_N_ELEMENTS( allPrivileges ); ++i) { - std::vector< Any > aRow; - aRow.push_back(makeAny( sal_Int32( i ) )); - aRow.push_back(catalog); // TABLE_CAT - aRow.push_back(makeAny( schemaPattern )); // TABLE_SCHEM - aRow.push_back(makeAny( tableNamePattern )); // TABLE_NAME - aRow.push_back(Any()); // GRANTOR - aRow.push_back(userName); // GRANTEE - aRow.push_back(makeAny( rtl::OUString::createFromAscii( allPrivileges[i] ) )); // PRIVILEGE - aRow.push_back(Any()); // IS_GRANTABLE - - rRows.push_back(aRow); - } - } else { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getTablePrivileges(cat, sPattern.compare("")? sPattern:wild, tPattern.compare("")? tPattern:wild)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getTablePrivileges", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getTablePrivileges", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO lcl_setRows_throw(xResultSet,12,rRows); return xResultSet; } Reference< XResultSet > SAL_CALL ODatabaseMetaData::getCrossReference( - const Any& primaryCatalog, - const rtl::OUString& primarySchema_, - const rtl::OUString& primaryTable_, - const Any& foreignCatalog, - const rtl::OUString& foreignSchema, - const rtl::OUString& foreignTable) + const Any& /*primaryCatalog*/, + const rtl::OUString& /*primarySchema_*/, + const rtl::OUString& /*primaryTable_*/, + const Any& /*foreignCatalog*/, + const rtl::OUString& /*foreignSchema*/, + const rtl::OUString& /*foreignTable*/) { Reference< XResultSet > xResultSet(getOwnConnection().getDriver().getFactory()->createInstance("org.openoffice.comp.helper.DatabaseMetaDataResultSet"),UNO_QUERY); std::vector< std::vector< Any > > rRows; - - std::string primaryCat(primaryCatalog.hasValue()? rtl::OUStringToOString(getStringFromAny(primaryCatalog), m_rConnection.getConnectionEncoding()).getStr():""), - foreignCat(foreignCatalog.hasValue()? rtl::OUStringToOString(getStringFromAny(foreignCatalog), m_rConnection.getConnectionEncoding()).getStr():""), - primarySchema(rtl::OUStringToOString(primarySchema_, m_rConnection.getConnectionEncoding()).getStr()), - primaryTable(rtl::OUStringToOString(primaryTable_, m_rConnection.getConnectionEncoding()).getStr()), - fSchema(rtl::OUStringToOString(foreignSchema, m_rConnection.getConnectionEncoding()).getStr()), - fTable(rtl::OUStringToOString(foreignTable, m_rConnection.getConnectionEncoding()).getStr()); - - try { - rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding(); - std::unique_ptr< sql::ResultSet> rset( meta->getCrossReference(primaryCat, primarySchema, primaryTable, foreignCat, fSchema, fTable)); - sql::ResultSetMetaData * rs_meta = rset->getMetaData(); - sal_uInt32 columns = rs_meta->getColumnCount(); - while (rset->next()) { - std::vector< Any > aRow { Any() }; - for (sal_uInt32 i = 1; i <= columns; i++) { - aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(rset->getString(i), encoding))); - } - rRows.push_back(aRow); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getCrossReference", *this); - } catch (const sql::InvalidArgumentException &) { - mysqlc_sdbc_driver::throwInvalidArgumentException("ODatabaseMetaData::getCrossReference", *this); - } catch (const sql::SQLException& e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_rConnection.getConnectionEncoding()); - } - + // TODO lcl_setRows_throw(xResultSet,13,rRows); return xResultSet; } @@ -1491,13 +1231,4 @@ Reference< XResultSet > SAL_CALL ODatabaseMetaData::getUDTs( return nullptr; } -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_databasemetadata.hxx b/mysqlc/source/mysqlc_databasemetadata.hxx index 9f09e534215d..3801acadc4a7 100644 --- a/mysqlc/source/mysqlc_databasemetadata.hxx +++ b/mysqlc/source/mysqlc_databasemetadata.hxx @@ -42,7 +42,7 @@ namespace connectivity class ODatabaseMetaData final : public ODatabaseMetaData_BASE { OConnection& m_rConnection; - sql::DatabaseMetaData * meta; + MYSQL * m_pMySql; rtl::OUString identifier_quote_string; bool identifier_quote_string_set; @@ -56,7 +56,7 @@ namespace connectivity public: const OConnection& getOwnConnection() const { return m_rConnection; } - explicit ODatabaseMetaData(OConnection& _rCon); + explicit ODatabaseMetaData(OConnection& _rCon, MYSQL* pMySql); virtual ~ODatabaseMetaData(); // as I mentioned before this interface is really BIG diff --git a/mysqlc/source/mysqlc_driver.cxx b/mysqlc/source/mysqlc_driver.cxx index 18e2db4cb9ae..40cab769e912 100644 --- a/mysqlc/source/mysqlc_driver.cxx +++ b/mysqlc/source/mysqlc_driver.cxx @@ -198,7 +198,7 @@ Reference< XConnection > SAL_CALL MysqlCDriver::connect(const rtl::OUString& url Reference< XConnection > xConn; // create a new connection with the given properties and append it to our vector try { - OConnection* pCon = new OConnection(*this, cppDriver); + OConnection* pCon = new OConnection(*this); xConn = pCon; pCon->construct(url,info); diff --git a/mysqlc/source/mysqlc_general.cxx b/mysqlc/source/mysqlc_general.cxx index 2c4eb1f53853..8f3d0ed619d2 100644 --- a/mysqlc/source/mysqlc_general.cxx +++ b/mysqlc/source/mysqlc_general.cxx @@ -19,8 +19,7 @@ #include "mysqlc_general.hxx" #include "mysqlc_resultsetmetadata.hxx" -#include <cppconn/exception.h> -#include <cppconn/datatype.h> +#include <rtl/ustring.hxx> using com::sun::star::sdbc::SQLException; @@ -28,10 +27,77 @@ using com::sun::star::uno::Reference; using com::sun::star::uno::XInterface; using com::sun::star::uno::Any; +using namespace rtl; + namespace mysqlc_sdbc_driver { -void throwFeatureNotImplementedException( const sal_Char* _pAsciiFeatureName, const Reference< XInterface >& _rxContext ) +void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize) +{ + assert(mem); + switch(eType) + { + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: + *mem = malloc(sizeof(sal_Int32)); + break; + case MYSQL_TYPE_SHORT: + *mem = malloc(sizeof(sal_Int16)); + break; + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_TINY: + *mem = malloc(sizeof(sal_Int8)); + break; + case MYSQL_TYPE_LONGLONG: + *mem = malloc(sizeof(sal_Int64)); + break; + case MYSQL_TYPE_FLOAT: + *mem = malloc(sizeof(float)); + break; + case MYSQL_TYPE_DOUBLE: + *mem = malloc(sizeof(double)); + break; + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_YEAR: // FIXME below + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_GEOMETRY: + *mem = malloc(sizeof(MYSQL_TIME)); + break; + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + *mem = malloc(sizeof(char)*nSize); + break; + case MYSQL_TYPE_NULL: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + *mem = nullptr; + break; + default: + SAL_WARN("connectivity","unknown enum_field_type"); + } +} + +/// Use this intead of mysql_real_escape_string, because that one also escapes +/// single quote ('), which should not be escaped +rtl::OString escapeSql( const rtl::OString& from ) +{ + rtl::OString sRet = from.replaceAll("\\", "\\\\"); + sRet = sRet.replaceAll("\"", "\\\""); + sRet = sRet.replaceAll("`", "\\`"); + return sRet; +} + +void throwFeatureNotImplementedException( const sal_Char* _pAsciiFeatureName, const css::uno::Reference< XInterface >& _rxContext ) { const rtl::OUString sMessage = rtl::OUString::createFromAscii( _pAsciiFeatureName ) + ": feature not implemented."; throw SQLException( @@ -43,7 +109,7 @@ void throwFeatureNotImplementedException( const sal_Char* _pAsciiFeatureName, co ); } -void throwInvalidArgumentException( const sal_Char* _pAsciiFeatureName, const Reference< XInterface >& _rxContext ) +void throwInvalidArgumentException( const sal_Char* _pAsciiFeatureName, const css::uno::Reference< XInterface >& _rxContext ) { const rtl::OUString sMessage = rtl::OUString::createFromAscii( _pAsciiFeatureName ) + ": invalid arguments."; throw SQLException( @@ -66,6 +132,14 @@ void translateAndThrow(const ::sql::SQLException& _error, const css::uno::Refere ); } +void throwSQLExceptionWithMsg(const char* msg, unsigned int errorNum, const css::uno::Reference< css::uno::XInterface >& _context, const rtl_TextEncoding encoding) +{ + rtl::OString errorMsg{msg}; + // TODO error code? + throw SQLException( rtl::OStringToOUString(errorMsg, encoding), + _context, rtl::OUString(), errorNum, Any()); +} + rtl::OUString getStringFromAny(const Any& _rAny) { rtl::OUString nReturn; @@ -73,77 +147,195 @@ rtl::OUString getStringFromAny(const Any& _rAny) return nReturn; } -int mysqlToOOOType(int cppConnType) - throw () +int mysqlToOOOType(int eType, int charsetnr) noexcept { - switch (cppConnType) { - case sql::DataType::BIT: + // charset number 63 indicates binary + switch (eType) { + case MYSQL_TYPE_BIT: return css::sdbc::DataType::VARCHAR; - case sql::DataType::TINYINT: + case MYSQL_TYPE_TINY: return css::sdbc::DataType::TINYINT; - case sql::DataType::SMALLINT: + case MYSQL_TYPE_SHORT: return css::sdbc::DataType::SMALLINT; - case sql::DataType::INTEGER: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: return css::sdbc::DataType::INTEGER; - case sql::DataType::BIGINT: + case MYSQL_TYPE_LONGLONG: return css::sdbc::DataType::BIGINT; - case sql::DataType::REAL: + case MYSQL_TYPE_FLOAT: return css::sdbc::DataType::REAL; - case sql::DataType::DOUBLE: + case MYSQL_TYPE_DOUBLE: return css::sdbc::DataType::DOUBLE; - case sql::DataType::DECIMAL: + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: return css::sdbc::DataType::DECIMAL; - case sql::DataType::CHAR: + case MYSQL_TYPE_STRING: + if(charsetnr == 63) + return css::sdbc::DataType::BINARY; return css::sdbc::DataType::CHAR; - case sql::DataType::BINARY: - return css::sdbc::DataType::BINARY; - - case sql::DataType::ENUM: - case sql::DataType::SET: - case sql::DataType::VARCHAR: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_VAR_STRING: + if(charsetnr == 63) + return css::sdbc::DataType::VARBINARY; return css::sdbc::DataType::VARCHAR; - case sql::DataType::VARBINARY: - return css::sdbc::DataType::VARBINARY; - - case sql::DataType::LONGVARCHAR: + case MYSQL_TYPE_BLOB: + if(charsetnr == 63) + return css::sdbc::DataType::LONGVARBINARY; return css::sdbc::DataType::LONGVARCHAR; - case sql::DataType::LONGVARBINARY: - return css::sdbc::DataType::LONGVARBINARY; - - case sql::DataType::TIMESTAMP: + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: return css::sdbc::DataType::TIMESTAMP; - case sql::DataType::DATE: + case MYSQL_TYPE_DATE: return css::sdbc::DataType::DATE; - case sql::DataType::TIME: + case MYSQL_TYPE_TIME: return css::sdbc::DataType::TIME; - case sql::DataType::GEOMETRY: + case MYSQL_TYPE_GEOMETRY: return css::sdbc::DataType::VARCHAR; - case sql::DataType::SQLNULL: + case MYSQL_TYPE_NULL: return css::sdbc::DataType::SQLNULL; - - case sql::DataType::UNKNOWN: - return css::sdbc::DataType::VARCHAR; } OSL_FAIL( "mysqlToOOOType: unhandled case, falling back to VARCHAR" ); return css::sdbc::DataType::VARCHAR; } +int mysqlStrToOOOType(const rtl::OUString& sType) +{ + // TODO other types. + if(sType.equalsIgnoreAsciiCase("tiny") || sType.equalsIgnoreAsciiCase("tinyint")) + return css::sdbc::DataType::TINYINT; + if(sType.equalsIgnoreAsciiCase("smallint")) + return css::sdbc::DataType::SMALLINT; + if(sType.equalsIgnoreAsciiCase("longtext")) + return css::sdbc::DataType::LONGVARCHAR; + if(sType.equalsIgnoreAsciiCase("int")) + return css::sdbc::DataType::INTEGER; + if(sType.equalsIgnoreAsciiCase("varchar") || sType.equalsIgnoreAsciiCase("set") || + sType.equalsIgnoreAsciiCase("enum")) + return css::sdbc::DataType::VARCHAR; + if(sType.equalsIgnoreAsciiCase("bigint")) + return css::sdbc::DataType::BIGINT; + if(sType.equalsIgnoreAsciiCase("blob") || sType.equalsIgnoreAsciiCase("longblob")) + return css::sdbc::DataType::BLOB; + if(sType.equalsIgnoreAsciiCase("varbinary")) + return css::sdbc::DataType::VARBINARY; + if(sType.equalsIgnoreAsciiCase("text")) + return css::sdbc::DataType::CHAR; + if(sType.equalsIgnoreAsciiCase("binary")) + return css::sdbc::DataType::BINARY; + if(sType.equalsIgnoreAsciiCase("time")) + return css::sdbc::DataType::TIME; + if(sType.equalsIgnoreAsciiCase("date")) + return css::sdbc::DataType::DATE; + if(sType.equalsIgnoreAsciiCase("datetime")) + return css::sdbc::DataType::TIMESTAMP; + if(sType.equalsIgnoreAsciiCase("decimal")) + return css::sdbc::DataType::DECIMAL; + if(sType.equalsIgnoreAsciiCase("real") || sType.equalsIgnoreAsciiCase("float")) + return css::sdbc::DataType::REAL; + if(sType.equalsIgnoreAsciiCase("double")) + return css::sdbc::DataType::DOUBLE; + if(sType.equalsIgnoreAsciiCase("bit") || sType.equalsIgnoreAsciiCase("bool") || + sType.equalsIgnoreAsciiCase("boolean")) + return css::sdbc::DataType::BOOLEAN; + OSL_FAIL("Unknown type name from string, failing back to varchar."); + return css::sdbc::DataType::VARCHAR; +} + +rtl::OUString mysqlTypeToStr(MYSQL_FIELD* field) +{ + bool isUnsigned = (field->flags & UNSIGNED_FLAG) != 0; + bool isZerofill = (field->flags & ZEROFILL_FLAG) != 0; + switch (field->type) + { + case MYSQL_TYPE_BIT: + return OUString{"BIT"}; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + return isUnsigned ? (isZerofill? OUString{"DECIMAL UNSIGNED ZEROFILL"} : OUString{"DECIMAL UNSIGNED"}): OUString{"DECIMAL"}; + case MYSQL_TYPE_TINY: + return isUnsigned ? (isZerofill? OUString{"TINYINT UNSIGNED ZEROFILL"} : OUString{"TINYINT UNSIGNED"}): OUString{"TINYINT"}; + case MYSQL_TYPE_SHORT: + return isUnsigned ? (isZerofill? OUString{"SMALLINT UNSIGNED ZEROFILL"} : OUString{"SMALLINT UNSIGNED"}): OUString{"SMALLINT"}; + case MYSQL_TYPE_LONG: + return isUnsigned ? (isZerofill? OUString{"INT UNSIGNED ZEROFILL"} : OUString{"INT UNSIGNED"}): OUString{"INT"}; + case MYSQL_TYPE_FLOAT: + return isUnsigned ? (isZerofill? OUString{"FLOAT UNSIGNED ZEROFILL"} : OUString{"FLOAT UNSIGNED"}): OUString{"FLOAT"}; + case MYSQL_TYPE_DOUBLE: + return isUnsigned ? (isZerofill? OUString{"DOUBLE UNSIGNED ZEROFILL"} : OUString{"DOUBLE UNSIGNED"}): OUString{"DOUBLE"}; + case MYSQL_TYPE_NULL: + return OUString{"NULL"}; + case MYSQL_TYPE_TIMESTAMP: + return OUString{"TIMESTAMP"}; + case MYSQL_TYPE_LONGLONG: + return isUnsigned ? (isZerofill? OUString{"BIGINT UNSIGNED ZEROFILL"} : OUString{"BIGINT UNSIGNED"}) : OUString{"BIGINT"}; + case MYSQL_TYPE_INT24: + return isUnsigned ? (isZerofill? OUString{"MEDIUMINT UNSIGNED ZEROFILL"} : OUString{"MEDIUMINT UNSIGNED"}) : OUString{"MEDIUMINT"}; + case MYSQL_TYPE_DATE: + return OUString{"DATE"}; + case MYSQL_TYPE_TIME: + return OUString{"TIME"}; + case MYSQL_TYPE_DATETIME: + return OUString{"DATETIME"}; + case MYSQL_TYPE_TINY_BLOB: + { + return OUString{"TINYBLOB"}; + } + case MYSQL_TYPE_MEDIUM_BLOB: + { + return OUString{"MEDIUMBLOB"}; + } + case MYSQL_TYPE_LONG_BLOB: + { + return OUString{"LONGBLOB"}; + } + case MYSQL_TYPE_BLOB: + { + return OUString{"BLOB"}; + } + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VAR_STRING: + if (field->flags & ENUM_FLAG) { + return OUString{"ENUM"}; + } + if (field->flags & SET_FLAG) { + return OUString{"SET"}; + } + return OUString{"VARCHAR"}; + case MYSQL_TYPE_STRING: + if (field->flags & ENUM_FLAG) { + return OUString{"ENUM"}; + } + if (field->flags & SET_FLAG) { + return OUString{"SET"}; + } + return OUString{"CHAR"}; + case MYSQL_TYPE_YEAR: + return OUString{"YEAR"}; + case MYSQL_TYPE_GEOMETRY: + return OUString{"GEOMETRY"}; + default: + return OUString{"UNKNOWN"}; + } + +} + rtl::OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding) { return rtl::OUString( _string.c_str(), _string.size(), encoding ); diff --git a/mysqlc/source/mysqlc_general.hxx b/mysqlc/source/mysqlc_general.hxx index 5d0b828c3e51..43544a2a172e 100644 --- a/mysqlc/source/mysqlc_general.hxx +++ b/mysqlc/source/mysqlc_general.hxx @@ -25,6 +25,9 @@ #include <com/sun/star/uno/XInterface.hpp> #include <com/sun/star/sdbc/SQLException.hpp> +#include <osl/diagnose.h> +#include <mysql.h> + #if defined __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated" @@ -36,6 +39,61 @@ namespace mysqlc_sdbc_driver { + template<typename T> + void resetSqlVar(void** target, T* pValue, enum_field_types type, sal_Int32 nSize = 0) + { + if(*target) + { + free(*target); + *target = nullptr; + } + constexpr auto nUnitSize = sizeof(T); + switch(type) + { + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_GEOMETRY: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + *target = malloc(nUnitSize); + memcpy(*target, pValue, nUnitSize); + break; + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + *target = malloc(nUnitSize*nSize); + memcpy(*target, pValue, nUnitSize*nSize); + break; + case MYSQL_TYPE_NULL: + // nothing I guess + break; + default: + OSL_FAIL("resetSqlVar: unknown enum_field_type"); + } + } + + void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize = 0); + + rtl::OString escapeSql(const rtl::OString& from); + rtl::OUString getStringFromAny(const css::uno::Any& _rAny); /// @throws css::sdbc::SQLException @@ -52,8 +110,13 @@ namespace mysqlc_sdbc_driver void translateAndThrow(const ::sql::SQLException& _error, const css::uno::Reference< css::uno::XInterface >& _context, const rtl_TextEncoding encoding); - int mysqlToOOOType(int mysqlType) throw (); + void throwSQLExceptionWithMsg(const char* msg, unsigned int errorNum, const css::uno::Reference< css::uno::XInterface >& _context, const rtl_TextEncoding encoding); + + int mysqlToOOOType(int eType, int charsetnr) noexcept; + + rtl::OUString mysqlTypeToStr(MYSQL_FIELD* pField); + int mysqlStrToOOOType(const rtl::OUString& sType); rtl::OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding); diff --git a/mysqlc/source/mysqlc_prepared_resultset.cxx b/mysqlc/source/mysqlc_prepared_resultset.cxx new file mode 100644 index 000000000000..3bc6b9424752 --- /dev/null +++ b/mysqlc/source/mysqlc_prepared_resultset.cxx @@ -0,0 +1,1097 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you 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 http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "mysqlc_propertyids.hxx" +#include "mysqlc_general.hxx" +#include "mysqlc_prepared_resultset.hxx" +#include "mysqlc_resultsetmetadata.hxx" + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/typeprovider.hxx> + +using namespace rtl; +#include <comphelper/string.hxx> + +#include <cstdlib> + +using namespace connectivity::mysqlc; +using namespace cppu; +using namespace com::sun::star; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::sdbcx; +using namespace com::sun::star::container; +using namespace com::sun::star::io; +using namespace com::sun::star::util; +using namespace ::comphelper; +using ::osl::MutexGuard; + +#include <cppconn/resultset.h> +#include <cppconn/resultset_metadata.h> + +#include <stdio.h> + +rtl::OUString SAL_CALL OPreparedResultSet::getImplementationName() +{ + return rtl::OUString("com.sun.star.sdbcx.mysqlc.ResultSet"); +} + +uno::Sequence<rtl::OUString> SAL_CALL OPreparedResultSet::getSupportedServiceNames() +{ + uno::Sequence<rtl::OUString> aSupported(2); + aSupported[0] = "com.sun.star.sdbc.ResultSet"; + aSupported[1] = "com.sun.star.sdbcx.ResultSet"; + return aSupported; +} + +sal_Bool SAL_CALL OPreparedResultSet::supportsService(const rtl::OUString& _rServiceName) +{ + return cppu::supportsService(this, _rServiceName); +} +OPreparedResultSet::OPreparedResultSet(OConnection& rConn, OPreparedStatement* pPrepared, + MYSQL_STMT* pStmt) + : OPreparedResultSet_BASE(m_aMutex) + , OPropertySetHelper(OPreparedResultSet_BASE::rBHelper) + , m_rConnection(rConn) + , m_aStatement(static_cast<OWeakObject*>(pPrepared)) + , m_xMetaData(nullptr) + , m_pStmt(pStmt) + , m_encoding(rConn.getConnectionEncoding()) +{ + m_nFieldCount = mysql_stmt_field_count(pStmt); + m_pResult = mysql_stmt_result_metadata(m_pStmt); + m_aFields = mysql_fetch_fields(m_pResult); +} + +OPreparedResultSet::~OPreparedResultSet() {} + +void OPreparedResultSet::disposing() +{ + OPropertySetHelper::disposing(); + + MutexGuard aGuard(m_aMutex); + + m_aStatement = nullptr; + m_xMetaData = nullptr; +} + +Any SAL_CALL OPreparedResultSet::queryInterface(const Type& rType) +{ + Any aRet = OPropertySetHelper::queryInterface(rType); + if (!aRet.hasValue()) + { + aRet = OPreparedResultSet_BASE::queryInterface(rType); + } + return aRet; +} + +uno::Sequence<Type> SAL_CALL OPreparedResultSet::getTypes() +{ + OTypeCollection aTypes(cppu::UnoType<XMultiPropertySet>::get(), + cppu::UnoType<XFastPropertySet>::get(), + cppu::UnoType<XPropertySet>::get()); + + return concatSequences(aTypes.getTypes(), OPreparedResultSet_BASE::getTypes()); +} + +sal_Int32 SAL_CALL OPreparedResultSet::findColumn(const rtl::OUString& columnName) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + MYSQL_FIELD* pFields = mysql_fetch_field(m_pResult); + for (sal_Int32 i = 0; i < m_nFieldCount; ++i) + { + if (columnName.equalsIgnoreAsciiCaseAscii(pFields[i].name)) + return i + 1; // sdbc indexes from 1 + } + + throw SQLException("The column name '" + columnName + "' is not valid.", *this, + rtl::OUString("42S22"), 0, Any()); +} + +uno::Reference<XInputStream> SAL_CALL OPreparedResultSet::getBinaryStream(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getBinaryStream", + *this); + return nullptr; +} + +uno::Reference<XInputStream> SAL_CALL OPreparedResultSet::getCharacterStream(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException( + "OPreparedResultSet::getCharacterStream", *this); + return nullptr; +} + +sal_Bool SAL_CALL OPreparedResultSet::getBoolean(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return false; + } + m_bWasNull = false; + return *reinterpret_cast<bool*>(m_aData[column - 1].buffer); +} + +sal_Int8 SAL_CALL OPreparedResultSet::getByte(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return 0; + } + m_bWasNull = false; + return *reinterpret_cast<sal_Int8*>(m_aData[column - 1].buffer); +} + +uno::Sequence<sal_Int8> SAL_CALL OPreparedResultSet::getBytes(sal_Int32 column) +{ + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return uno::Sequence<sal_Int8>(); + } + m_bWasNull = false; + + return uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8 const*>(m_aData[column - 1].buffer), + *m_aData[column - 1].length); +} + +Date SAL_CALL OPreparedResultSet::getDate(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return Date{}; // TODO init + } + m_bWasNull = false; + + const MYSQL_TIME* pTime = reinterpret_cast<MYSQL_TIME*>(m_aData[column - 1].buffer); + + assert(pTime != nullptr); + + Date d; + d.Year = pTime->year; + d.Month = pTime->month; + d.Day = pTime->day; + return d; +} + +double SAL_CALL OPreparedResultSet::getDouble(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return double{}; + } + m_bWasNull = false; + + return *reinterpret_cast<double*>(m_aData[column - 1].buffer); +} + +float SAL_CALL OPreparedResultSet::getFloat(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return float{}; + } + m_bWasNull = false; + + return *reinterpret_cast<float*>(m_aData[column - 1].buffer); +} + +sal_Int32 SAL_CALL OPreparedResultSet::getInt(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return sal_Int32{}; + } + m_bWasNull = false; + + return *reinterpret_cast<sal_Int32*>(m_aData[column - 1].buffer); +} + +sal_Int32 SAL_CALL OPreparedResultSet::getRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return static_cast<sal_Int32>(mysql_field_tell(m_pResult)); +} + +sal_Int64 SAL_CALL OPreparedResultSet::getLong(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + return sal_Int64{}; + + return *reinterpret_cast<sal_Int64*>(m_aData[column - 1].buffer); +} + +uno::Reference<XResultSetMetaData> SAL_CALL OPreparedResultSet::getMetaData() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + if (!m_xMetaData.is()) + { + m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult, m_encoding); + } + return m_xMetaData; +} + +uno::Reference<XArray> SAL_CALL OPreparedResultSet::getArray(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getArray", *this); + return nullptr; +} + +uno::Reference<XClob> SAL_CALL OPreparedResultSet::getClob(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getClob", *this); + return nullptr; +} + +uno::Reference<XBlob> SAL_CALL OPreparedResultSet::getBlob(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getBlob", *this); + return nullptr; +} + +uno::Reference<XRef> SAL_CALL OPreparedResultSet::getRef(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getRef", *this); + return nullptr; +} + +Any SAL_CALL OPreparedResultSet::getObject(sal_Int32 column, + const uno::Reference<XNameAccess>& /* typeMap */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + Any aRet = Any(); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getObject", *this); + return aRet; +} + +sal_Int16 SAL_CALL OPreparedResultSet::getShort(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return sal_Int16{}; + } + m_bWasNull = false; + + return *reinterpret_cast<sal_Int16*>(m_aData[column - 1].buffer); +} + +rtl::OUString SAL_CALL OPreparedResultSet::getString(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return OUString{}; + } + m_bWasNull = false; + + if (m_aFields[column - 1].type == MYSQL_TYPE_BIT) + { + if (*reinterpret_cast<sal_Int8*>(m_aData[column - 1].buffer) != 0) + return OUString{ "YES" }; + return OUString{ "NO" }; + } + + const char* sStr = reinterpret_cast<const char*>(m_aData[column - 1].buffer); + + OUString sReturn = rtl::OUString(sStr, *m_aData[column - 1].length, m_encoding); + return sReturn; +} + +Time SAL_CALL OPreparedResultSet::getTime(sal_Int32 column) +{ + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return Time{}; // TODO init + } + m_bWasNull = false; + + const MYSQL_TIME* pTime = reinterpret_cast<MYSQL_TIME*>(m_aData[column - 1].buffer); + + assert(pTime != nullptr); + + Time t; + t.Hours = pTime->hour; + t.Minutes = pTime->minute; + t.Seconds = pTime->second; + return t; +} + +DateTime SAL_CALL OPreparedResultSet::getTimestamp(sal_Int32 column) +{ + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + checkColumnIndex(column); + + if (*m_aData[column - 1].is_null) + { + m_bWasNull = true; + return DateTime{}; + } + m_bWasNull = false; + + const MYSQL_TIME* pTime = reinterpret_cast<MYSQL_TIME*>(m_aData[column - 1].buffer); + + assert(pTime != nullptr); + + DateTime t; + t.Year = pTime->year; + t.Month = pTime->month; + t.Day = pTime->day; + t.Hours = pTime->hour; + t.Minutes = pTime->minute; + t.Seconds = pTime->second; + return t; +} + +sal_Bool SAL_CALL OPreparedResultSet::isBeforeFirst() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return m_nCurrentField == 0; +} + +sal_Bool SAL_CALL OPreparedResultSet::isAfterLast() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return m_nCurrentField >= m_nFieldCount; +} + +sal_Bool SAL_CALL OPreparedResultSet::isFirst() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return m_nCurrentField == 1 && !isAfterLast(); +} + +sal_Bool SAL_CALL OPreparedResultSet::isLast() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return mysql_field_tell(m_pResult) == static_cast<unsigned>(m_nFieldCount); +} + +void SAL_CALL OPreparedResultSet::beforeFirst() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::beforeFirst", + *this); +} + +void SAL_CALL OPreparedResultSet::afterLast() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::afterLast", *this); +} + +void SAL_CALL OPreparedResultSet::close() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + if (m_aData) + { + delete[] m_aData; + delete[] m_aMetaData; + } + + if (m_pResult) + mysql_free_result(m_pResult); + mysql_stmt_free_result(m_pStmt); + dispose(); +} + +sal_Bool SAL_CALL OPreparedResultSet::first() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + mysql_stmt_data_seek(m_pStmt, 0); + next(); + + return true; +} + +sal_Bool SAL_CALL OPreparedResultSet::last() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + mysql_stmt_data_seek(m_pStmt, m_nFieldCount - 1); + next(); + + return true; +} + +sal_Bool SAL_CALL OPreparedResultSet::absolute(sal_Int32 row) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + sal_Int32 nFields = static_cast<sal_Int32>(m_nFieldCount); + sal_Int32 nToGo = row < 0 ? nFields - row : row - 1; + + if (nToGo >= nFields) + nToGo = nFields - 1; + if (nToGo < 0) + nToGo = 0; + + mysql_stmt_data_seek(m_pStmt, nToGo); + next(); + + return true; +} + +sal_Bool SAL_CALL OPreparedResultSet::relative(sal_Int32 row) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + sal_Int32 nFields = static_cast<sal_Int32>(m_nFieldCount); + if (row == 0) + return true; + + sal_Int32 nToGo = m_nCurrentField + row; + if (nToGo >= nFields) + nToGo = nFields - 1; + if (nToGo < 0) + nToGo = 0; + + mysql_stmt_data_seek(m_pStmt, nToGo); + next(); + m_nCurrentField += row; + + return true; +} + +sal_Bool SAL_CALL OPreparedResultSet::previous() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + if (m_nCurrentField <= 1) + return false; + + mysql_stmt_data_seek(m_pStmt, m_nCurrentField - 2); + next(); + --m_nFieldCount; + return true; +} + +uno::Reference<uno::XInterface> SAL_CALL OPreparedResultSet::getStatement() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return m_aStatement.get(); +} + +sal_Bool SAL_CALL OPreparedResultSet::rowDeleted() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +sal_Bool SAL_CALL OPreparedResultSet::rowInserted() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +sal_Bool SAL_CALL OPreparedResultSet::rowUpdated() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +sal_Bool SAL_CALL OPreparedResultSet::next() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + bool bFirstRun = false; + // allocate array if it does not exist + if (m_aData == nullptr) + { + bFirstRun = true; + m_aData = new MYSQL_BIND[m_nFieldCount]; + memset(m_aData, 0, m_nFieldCount * sizeof(MYSQL_BIND)); + m_aMetaData = new BindMetaData[m_nFieldCount]; + } + for (sal_Int32 i = 0; i < m_nFieldCount; ++i) + { + m_aMetaData[i].is_null = 0; + m_aMetaData[i].length = 0l; + m_aMetaData[i].error = 0; + + m_aData[i].is_null = &m_aMetaData[i].is_null; + m_aData[i].buffer_length = m_aFields[i].type == MYSQL_TYPE_BLOB ? 0 : m_aFields[i].length; + m_aData[i].length = &m_aMetaData[i].length; + m_aData[i].error = &m_aMetaData[i].error; + m_aData[i].buffer = nullptr; + m_aData[i].buffer_type = m_aFields[i].type; + + // allocates memory, if it is a fixed size type. If not then nullptr + mysqlc_sdbc_driver::allocateSqlVar(&m_aData[i].buffer, m_aData[i].buffer_type, + m_aFields[i].length); + } + mysql_stmt_bind_result(m_pStmt, m_aData); + if (bFirstRun) + mysql_stmt_store_result(m_pStmt); + int failure = mysql_stmt_fetch(m_pStmt); + + for (sal_Int32 i = 0; i < m_nFieldCount; ++i) + { + if (*m_aData[i].error) + { + // expected if we have a BLOB, as buffer_length is set to 0. We want to + // fetch it piece by piece + // see https://bugs.mysql.com/file.php?id=12361&bug_id=33086 + if (m_aData[i].buffer == nullptr) + { + m_aData[i].buffer_length = *m_aData[i].length; + m_aData[i].buffer = malloc(*m_aData[i].length); + mysql_stmt_fetch_column(m_pStmt, &m_aData[i], i, 0); + } + } + } + + if (failure == 1) + { + MYSQL* pMysql = m_rConnection.getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMysql), mysql_errno(pMysql), + *this, m_encoding); + } + else if (failure == MYSQL_NO_DATA) + return false; + + // current field cannot be asked as a number. We have to keep track it + // manually. + m_nCurrentField += 1; + + return true; +} + +sal_Bool SAL_CALL OPreparedResultSet::wasNull() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return m_bWasNull; +} + +void SAL_CALL OPreparedResultSet::cancel() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); +} + +void SAL_CALL OPreparedResultSet::clearWarnings() {} + +Any SAL_CALL OPreparedResultSet::getWarnings() +{ + Any aRet = Any(); + return aRet; +} + +void SAL_CALL OPreparedResultSet::insertRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + // you only have to implement this if you want to insert new rows + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::insertRow", *this); +} + +void SAL_CALL OPreparedResultSet::updateRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + // only when you allow updates + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateRow", *this); +} + +void SAL_CALL OPreparedResultSet::deleteRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::deleteRow", *this); +} + +void SAL_CALL OPreparedResultSet::cancelRowUpdates() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::cancelRowUpdates", + *this); +} + +void SAL_CALL OPreparedResultSet::moveToInsertRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + // only when you allow insert's + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::moveToInsertRow", + *this); +} + +void SAL_CALL OPreparedResultSet::moveToCurrentRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); +} + +void SAL_CALL OPreparedResultSet::updateNull(sal_Int32 column) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateNull", + *this); +} + +void SAL_CALL OPreparedResultSet::updateBoolean(sal_Int32 column, sal_Bool /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateBoolean", + *this); +} + +void SAL_CALL OPreparedResultSet::updateByte(sal_Int32 column, sal_Int8 /* x */) +{ + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateByte", + *this); +} + +void SAL_CALL OPreparedResultSet::updateShort(sal_Int32 column, sal_Int16 /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateShort", + *this); +} + +void SAL_CALL OPreparedResultSet::updateInt(sal_Int32 column, sal_Int32 /* x */) +{ + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateInt", *this); +} + +void SAL_CALL OPreparedResultSet::updateLong(sal_Int32 column, sal_Int64 /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateLong", + *this); +} + +void SAL_CALL OPreparedResultSet::updateFloat(sal_Int32 column, float /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateFloat", + *this); +} + +void SAL_CALL OPreparedResultSet::updateDouble(sal_Int32 column, double /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateDouble", + *this); +} + +void SAL_CALL OPreparedResultSet::updateString(sal_Int32 column, const rtl::OUString& /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateString", + *this); +} + +void SAL_CALL OPreparedResultSet::updateBytes(sal_Int32 column, + const uno::Sequence<sal_Int8>& /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateBytes", + *this); +} + +void SAL_CALL OPreparedResultSet::updateDate(sal_Int32 column, const Date& /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateDate", + *this); +} + +void SAL_CALL OPreparedResultSet::updateTime(sal_Int32 column, const Time& /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateTime", + *this); +} + +void SAL_CALL OPreparedResultSet::updateTimestamp(sal_Int32 column, const DateTime& /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateTimestamp", + *this); +} + +void SAL_CALL OPreparedResultSet::updateBinaryStream(sal_Int32 column, + const uno::Reference<XInputStream>& /* x */, + sal_Int32 /* length */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException( + "OPreparedResultSet::updateBinaryStream", *this); +} + +void SAL_CALL OPreparedResultSet::updateCharacterStream(sal_Int32 column, + const uno::Reference<XInputStream>& /* x */, + sal_Int32 /* length */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException( + "OPreparedResultSet::updateCharacterStream", *this); +} + +void SAL_CALL OPreparedResultSet::refreshRow() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::refreshRow", + *this); +} + +void SAL_CALL OPreparedResultSet::updateObject(sal_Int32 column, const Any& /* x */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateObject", + *this); +} + +void SAL_CALL OPreparedResultSet::updateNumericObject(sal_Int32 column, const Any& /* x */, + sal_Int32 /* scale */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); + mysqlc_sdbc_driver::throwFeatureNotImplementedException( + "OPreparedResultSet::updateNumericObject", *this); +} + +// XRowLocate +Any SAL_CALL OPreparedResultSet::getBookmark() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + Any aRet = Any(); + + // if you don't want to support bookmark you must remove the XRowLocate interface + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getBookmark", + *this); + + return aRet; +} + +sal_Bool SAL_CALL OPreparedResultSet::moveToBookmark(const Any& /* bookmark */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +sal_Bool SAL_CALL OPreparedResultSet::moveRelativeToBookmark(const Any& /* bookmark */, + sal_Int32 /* rows */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException( + "OPreparedResultSet::moveRelativeToBookmark", *this); + return false; +} + +sal_Int32 SAL_CALL OPreparedResultSet::compareBookmarks(const Any& /* n1 */, const Any& /* n2 */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::compareBookmarks", + *this); + + return CompareBookmark::NOT_EQUAL; +} + +sal_Bool SAL_CALL OPreparedResultSet::hasOrderedBookmarks() { return false; } + +sal_Int32 SAL_CALL OPreparedResultSet::hashBookmark(const Any& /* bookmark */) +{ + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::hashBookmark", + *this); + return 0; +} + +// XDeleteRows +uno::Sequence<sal_Int32> + SAL_CALL OPreparedResultSet::deleteRows(const uno::Sequence<Any>& /* rows */) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed); + uno::Sequence<sal_Int32> aRet = uno::Sequence<sal_Int32>(); + + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::deleteRows", + *this); + return aRet; +} + +IPropertyArrayHelper* OPreparedResultSet::createArrayHelper() const +{ + uno::Sequence<Property> aProps(5); + Property* pProperties = aProps.getArray(); + sal_Int32 nPos = 0; + pProperties[nPos++] = Property("FetchDirection", PROPERTY_ID_FETCHDIRECTION, + cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] + = Property("FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = Property("IsBookmarkable", PROPERTY_ID_ISBOOKMARKABLE, + cppu::UnoType<bool>::get(), PropertyAttribute::READONLY); + pProperties[nPos++] = Property("ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY, + cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY); + pProperties[nPos++] = Property("ResultSetType", PROPERTY_ID_RESULTSETTYPE, + cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY); + + return new OPropertyArrayHelper(aProps); +} + +IPropertyArrayHelper& OPreparedResultSet::getInfoHelper() { return *getArrayHelper(); } + +sal_Bool OPreparedResultSet::convertFastPropertyValue(Any& /* rConvertedValue */, + Any& /* rOldValue */, sal_Int32 nHandle, + const Any& /* rValue */) +{ + switch (nHandle) + { + case PROPERTY_ID_ISBOOKMARKABLE: + case PROPERTY_ID_CURSORNAME: + case PROPERTY_ID_RESULTSETCONCURRENCY: + case PROPERTY_ID_RESULTSETTYPE: + throw css::lang::IllegalArgumentException(); + case PROPERTY_ID_FETCHDIRECTION: + case PROPERTY_ID_FETCHSIZE: + default:; + } + return false; +} + +void OPreparedResultSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, + const Any& /* rValue */) +{ + switch (nHandle) + { + case PROPERTY_ID_ISBOOKMARKABLE: + case PROPERTY_ID_CURSORNAME: + case PROPERTY_ID_RESULTSETCONCURRENCY: + case PROPERTY_ID_RESULTSETTYPE: + throw uno::Exception("cannot set prop " + rtl::OUString::number(nHandle), nullptr); + case PROPERTY_ID_FETCHDIRECTION: + break; + case PROPERTY_ID_FETCHSIZE: + break; + default:; + } +} + +void OPreparedResultSet::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const +{ + switch (nHandle) + { + case PROPERTY_ID_ISBOOKMARKABLE: + _rValue <<= false; + break; + case PROPERTY_ID_CURSORNAME: + break; + case PROPERTY_ID_RESULTSETCONCURRENCY: + _rValue <<= ResultSetConcurrency::READ_ONLY; + break; + case PROPERTY_ID_RESULTSETTYPE: + _rValue <<= ResultSetType::SCROLL_INSENSITIVE; + break; + case PROPERTY_ID_FETCHDIRECTION: + _rValue <<= FetchDirection::FORWARD; + break; + case PROPERTY_ID_FETCHSIZE: + _rValue <<= sal_Int32(50); + break; + ; + default:; + } +} + +void SAL_CALL OPreparedResultSet::acquire() throw() { OPreparedResultSet_BASE::acquire(); } + +void SAL_CALL OPreparedResultSet::release() throw() { OPreparedResultSet_BASE::release(); } + +css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL OPreparedResultSet::getPropertySetInfo() +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} + +void OPreparedResultSet::checkColumnIndex(sal_Int32 index) +{ + if (index < 1 || index > static_cast<int>(m_nFieldCount)) + { + /* static object for efficiency or thread safety is a problem ? */ + throw SQLException("index out of range", *this, rtl::OUString(), 1, Any()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_prepared_resultset.hxx b/mysqlc/source/mysqlc_prepared_resultset.hxx new file mode 100644 index 000000000000..db3e1034cb76 --- /dev/null +++ b/mysqlc/source/mysqlc_prepared_resultset.hxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you 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 http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSET_HXX +#define INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSET_HXX + +#include "mysqlc_preparedstatement.hxx" +#include "mysqlc_statement.hxx" +#include "mysqlc_subcomponent.hxx" +#include "mysqlc_connection.hxx" + +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <cppuhelper/compbase12.hxx> + +namespace connectivity +{ +namespace mysqlc +{ +using ::com::sun::star::sdbc::SQLException; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::RuntimeException; + +typedef ::cppu::WeakComponentImplHelper12< + css::sdbc::XResultSet, css::sdbc::XRow, css::sdbc::XResultSetMetaDataSupplier, + css::util::XCancellable, css::sdbc::XWarningsSupplier, css::sdbc::XResultSetUpdate, + css::sdbc::XRowUpdate, css::sdbcx::XRowLocate, css::sdbcx::XDeleteRows, css::sdbc::XCloseable, + css::sdbc::XColumnLocate, css::lang::XServiceInfo> + OPreparedResultSet_BASE; + +class OPreparedResultSet final : public OBase_Mutex, + public OPreparedResultSet_BASE, + public ::cppu::OPropertySetHelper, + public OPropertyArrayUsageHelper<OPreparedResultSet> +{ + OConnection& m_rConnection; + css::uno::WeakReferenceHelper m_aStatement; + css::uno::Reference<css::sdbc::XResultSetMetaData> m_xMetaData; + MYSQL_RES* m_pResult; + MYSQL_STMT* m_pStmt; + rtl_TextEncoding m_encoding; + sal_Int32 m_nCurrentField = 0; + sal_Int32 m_nFieldCount; + + // Use c style arrays, because we have to work with pointers + // on these. + MYSQL_BIND* m_aData = nullptr; + MYSQL_FIELD* m_aFields = nullptr; + BindMetaData* m_aMetaData = nullptr; + + bool m_bWasNull = false; + + // OPropertyArrayUsageHelper + ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE; + // OPropertySetHelper + ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE; + + sal_Bool SAL_CALL convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, + sal_Int32 nHandle, const Any& rValue) SAL_OVERRIDE; + + void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, + const Any& rValue) SAL_OVERRIDE; + + void SAL_CALL getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE; + + // you can't delete objects of this type + virtual ~OPreparedResultSet(); + +public: + virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE; + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const& ServiceName) SAL_OVERRIDE; + + virtual css::uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE; + + OPreparedResultSet(OConnection& rConn, OPreparedStatement* pStmt, MYSQL_STMT* pMyStmt); + + // ::cppu::OComponentHelper + void SAL_CALL disposing() SAL_OVERRIDE; + + // XInterface + Any SAL_CALL queryInterface(const css::uno::Type& rType) SAL_OVERRIDE; + + void SAL_CALL acquire() throw() SAL_OVERRIDE; + void SAL_CALL release() throw() SAL_OVERRIDE; + + //XTypeProvider + css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() SAL_OVERRIDE; + + // XPropertySet + css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() SAL_OVERRIDE; + + // XResultSet + sal_Bool SAL_CALL next() SAL_OVERRIDE; + sal_Bool SAL_CALL isBeforeFirst() SAL_OVERRIDE; + sal_Bool SAL_CALL isAfterLast() SAL_OVERRIDE; + sal_Bool SAL_CALL isFirst() SAL_OVERRIDE; + sal_Bool SAL_CALL isLast() SAL_OVERRIDE; + + void SAL_CALL beforeFirst() SAL_OVERRIDE; + void SAL_CALL afterLast() SAL_OVERRIDE; + + sal_Bool SAL_CALL first() SAL_OVERRIDE; + sal_Bool SAL_CALL last() SAL_OVERRIDE; + + sal_Int32 SAL_CALL getRow() SAL_OVERRIDE; + + sal_Bool SAL_CALL absolute(sal_Int32 row) SAL_OVERRIDE; + sal_Bool SAL_CALL relative(sal_Int32 rows) SAL_OVERRIDE; + sal_Bool SAL_CALL previous() SAL_OVERRIDE; + + void SAL_CALL refreshRow() SAL_OVERRIDE; + + sal_Bool SAL_CALL rowUpdated() SAL_OVERRIDE; + sal_Bool SAL_CALL rowInserted() SAL_OVERRIDE; + sal_Bool SAL_CALL rowDeleted() SAL_OVERRIDE; + + css::uno::Reference<css::uno::XInterface> SAL_CALL getStatement() SAL_OVERRIDE; + // XRow + sal_Bool SAL_CALL wasNull() SAL_OVERRIDE; + + rtl::OUString SAL_CALL getString(sal_Int32 column) SAL_OVERRIDE; + + sal_Bool SAL_CALL getBoolean(sal_Int32 column) SAL_OVERRIDE; + sal_Int8 SAL_CALL getByte(sal_Int32 column) SAL_OVERRIDE; + sal_Int16 SAL_CALL getShort(sal_Int32 column) SAL_OVERRIDE; + sal_Int32 SAL_CALL getInt(sal_Int32 column) SAL_OVERRIDE; + sal_Int64 SAL_CALL getLong(sal_Int32 column) SAL_OVERRIDE; + + float SAL_CALL getFloat(sal_Int32 column) SAL_OVERRIDE; + double SAL_CALL getDouble(sal_Int32 column) SAL_OVERRIDE; + + css::uno::Sequence<sal_Int8> SAL_CALL getBytes(sal_Int32 column) SAL_OVERRIDE; + css::util::Date SAL_CALL getDate(sal_Int32 column) SAL_OVERRIDE; + css::util::Time SAL_CALL getTime(sal_Int32 column) SAL_OVERRIDE; + css::util::DateTime SAL_CALL getTimestamp(sal_Int32 column) SAL_OVERRIDE; + + css::uno::Reference<css::io::XInputStream> + SAL_CALL getBinaryStream(sal_Int32 column) SAL_OVERRIDE; + css::uno::Reference<css::io::XInputStream> + SAL_CALL getCharacterStream(sal_Int32 column) SAL_OVERRIDE; + + Any SAL_CALL getObject(sal_Int32 column, const my_XNameAccessRef& typeMap) SAL_OVERRIDE; + + css::uno::Reference<css::sdbc::XRef> SAL_CALL getRef(sal_Int32 column) SAL_OVERRIDE; + css::uno::Reference<css::sdbc::XBlob> SAL_CALL getBlob(sal_Int32 column) SAL_OVERRIDE; + css::uno::Reference<css::sdbc::XClob> SAL_CALL getClob(sal_Int32 column) SAL_OVERRIDE; + css::uno::Reference<css::sdbc::XArray> SAL_CALL getArray(sal_Int32 column) SAL_OVERRIDE; + + // XResultSetMetaDataSupplier + css::uno::Reference<css::sdbc::XResultSetMetaData> SAL_CALL getMetaData() SAL_OVERRIDE; + + // XCancellable + void SAL_CALL cancel() SAL_OVERRIDE; + + // XCloseable + void SAL_CALL close() SAL_OVERRIDE; + + // XWarningsSupplier + Any SAL_CALL getWarnings() SAL_OVERRIDE; + + void SAL_CALL clearWarnings() SAL_OVERRIDE; + + // XResultSetUpdate + void SAL_CALL insertRow() SAL_OVERRIDE; + void SAL_CALL updateRow() SAL_OVERRIDE; + void SAL_CALL deleteRow() SAL_OVERRIDE; + void SAL_CALL cancelRowUpdates() SAL_OVERRIDE; + void SAL_CALL moveToInsertRow() SAL_OVERRIDE; + void SAL_CALL moveToCurrentRow() SAL_OVERRIDE; + + // XRowUpdate + void SAL_CALL updateNull(sal_Int32 column) SAL_OVERRIDE; + void SAL_CALL updateBoolean(sal_Int32 column, sal_Bool x) SAL_OVERRIDE; + void SAL_CALL updateByte(sal_Int32 column, sal_Int8 x) SAL_OVERRIDE; + void SAL_CALL updateShort(sal_Int32 column, sal_Int16 x) SAL_OVERRIDE; + void SAL_CALL updateInt(sal_Int32 column, sal_Int32 x) SAL_OVERRIDE; + void SAL_CALL updateLong(sal_Int32 column, sal_Int64 x) SAL_OVERRIDE; + void SAL_CALL updateFloat(sal_Int32 column, float x) SAL_OVERRIDE; + void SAL_CALL updateDouble(sal_Int32 column, double x) SAL_OVERRIDE; + void SAL_CALL updateString(sal_Int32 column, const rtl::OUString& x) SAL_OVERRIDE; + void SAL_CALL updateBytes(sal_Int32 column, const css::uno::Sequence<sal_Int8>& x) SAL_OVERRIDE; + void SAL_CALL updateDate(sal_Int32 column, const css::util::Date& x) SAL_OVERRIDE; + void SAL_CALL updateTime(sal_Int32 column, const css::util::Time& x) SAL_OVERRIDE; + void SAL_CALL updateTimestamp(sal_Int32 column, const css::util::DateTime& x) SAL_OVERRIDE; + void SAL_CALL updateBinaryStream(sal_Int32 column, + const css::uno::Reference<css::io::XInputStream>& x, + sal_Int32 length) SAL_OVERRIDE; + void SAL_CALL updateCharacterStream(sal_Int32 column, + const css::uno::Reference<css::io::XInputStream>& x, + sal_Int32 length) SAL_OVERRIDE; + void SAL_CALL updateObject(sal_Int32 column, const Any& x) SAL_OVERRIDE; + void SAL_CALL updateNumericObject(sal_Int32 column, const Any& x, sal_Int32 scale) SAL_OVERRIDE; + + // XColumnLocate + sal_Int32 SAL_CALL findColumn(const rtl::OUString& columnName) SAL_OVERRIDE; + + // XRowLocate + Any SAL_CALL getBookmark() SAL_OVERRIDE; + + sal_Bool SAL_CALL moveToBookmark(const Any& bookmark) SAL_OVERRIDE; + sal_Bool SAL_CALL moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows) SAL_OVERRIDE; + sal_Int32 SAL_CALL compareBookmarks(const Any& first, const Any& second) SAL_OVERRIDE; + sal_Bool SAL_CALL hasOrderedBookmarks() SAL_OVERRIDE; + sal_Int32 SAL_CALL hashBookmark(const Any& bookmark) SAL_OVERRIDE; + + // XDeleteRows + css::uno::Sequence<sal_Int32> + SAL_CALL deleteRows(const css::uno::Sequence<Any>& rows) SAL_OVERRIDE; + + /// @throws SQLException + /// @throws RuntimeException + void checkColumnIndex(sal_Int32 index); + +private: + using ::cppu::OPropertySetHelper::getFastPropertyValue; +}; +} /* mysqlc */ +} /* connectivity */ +#endif // CONNECTIVITY_SRESULTSET_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_preparedstatement.cxx b/mysqlc/source/mysqlc_preparedstatement.cxx index fae2a6642724..88b899a55814 100644 --- a/mysqlc/source/mysqlc_preparedstatement.cxx +++ b/mysqlc/source/mysqlc_preparedstatement.cxx @@ -18,6 +18,7 @@ */ #include "mysqlc_general.hxx" +#include "mysqlc_prepared_resultset.hxx" #include "mysqlc_preparedstatement.hxx" #include "mysqlc_propertyids.hxx" #include "mysqlc_resultsetmetadata.hxx" @@ -48,13 +49,6 @@ using namespace com::sun::star::io; using namespace com::sun::star::util; using ::osl::MutexGuard; - -static inline char * my_i_to_a(char * buf, size_t buf_size, int a) -{ - snprintf(buf, buf_size, "%d", a); - return buf; -} - rtl::OUString OPreparedStatement::getImplementationName() { return rtl::OUString("com.sun.star.sdbcx.mysqlc.PreparedStatement"); @@ -72,15 +66,22 @@ sal_Bool OPreparedStatement::supportsService(rtl::OUString const & ServiceName) return cppu::supportsService(this, ServiceName); } -OPreparedStatement::OPreparedStatement(OConnection* _pConnection, sql::PreparedStatement * _cppPrepStmt) - :OCommonStatement(_pConnection, _cppPrepStmt) +OPreparedStatement::OPreparedStatement(OConnection* _pConnection, MYSQL_STMT* pStmt) + :OCommonStatement(_pConnection) + ,m_pStmt(pStmt) { - m_xConnection = _pConnection; - - try { - m_paramCount = static_cast<sql::PreparedStatement *>(cppStatement.get())->getParameterMetaData()->getParameterCount(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + m_paramCount = mysql_stmt_param_count(m_pStmt); + m_binds.reserve(m_paramCount); + m_bindMetas.reserve(m_paramCount); + for(unsigned i=0; i<m_paramCount; ++i) + { + MYSQL_BIND bind; + memset(&bind, 0, sizeof(MYSQL_BIND)); + m_binds.push_back(bind); + m_bindMetas.push_back(BindMetaData{}); + m_binds.back().is_null = &m_bindMetas.back().is_null; + m_binds.back().length = &m_bindMetas.back().length; + m_binds.back().buffer = nullptr; } } @@ -119,17 +120,12 @@ Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData() MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); - try { - if (!m_xMetaData.is()) { - m_xMetaData = new OResultSetMetaData( - static_cast<sql::PreparedStatement *>(cppStatement.get())->getMetaData(), - getOwnConnection()->getConnectionEncoding() - ); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + if (!m_xMetaData.is()) + { + MYSQL_RES* pRes = mysql_stmt_result_metadata(m_pStmt); + // TODO warning or error if no meta data. + m_xMetaData = new OResultSetMetaData( *m_xConnection.get(), pRes, + getOwnConnection()->getConnectionEncoding()); } return m_xMetaData; } @@ -139,16 +135,14 @@ void SAL_CALL OPreparedStatement::close() MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); - try { - clearWarnings(); - clearParameters(); - OCommonStatement::close(); - } catch (const SQLException &) { - // If we get an error, ignore + if(mysql_stmt_close(m_pStmt)) + { + SAL_WARN("connectivity", "failed to close mysql prepared statement"); } - - // Remove this Statement object from the Connection object's - // list + m_pStmt = nullptr; // it's deallocated already + clearWarnings(); + clearParameters(); + OCommonStatement::close(); } sal_Bool SAL_CALL OPreparedStatement::execute() @@ -156,13 +150,22 @@ sal_Bool SAL_CALL OPreparedStatement::execute() MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); - bool success = false; - try { - success = static_cast<sql::PreparedStatement *>(cppStatement.get())->execute(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + if(!m_binds.empty() && mysql_stmt_bind_param(m_pStmt, m_binds.data())) + { + MYSQL* pMysql = m_xConnection.get()->getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), + mysql_errno(pMysql), *this, m_xConnection.get()->getConnectionEncoding()); } - return success; + + int nFail = mysql_stmt_execute(m_pStmt); + if(nFail != 0) + { + MYSQL* pMysql = m_xConnection.get()->getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), + mysql_errno(pMysql), *this, m_xConnection.get()->getConnectionEncoding()); + } + + return !nFail; } sal_Int32 SAL_CALL OPreparedStatement::executeUpdate() @@ -170,12 +173,23 @@ sal_Int32 SAL_CALL OPreparedStatement::executeUpdate() MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); - sal_Int32 affectedRows = 0; - try { - affectedRows = static_cast<sql::PreparedStatement *>(cppStatement.get())->executeUpdate(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + if(!m_binds.empty() && mysql_stmt_bind_param(m_pStmt, m_binds.data())) + { + MYSQL* pMysql = m_xConnection.get()->getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), + mysql_errno(pMysql), *this, m_xConnection.get()->getConnectionEncoding()); } + + int nFail = mysql_stmt_execute(m_pStmt); + + if(nFail != 0) + { + MYSQL* pMysql = m_xConnection.get()->getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), + mysql_errno(pMysql), *this, m_xConnection.get()->getConnectionEncoding()); + } + + sal_Int32 affectedRows = mysql_stmt_affected_rows(m_pStmt); return affectedRows; } @@ -185,14 +199,13 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 parameter, const rtl::OUSt checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - std::string stringie(rtl::OUStringToOString(x, m_xConnection->getConnectionEncoding()).getStr()); - static_cast<sql::PreparedStatement *>(cppStatement.get())->setString(parameter, stringie); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::clearParameters", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + rtl::OString stringie(rtl::OUStringToOString(x, + m_xConnection->getConnectionEncoding())); + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_STRING; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, stringie.getStr(), MYSQL_TYPE_STRING, stringie.getLength()); + m_bindMetas[nIndex].is_null = 0; + m_bindMetas[nIndex].length = stringie.getLength(); } Reference< XConnection > SAL_CALL OPreparedStatement::getConnection() @@ -208,13 +221,24 @@ Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery() MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); - Reference< XResultSet > xResultSet; - try { - sql::ResultSet * res = static_cast<sql::PreparedStatement *>(cppStatement.get())->executeQuery(); - xResultSet = new OResultSet(this, res, getOwnConnection()->getConnectionEncoding()); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + if(!m_binds.empty() && mysql_stmt_bind_param(m_pStmt, m_binds.data())) + { + MYSQL* pMysql = m_xConnection.get()->getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), + mysql_errno(pMysql), *this, m_xConnection.get()->getConnectionEncoding()); } + + int nFail = mysql_stmt_execute(m_pStmt); + + if(nFail != 0) + { + MYSQL* pMysql = m_xConnection.get()->getMysqlConnection(); + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), + mysql_errno(pMysql), *this, m_xConnection.get()->getConnectionEncoding()); + } + + Reference< XResultSet > xResultSet; + xResultSet = new OPreparedResultSet(*m_xConnection.get(), this, m_pStmt); return xResultSet; } @@ -224,13 +248,10 @@ void SAL_CALL OPreparedStatement::setBoolean(sal_Int32 parameter, sal_Bool x) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setBoolean(parameter, x); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setBoolean", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_TINY; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_TINY); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setByte(sal_Int32 parameter, sal_Int8 x) @@ -239,13 +260,10 @@ void SAL_CALL OPreparedStatement::setByte(sal_Int32 parameter, sal_Int8 x) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setInt(parameter, x); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setByte", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_TINY; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_TINY); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setDate(sal_Int32 parameter, const Date& aData) @@ -254,21 +272,16 @@ void SAL_CALL OPreparedStatement::setDate(sal_Int32 parameter, const Date& aData checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - std::string dateStr; - char buf[20]; - dateStr.append(my_i_to_a(buf, sizeof(buf)-1, aData.Year)); - dateStr.append("-", 1); - dateStr.append(my_i_to_a(buf, sizeof(buf)-1, aData.Month)); - dateStr.append("-", 1); - dateStr.append(my_i_to_a(buf, sizeof(buf)-1, aData.Day)); - - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setDateTime(parameter, dateStr); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setDate", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + MYSQL_TIME my_time; + + my_time.year = aData.Year; + my_time.month = aData.Month; + my_time.day = aData.Day; + + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_DATE; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &my_time, MYSQL_TYPE_DATE); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setTime(sal_Int32 parameter, const Time& aVal) @@ -277,21 +290,16 @@ void SAL_CALL OPreparedStatement::setTime(sal_Int32 parameter, const Time& aVal) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - std::string timeStr; - char buf[20]; - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Hours)); - timeStr.append(":", 1); - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Minutes)); - timeStr.append(":", 1); - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Seconds)); - - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setDateTime(parameter, timeStr); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setTime", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + MYSQL_TIME my_time; + + my_time.hour = aVal.Hours; + my_time.minute = aVal.Minutes; + my_time.second = aVal.Seconds; + + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_TIME; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &my_time, MYSQL_TYPE_TIME); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setTimestamp(sal_Int32 parameter, const DateTime& aVal) @@ -300,29 +308,19 @@ void SAL_CALL OPreparedStatement::setTimestamp(sal_Int32 parameter, const DateTi checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - std::string timeStr; - char buf[20]; - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Year)); - timeStr.append("-", 1); - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Month)); - timeStr.append("-", 1); - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Day)); - - timeStr.append(" ", 1); - - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Hours)); - timeStr.append(":", 1); - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Minutes)); - timeStr.append(":", 1); - timeStr.append(my_i_to_a(buf, sizeof(buf)-1, aVal.Seconds)); - - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setDateTime(parameter, timeStr); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setTimestamp", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + MYSQL_TIME my_time; + + my_time.hour = aVal.Hours; + my_time.minute = aVal.Minutes; + my_time.second = aVal.Seconds; + my_time.year = aVal.Year; + my_time.month = aVal.Month; + my_time.day = aVal.Day; + + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_TIME; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &my_time, MYSQL_TYPE_DATETIME); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setDouble(sal_Int32 parameter, double x) @@ -331,13 +329,10 @@ void SAL_CALL OPreparedStatement::setDouble(sal_Int32 parameter, double x) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setDouble(parameter, x); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setDouble", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_DOUBLE; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_DOUBLE); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setFloat(sal_Int32 parameter, float x) @@ -346,13 +341,10 @@ void SAL_CALL OPreparedStatement::setFloat(sal_Int32 parameter, float x) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setDouble(parameter, x); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setFloat", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_FLOAT; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_FLOAT); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setInt(sal_Int32 parameter, sal_Int32 x) @@ -361,13 +353,10 @@ void SAL_CALL OPreparedStatement::setInt(sal_Int32 parameter, sal_Int32 x) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setInt(parameter, x); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setInt", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_LONG; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_LONG); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setLong(sal_Int32 parameter, sal_Int64 aVal) @@ -376,28 +365,22 @@ void SAL_CALL OPreparedStatement::setLong(sal_Int32 parameter, sal_Int64 aVal) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setInt64(parameter, aVal); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setLong", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_LONGLONG; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &aVal, MYSQL_TYPE_LONGLONG); + m_bindMetas[nIndex].is_null = 0; } -void SAL_CALL OPreparedStatement::setNull(sal_Int32 parameter, sal_Int32 sqlType) +void SAL_CALL OPreparedStatement::setNull(sal_Int32 parameter, sal_Int32 /*sqlType*/) { MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setNull(parameter, sqlType); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setNull", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_bindMetas[nIndex].is_null = 1; + free(m_binds[nIndex].buffer); + m_binds[nIndex].buffer = nullptr; } void SAL_CALL OPreparedStatement::setClob(sal_Int32 parameter, const Reference< XClob >& /* x */) @@ -436,88 +419,42 @@ void SAL_CALL OPreparedStatement::setRef(sal_Int32 parameter, const Reference< X mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setRef", *this); } -namespace -{ - template < class COMPLEXTYPE > - bool impl_setObject( const Reference< XParameters >& _rxParam, sal_Int32 _parameterIndex, const Any& _value, - void ( SAL_CALL XParameters::*Setter )( sal_Int32, const COMPLEXTYPE& ), bool _throwIfNotExtractable ) - { - COMPLEXTYPE aValue; - if ( _value >>= aValue ) - { - (_rxParam.get()->*Setter)( _parameterIndex, aValue ); - return true; - } - - if ( _throwIfNotExtractable ) - mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", _rxParam ); - return false; - } - - template < class INTTYPE > - void impl_setObject( const Reference< XParameters >& _rxParam, sal_Int32 _parameterIndex, const Any& _value, - void ( SAL_CALL XParameters::*Setter )( sal_Int32, INTTYPE ) ) - { - sal_Int32 nValue(0); - if ( !( _value >>= nValue ) ) - mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", _rxParam ); - (_rxParam.get()->*Setter)( _parameterIndex, static_cast<INTTYPE>(nValue) ); - } -} - -void SAL_CALL OPreparedStatement::setObjectWithInfo(sal_Int32 _parameterIndex, const Any& _value, sal_Int32 _targetSqlType, sal_Int32 /* scale */) +void SAL_CALL OPreparedStatement::setObjectWithInfo(sal_Int32 parameterIndex, const Any& value, sal_Int32 targetSqlType, sal_Int32 /* scale */) { checkDisposed(OPreparedStatement::rBHelper.bDisposed); MutexGuard aGuard(m_aMutex); - checkParameterIndex( _parameterIndex ); + checkParameterIndex( parameterIndex ); - if ( !_value.hasValue() ) + const sal_Int32 nIndex = parameterIndex - 1; + if ( !value.hasValue() ) { - setNull( _parameterIndex, _targetSqlType ); + free(m_binds[nIndex].buffer); + m_binds[nIndex].buffer = nullptr; + m_bindMetas[parameterIndex-1].is_null = 1; return; } - switch ( _targetSqlType ) + switch ( targetSqlType ) { case DataType::DECIMAL: case DataType::NUMERIC: { double nValue(0); - if ( _value >>= nValue ) + if ( value >>= nValue ) { - setDouble( _parameterIndex, nValue ); + setDouble( parameterIndex, nValue ); break; } -#if defined __GNUC__ && __GNUC__ >= 7 - [[fallthrough]]; -#else - BOOST_FALLTHROUGH; -#endif - } - - case DataType::CHAR: - case DataType::VARCHAR: - case DataType::LONGVARCHAR: - impl_setObject( this, _parameterIndex, _value, &XParameters::setString, true ); - break; - - case DataType::BIGINT: - { - sal_Int64 nValue = 0; - if ( !( _value >>= nValue ) ) - mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", *this ); - setLong( _parameterIndex, nValue ); - } - break; - - case DataType::FLOAT: - case DataType::REAL: - { - float nValue = 0; - if ( _value >>= nValue ) + else { - setFloat(_parameterIndex,nValue); - break; + rtl::OUString sValue; + if( value >>= sValue ) + { + m_binds[nIndex].buffer_type = MYSQL_TYPE_NEWDECIMAL; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, sValue.getStr(), MYSQL_TYPE_LONGLONG, sValue.getLength()); + m_bindMetas[nIndex].is_null = 0; + } + } #if defined __GNUC__ && __GNUC__ >= 7 [[fallthrough]]; @@ -526,78 +463,7 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo(sal_Int32 _parameterIndex, c #endif } - case DataType::DOUBLE: - { - double nValue(0); - if ( !( _value >>= nValue ) ) - mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", *this ); - setDouble( _parameterIndex, nValue ); - } - break; - - case DataType::DATE: - impl_setObject( this, _parameterIndex, _value, &XParameters::setDate, true ); - break; - - case DataType::TIME: - impl_setObject( this, _parameterIndex, _value, &XParameters::setTime, true ); - break; - - case DataType::TIMESTAMP: - impl_setObject( this, _parameterIndex, _value, &XParameters::setTimestamp, true ); - break; - - case DataType::BINARY: - case DataType::VARBINARY: - case DataType::LONGVARBINARY: - { - if ( impl_setObject( this, _parameterIndex, _value, &XParameters::setBytes, false ) - || impl_setObject( this, _parameterIndex, _value, &XParameters::setBlob, false ) - || impl_setObject( this, _parameterIndex, _value, &XParameters::setClob, false ) - ) - break; - - Reference< css::io::XInputStream > xBinStream; - if ( _value >>= xBinStream ) - { - setBinaryStream( _parameterIndex, xBinStream, xBinStream->available() ); - break; - } - - mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", *this ); - } - break; - - case DataType::BIT: - case DataType::BOOLEAN: - { - bool bValue( false ); - if ( _value >>= bValue ) - { - setBoolean( _parameterIndex, bValue ); - break; - } - sal_Int32 nValue( 0 ); - if ( _value >>= nValue ) - { - setBoolean( _parameterIndex, ( nValue != 0 ) ); - break; - } - mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", *this ); - } - break; - - case DataType::TINYINT: - impl_setObject( this, _parameterIndex, _value, &XParameters::setByte ); - break; - - case DataType::SMALLINT: - impl_setObject( this, _parameterIndex, _value, &XParameters::setShort ); - break; - - case DataType::INTEGER: - impl_setObject( this, _parameterIndex, _value, &XParameters::setInt ); - break; + // TODO other types default: mysqlc_sdbc_driver::throwInvalidArgumentException( "OPreparedStatement::setObjectWithInfo", *this ); @@ -629,13 +495,10 @@ void SAL_CALL OPreparedStatement::setShort(sal_Int32 parameter, sal_Int16 x) checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setInt(parameter, x); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setShort", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_SHORT; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_SHORT); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setBytes(sal_Int32 parameter, const Sequence< sal_Int8 >& x) @@ -644,14 +507,10 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 parameter, const Sequence< checkDisposed(OPreparedStatement::rBHelper.bDisposed); checkParameterIndex(parameter); - std::string blobby(reinterpret_cast<char const *>(x.getConstArray()), x.getLength()); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->setString(parameter, blobby); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setBytes", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } + const sal_Int32 nIndex = parameter-1; + m_binds[nIndex].buffer_type = MYSQL_TYPE_BLOB; // FIXME + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_BLOB); + m_bindMetas[nIndex].is_null = 0; } void SAL_CALL OPreparedStatement::setCharacterStream(sal_Int32 parameter, @@ -681,12 +540,11 @@ void SAL_CALL OPreparedStatement::clearParameters() MutexGuard aGuard(m_aMutex); checkDisposed(OPreparedStatement::rBHelper.bDisposed); - try { - static_cast<sql::PreparedStatement *>(cppStatement.get())->clearParameters(); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::clearParameters", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + for(size_t i=0; i<m_binds.size(); ++i) + { + m_bindMetas[i].is_null = 1; + free(m_binds[i].buffer); + m_binds[i].buffer = nullptr; } } @@ -731,14 +589,4 @@ void OPreparedStatement::checkParameterIndex(sal_Int32 column) } } - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_preparedstatement.hxx b/mysqlc/source/mysqlc_preparedstatement.hxx index b82f88ecac38..7305c0dd005b 100644 --- a/mysqlc/source/mysqlc_preparedstatement.hxx +++ b/mysqlc/source/mysqlc_preparedstatement.hxx @@ -41,6 +41,13 @@ namespace connectivity using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::sdbc::XResultSetMetaData; + struct BindMetaData + { + char is_null = 0; + unsigned long length = 0; + char error = 0; + }; + typedef ::cppu::ImplHelper5< css::sdbc::XPreparedStatement, css::sdbc::XParameters, css::sdbc::XPreparedBatchExecution, @@ -50,8 +57,11 @@ namespace connectivity class OPreparedStatement final : public OCommonStatement, public OPreparedStatement_BASE { - unsigned int m_paramCount; // number of placeholders + unsigned int m_paramCount = 0; // number of placeholders Reference< XResultSetMetaData > m_xMetaData; + MYSQL_STMT* m_pStmt; + std::vector<MYSQL_BIND> m_binds; + std::vector<BindMetaData> m_bindMetas; void checkParameterIndex(sal_Int32 parameter); @@ -68,7 +78,7 @@ namespace connectivity getSupportedServiceNames() SAL_OVERRIDE; - OPreparedStatement(OConnection* _pConnection, sql::PreparedStatement * cppPrepStmt); + OPreparedStatement(OConnection* _pConnection, MYSQL_STMT* pStmt); //XInterface Any SAL_CALL queryInterface(const Type & rType) SAL_OVERRIDE; @@ -150,14 +160,4 @@ namespace connectivity } /* connectivity */ #endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_PREPAREDSTATEMENT_HXX -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_resultset.cxx b/mysqlc/source/mysqlc_resultset.cxx index faa9357f3cae..252f6633089d 100644 --- a/mysqlc/source/mysqlc_resultset.cxx +++ b/mysqlc/source/mysqlc_resultset.cxx @@ -32,9 +32,14 @@ #include <cppuhelper/supportsservice.hxx> #include <cppuhelper/typeprovider.hxx> +using namespace rtl; +#include <comphelper/string.hxx> + +#include <cstdlib> + using namespace connectivity::mysqlc; using namespace cppu; -using namespace com::sun::star::uno; +using namespace com::sun::star; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::sdbc; @@ -42,6 +47,7 @@ using namespace com::sun::star::sdbcx; using namespace com::sun::star::container; using namespace com::sun::star::io; using namespace com::sun::star::util; +using namespace ::comphelper; using ::osl::MutexGuard; #include <cppconn/resultset.h> @@ -49,14 +55,36 @@ using ::osl::MutexGuard; #include <stdio.h> +namespace +{ + // copied from string misc, it should be replaced when library is not an + // extension anymore + std::vector<OUString> lcl_split(const OUString& rStr, sal_Unicode cSeparator) + { + std::vector< OUString > vec; + sal_Int32 idx = 0; + do + { + OUString kw = + rStr.getToken(0, cSeparator, idx); + kw = kw.trim(); + if (!kw.isEmpty()) + { + vec.push_back(kw); + } + } while (idx >= 0); + return vec; + } +} + rtl::OUString SAL_CALL OResultSet::getImplementationName() { return rtl::OUString( "com.sun.star.sdbcx.mysqlc.ResultSet" ); } -Sequence< rtl::OUString > SAL_CALL OResultSet::getSupportedServiceNames() +uno::Sequence< rtl::OUString > SAL_CALL OResultSet::getSupportedServiceNames() { - Sequence< rtl::OUString > aSupported(2); + uno::Sequence< rtl::OUString > aSupported(2); aSupported[0] = "com.sun.star.sdbc.ResultSet"; aSupported[1] = "com.sun.star.sdbcx.ResultSet"; return aSupported; @@ -67,21 +95,18 @@ sal_Bool SAL_CALL OResultSet::supportsService(const rtl::OUString& _rServiceName return cppu::supportsService(this, _rServiceName); } -OResultSet::OResultSet(OCommonStatement * pStmt, sql::ResultSet * result, rtl_TextEncoding _encoding ) +OResultSet::OResultSet(OConnection& rConn, OCommonStatement * pStmt, MYSQL_RES * pResult, rtl_TextEncoding _encoding ) : OResultSet_BASE(m_aMutex) ,OPropertySetHelper(OResultSet_BASE::rBHelper) + ,m_rConnection(rConn) + ,m_pMysql(rConn.getMysqlConnection()) ,m_aStatement(static_cast<OWeakObject*>(pStmt)) ,m_xMetaData(nullptr) - ,m_result(result) + ,m_pResult(pResult) ,fieldCount( 0 ) ,m_encoding( _encoding ) { - try { - sql::ResultSetMetaData * rs_meta = m_result->getMetaData(); - fieldCount = rs_meta->getColumnCount(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } + fieldCount = mysql_num_fields(pResult); } OResultSet::~OResultSet() @@ -107,7 +132,7 @@ Any SAL_CALL OResultSet::queryInterface(const Type & rType) return aRet; } -Sequence< Type > SAL_CALL OResultSet::getTypes() +uno::Sequence< Type > SAL_CALL OResultSet::getTypes() { OTypeCollection aTypes( cppu::UnoType<XMultiPropertySet>::get(), cppu::UnoType<XFastPropertySet>::get(), @@ -121,18 +146,13 @@ sal_Int32 SAL_CALL OResultSet::findColumn(const rtl::OUString& columnName) MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - // find the first column with the name columnName - sql::ResultSetMetaData * meta = m_result->getMetaData(); - for (sal_uInt32 i = 1; i <= fieldCount; i++) { - if (columnName.equalsIgnoreAsciiCaseAscii(meta->getColumnName(i).c_str())) { - /* SDBC knows them indexed from 1 */ - return i; - } + MYSQL_FIELD* pFields = mysql_fetch_field(m_pResult); + for(unsigned int i = 0; i< fieldCount; ++i) + { + if(columnName.equalsIgnoreAsciiCaseAscii(pFields[i].name)) + return i + 1; // sdbc indexes from 1 } - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } + throw SQLException( "The column name '" + columnName + "' is not valid.", *this, @@ -142,7 +162,7 @@ sal_Int32 SAL_CALL OResultSet::findColumn(const rtl::OUString& columnName) ); } -Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream(sal_Int32 column) +uno::Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -152,7 +172,7 @@ Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream(sal_Int32 column) return nullptr; } -Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream(sal_Int32 column) +uno::Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -166,41 +186,50 @@ sal_Bool SAL_CALL OResultSet::getBoolean(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - checkColumnIndex(column); - try { - return m_result->getBoolean(column); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return false; } - return false; + + m_bWasNull = false; + return static_cast<bool>(std::atoi(pValue)); } sal_Int8 SAL_CALL OResultSet::getByte(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - checkColumnIndex(column); - try { - return m_result->getInt(column); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return 0; } - return 0; // fool compiler + + m_bWasNull = false; + return static_cast<sal_Int8>(std::atoi(pValue)); } -Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes(sal_Int32 column) +uno::Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes(sal_Int32 column) { checkDisposed(OResultSet_BASE::rBHelper.bDisposed); MutexGuard aGuard(m_aMutex); - sql::SQLString val = m_result->getString(column); - if (!val.length()) { - return Sequence< sal_Int8>(); - } else { - return Sequence< sal_Int8 > (reinterpret_cast<sal_Int8 const *>(val.c_str()), val.length()); + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return uno::Sequence< sal_Int8>(); } + m_bWasNull = false; + return uno::Sequence< sal_Int8 > (reinterpret_cast<sal_Int8 const *>( + pValue), m_aLengths[column-1]); } Date SAL_CALL OResultSet::getDate(sal_Int32 column) @@ -209,31 +238,34 @@ Date SAL_CALL OResultSet::getDate(sal_Int32 column) checkDisposed(OResultSet_BASE::rBHelper.bDisposed); checkColumnIndex(column); - Date d; - try { - rtl::OUString dateString = getString(column); - rtl::OUString token; - sal_Int32 nIndex = 0, i=0; - - do { - token = dateString.getToken (0, '-', nIndex); - switch (i) { - case 0: - d.Year = static_cast<sal_uInt16>(token.toUInt32()); - break; - case 1: - d.Month = static_cast<sal_uInt16>(token.toUInt32()); - break; - case 2: - d.Day = static_cast<sal_uInt16>(token.toUInt32()); - break; - default:; - } - i++; - } while (nIndex >= 0); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + Date d; // TODO initialize + char* dateStr = m_aRow[column-1]; + if(!dateStr) + { + m_bWasNull = true; + return d; } + + rtl::OString dateString(dateStr); + rtl::OString token; + sal_Int32 nIndex = 0, i=0; + do { + token = dateString.getToken (0, '-', nIndex); + switch (i) { + case 0: + d.Year = static_cast<sal_uInt16>(token.toUInt32()); + break; + case 1: + d.Month = static_cast<sal_uInt16>(token.toUInt32()); + break; + case 2: + d.Day = static_cast<sal_uInt16>(token.toUInt32()); + break; + default:; + } + i++; + } while (nIndex >= 0); + m_bWasNull = false; return d; } @@ -241,42 +273,49 @@ double SAL_CALL OResultSet::getDouble(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - checkColumnIndex(column); - try { - return m_result->getDouble(column); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return 0.0; } - return 0.0; // fool compiler + + m_bWasNull = false; + return std::strtod(pValue, nullptr); } float SAL_CALL OResultSet::getFloat(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - checkColumnIndex(column); - try { - return m_result->getDouble(column); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return 0.0f; } - return 0.0; // fool compiler + + m_bWasNull = false; + return std::strtod(pValue, nullptr); } sal_Int32 SAL_CALL OResultSet::getInt(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - - checkColumnIndex(column); - try { - return m_result->getInt(column); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return 0; } - return 0; // fool compiler + + m_bWasNull = false; + return std::atoi(pValue); } sal_Int32 SAL_CALL OResultSet::getRow() @@ -284,45 +323,37 @@ sal_Int32 SAL_CALL OResultSet::getRow() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->getRow(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return 0; // fool compiler + return static_cast<sal_Int32>(mysql_field_tell(m_pResult)); } sal_Int64 SAL_CALL OResultSet::getLong(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - checkColumnIndex(column); - try { - return m_result->getInt64(column); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return 0LL; } - return 0; // fool compiler + + m_bWasNull = false; + return std::atol(pValue); } -Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData() +uno::Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData() { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - if (!m_xMetaData.is()) { - m_xMetaData = new OResultSetMetaData(m_result->getMetaData(), m_encoding); - } - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + if (!m_xMetaData.is()) { + m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult, m_encoding); } return m_xMetaData; } -Reference< XArray > SAL_CALL OResultSet::getArray(sal_Int32 column) +uno::Reference< XArray > SAL_CALL OResultSet::getArray(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -332,7 +363,7 @@ Reference< XArray > SAL_CALL OResultSet::getArray(sal_Int32 column) return nullptr; } -Reference< XClob > SAL_CALL OResultSet::getClob(sal_Int32 column) +uno::Reference< XClob > SAL_CALL OResultSet::getClob(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -342,7 +373,7 @@ Reference< XClob > SAL_CALL OResultSet::getClob(sal_Int32 column) return nullptr; } -Reference< XBlob > SAL_CALL OResultSet::getBlob(sal_Int32 column) +uno::Reference< XBlob > SAL_CALL OResultSet::getBlob(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -352,7 +383,7 @@ Reference< XBlob > SAL_CALL OResultSet::getBlob(sal_Int32 column) return nullptr; } -Reference< XRef > SAL_CALL OResultSet::getRef(sal_Int32 column) +uno::Reference< XRef > SAL_CALL OResultSet::getRef(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -362,7 +393,7 @@ Reference< XRef > SAL_CALL OResultSet::getRef(sal_Int32 column) return nullptr; } -Any SAL_CALL OResultSet::getObject(sal_Int32 column, const Reference< XNameAccess >& /* typeMap */) +Any SAL_CALL OResultSet::getObject(sal_Int32 column, const uno::Reference< XNameAccess >& /* typeMap */) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -378,33 +409,32 @@ sal_Int16 SAL_CALL OResultSet::getShort(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + checkColumnIndex(column); - try { - return static_cast<sal_Int16>(m_result->getInt(column)); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return 0; } - return 0; // fool compiler + m_bWasNull = false; + return std::atoi(pValue); } rtl::OUString SAL_CALL OResultSet::getString(sal_Int32 column) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - checkColumnIndex(column); - try { - sql::SQLString val = m_result->getString(column); - if (!m_result->wasNull()) { - return rtl::OUString( val.c_str(), val.length(), m_encoding ); - } else { - return rtl::OUString(); - } - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return rtl::OUString{}; } - return rtl::OUString(); // fool compiler + m_bWasNull = false; + return rtl::OUString(pValue, static_cast<sal_Int32>(m_aLengths[column-1]), m_encoding); } Time SAL_CALL OResultSet::getTime(sal_Int32 column) @@ -413,13 +443,18 @@ Time SAL_CALL OResultSet::getTime(sal_Int32 column) MutexGuard aGuard(m_aMutex); checkColumnIndex(column); - Time t; - rtl::OUString timeString = getString(column); + Time t; // initialize + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return t; + } + rtl::OUString timeString{pValue, static_cast<sal_Int32>(m_aLengths[column-1]), m_encoding}; rtl::OUString token; sal_Int32 nIndex, i=0; nIndex = timeString.indexOf(' ') + 1; - do { token = timeString.getToken (0, ':', nIndex); switch (i) { @@ -436,6 +471,7 @@ Time SAL_CALL OResultSet::getTime(sal_Int32 column) i++; } while (nIndex >= 0); + m_bWasNull = false; return t; } @@ -443,18 +479,32 @@ DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 column) { checkDisposed(OResultSet_BASE::rBHelper.bDisposed); MutexGuard aGuard(m_aMutex); - checkColumnIndex(column); + + char* pValue = m_aRow[column-1]; + if(!pValue) + { + m_bWasNull = true; + return DateTime{}; // init + } + + // YY-MM-DD HH:MM:SS + std::vector<rtl::OUString> dateAndTime = lcl_split(rtl::OUString{pValue, + static_cast<sal_Int32>(m_aLengths[column-1]), m_encoding}, + u' '); + + auto dateParts = lcl_split(dateAndTime.at(0), u'-'); + auto timeParts = lcl_split(dateAndTime.at(1), u':'); + DateTime dt; - Date d = getDate(column); - Time t = getTime(column); - - dt.Year = d.Year; - dt.Month = d.Month; - dt.Day = d.Day; - dt.Hours = t.Hours; - dt.Minutes = t.Minutes; - dt.Seconds = t.Seconds; + + dt.Year = dateParts.at(0).toUInt32(); + dt.Month = dateParts.at(1).toUInt32(); + dt.Day = dateParts.at(2).toUInt32(); + dt.Hours = timeParts.at(0).toUInt32(); + dt.Minutes = timeParts.at(1).toUInt32(); + dt.Seconds = timeParts.at(2).toUInt32(); + m_bWasNull = false; return dt; } @@ -463,12 +513,7 @@ sal_Bool SAL_CALL OResultSet::isBeforeFirst() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->isBeforeFirst(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + return m_nCurrentField == 0; } sal_Bool SAL_CALL OResultSet::isAfterLast() @@ -476,12 +521,7 @@ sal_Bool SAL_CALL OResultSet::isAfterLast() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->isAfterLast(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + return m_nCurrentField >= static_cast<sal_Int32>(fieldCount); } sal_Bool SAL_CALL OResultSet::isFirst() @@ -489,12 +529,7 @@ sal_Bool SAL_CALL OResultSet::isFirst() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->isFirst(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + return m_nCurrentField == 1 && !isAfterLast(); } sal_Bool SAL_CALL OResultSet::isLast() @@ -502,12 +537,7 @@ sal_Bool SAL_CALL OResultSet::isLast() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->isLast(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + return mysql_field_tell(m_pResult) == fieldCount; } void SAL_CALL OResultSet::beforeFirst() @@ -515,11 +545,7 @@ void SAL_CALL OResultSet::beforeFirst() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - m_result->beforeFirst(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::beforeFirst", *this); } void SAL_CALL OResultSet::afterLast() @@ -527,11 +553,7 @@ void SAL_CALL OResultSet::afterLast() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - m_result->afterLast(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } + mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::afterLast", *this); } void SAL_CALL OResultSet::close() @@ -539,12 +561,7 @@ void SAL_CALL OResultSet::close() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - m_result->close(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - + mysql_free_result(m_pResult); dispose(); } @@ -553,12 +570,10 @@ sal_Bool SAL_CALL OResultSet::first() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->first(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + mysql_data_seek(m_pResult, 0); + next(); + + return true; } sal_Bool SAL_CALL OResultSet::last() @@ -566,12 +581,10 @@ sal_Bool SAL_CALL OResultSet::last() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->last(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + mysql_data_seek(m_pResult, fieldCount-1); + next(); + + return true; } sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 row) @@ -579,12 +592,18 @@ sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 row) MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->absolute(row); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + sal_Int32 nFields = static_cast<sal_Int32>(fieldCount); + sal_Int32 nToGo = row < 0 ? nFields - row : row-1; + + if(nToGo >= nFields) + nToGo = nFields - 1; + if(nToGo < 0) + nToGo = 0; + + mysql_data_seek(m_pResult, nToGo); + next(); + + return true; } sal_Bool SAL_CALL OResultSet::relative(sal_Int32 row) @@ -592,12 +611,20 @@ sal_Bool SAL_CALL OResultSet::relative(sal_Int32 row) MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->relative(row); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + sal_Int32 nFields = static_cast<sal_Int32>(fieldCount); + if(row == 0) + return true; + + sal_Int32 nToGo = m_nCurrentField + row; + if(nToGo >= nFields) + nToGo = nFields - 1; + if(nToGo < 0) + nToGo = 0; + + mysql_data_seek(m_pResult, nToGo); + next(); + + return true; } sal_Bool SAL_CALL OResultSet::previous() @@ -605,15 +632,15 @@ sal_Bool SAL_CALL OResultSet::previous() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->previous(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + if(m_nCurrentField <= 1) + return false; + + mysql_data_seek(m_pResult, m_nCurrentField-2); + next(); + return true; } -Reference< XInterface > SAL_CALL OResultSet::getStatement() +uno::Reference< uno::XInterface > SAL_CALL OResultSet::getStatement() { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -650,12 +677,16 @@ sal_Bool SAL_CALL OResultSet::next() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->next(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + m_aRow = mysql_fetch_row(m_pResult); + m_aLengths = mysql_fetch_lengths(m_pResult); + m_nCurrentField = mysql_field_tell(m_pResult); + + unsigned errorNum = mysql_errno(m_pMysql); + if(errorNum) + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(m_pMysql), + errorNum, *this, m_encoding); + + return m_aRow != nullptr; } sal_Bool SAL_CALL OResultSet::wasNull() @@ -663,12 +694,7 @@ sal_Bool SAL_CALL OResultSet::wasNull() MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - try { - return m_result->wasNull(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; //fool + return m_bWasNull; } void SAL_CALL OResultSet::cancel() @@ -805,7 +831,7 @@ void SAL_CALL OResultSet::updateString(sal_Int32 column, const rtl::OUString& /* mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateString", *this); } -void SAL_CALL OResultSet::updateBytes(sal_Int32 column, const Sequence< sal_Int8 >& /* x */) +void SAL_CALL OResultSet::updateBytes(sal_Int32 column, const uno::Sequence< sal_Int8 >& /* x */) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); @@ -837,7 +863,7 @@ void SAL_CALL OResultSet::updateTimestamp(sal_Int32 column, const DateTime& /* x mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateTimestamp", *this); } -void SAL_CALL OResultSet::updateBinaryStream(sal_Int32 column, const Reference< XInputStream >& /* x */, +void SAL_CALL OResultSet::updateBinaryStream(sal_Int32 column, const uno::Reference< XInputStream >& /* x */, sal_Int32 /* length */) { MutexGuard aGuard(m_aMutex); @@ -846,7 +872,7 @@ void SAL_CALL OResultSet::updateBinaryStream(sal_Int32 column, const Reference< mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateBinaryStream", *this); } -void SAL_CALL OResultSet::updateCharacterStream(sal_Int32 column, const Reference< XInputStream >& /* x */, +void SAL_CALL OResultSet::updateCharacterStream(sal_Int32 column, const uno::Reference< XInputStream >& /* x */, sal_Int32 /* length */) { MutexGuard aGuard(m_aMutex); @@ -930,11 +956,11 @@ sal_Int32 SAL_CALL OResultSet::hashBookmark(const Any& /* bookmark */) } // XDeleteRows -Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows(const Sequence< Any >& /* rows */) +uno::Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows(const uno::Sequence< Any >& /* rows */) { MutexGuard aGuard(m_aMutex); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - Sequence< sal_Int32 > aRet = Sequence< sal_Int32 >(); + uno::Sequence< sal_Int32 > aRet = uno::Sequence< sal_Int32 >(); mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::deleteRows", *this); return aRet; @@ -942,7 +968,7 @@ Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows(const Sequence< Any >& /* IPropertyArrayHelper * OResultSet::createArrayHelper() const { - Sequence< Property > aProps(5); + uno::Sequence< Property > aProps(5); Property* pProperties = aProps.getArray(); sal_Int32 nPos = 0; pProperties[nPos++] = Property("FetchDirection", PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0); @@ -988,7 +1014,7 @@ void OResultSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& case PROPERTY_ID_CURSORNAME: case PROPERTY_ID_RESULTSETCONCURRENCY: case PROPERTY_ID_RESULTSETTYPE: - throw Exception("cannot set prop " + rtl::OUString::number(nHandle), nullptr); + throw uno::Exception("cannot set prop " + rtl::OUString::number(nHandle), nullptr); case PROPERTY_ID_FETCHDIRECTION: break; case PROPERTY_ID_FETCHSIZE: @@ -1049,13 +1075,4 @@ void OResultSet::checkColumnIndex(sal_Int32 index) } } -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_resultset.hxx b/mysqlc/source/mysqlc_resultset.hxx index a05cbb88cef6..407798c9cc96 100644 --- a/mysqlc/source/mysqlc_resultset.hxx +++ b/mysqlc/source/mysqlc_resultset.hxx @@ -23,6 +23,7 @@ #include "mysqlc_preparedstatement.hxx" #include "mysqlc_statement.hxx" #include "mysqlc_subcomponent.hxx" +#include "mysqlc_connection.hxx" #include <com/sun/star/sdbc/XCloseable.hpp> #include <com/sun/star/sdbc/XColumnLocate.hpp> @@ -68,11 +69,17 @@ namespace connectivity public ::cppu::OPropertySetHelper, public OPropertyArrayUsageHelper<OResultSet> { + OConnection &m_rConnection; + MYSQL_ROW m_aRow; + unsigned long *m_aLengths = nullptr; + MYSQL *m_pMysql = nullptr; css::uno::WeakReferenceHelper m_aStatement; css::uno::Reference< css::sdbc::XResultSetMetaData> m_xMetaData; - sql::ResultSet *m_result; + MYSQL_RES *m_pResult; unsigned int fieldCount; rtl_TextEncoding m_encoding; + sal_Int32 m_nCurrentField = 0; + bool m_bWasNull = false; // did the last getXXX result null? // OPropertyArrayUsageHelper ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE; // OPropertySetHelper @@ -98,7 +105,7 @@ namespace connectivity getSupportedServiceNames() SAL_OVERRIDE; - OResultSet( OCommonStatement* pStmt, sql::ResultSet *result, rtl_TextEncoding _encoding ); + OResultSet(OConnection& rConn, OCommonStatement* pStmt, MYSQL_RES *pResult, rtl_TextEncoding _encoding ); // ::cppu::OComponentHelper void SAL_CALL disposing() SAL_OVERRIDE; @@ -237,13 +244,4 @@ namespace connectivity } /* connectivity */ #endif // CONNECTIVITY_SRESULTSET_HXX -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_resultsetmetadata.cxx b/mysqlc/source/mysqlc_resultsetmetadata.cxx index d7a7054ea100..0c54ec5021ed 100644 --- a/mysqlc/source/mysqlc_resultsetmetadata.cxx +++ b/mysqlc/source/mysqlc_resultsetmetadata.cxx @@ -18,9 +18,11 @@ */ #include "mysqlc_resultsetmetadata.hxx" +#include "mysqlc_resultset.hxx" #include "mysqlc_general.hxx" #include <cppconn/exception.h> +#include <com/sun/star/sdbc/XRow.hpp> #include <rtl/ustrbuf.hxx> using namespace connectivity::mysqlc; @@ -28,150 +30,92 @@ using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::sdbc; - -OResultSetMetaData::~OResultSetMetaData() +MYSQL_FIELD* OResultSetMetaData::getField(sal_Int32 column) const { + return mysql_fetch_field_direct(m_pRes, column - 1); } sal_Int32 SAL_CALL OResultSetMetaData::getColumnDisplaySize(sal_Int32 column) { - try { - meta->getColumnDisplaySize(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getColumnDisplaySize", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return 0; // fool compiler + MYSQL_FIELD* pField = getField(column); + return pField->length; } sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column) { checkColumnIndex(column); + MYSQL_FIELD* pField = getField(column); - try { - return mysqlc_sdbc_driver::mysqlToOOOType(meta->getColumnType(column)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return 0; // fool compiler + return mysqlc_sdbc_driver::mysqlToOOOType(pField->type, pField->charsetnr); } -/* - XXX: This method doesn't throw exceptions at all. - Should it declare that it throws ?? What if throw() is removed? - Does it change the API, the open-close principle? -*/ sal_Int32 SAL_CALL OResultSetMetaData::getColumnCount() { - try { - return meta->getColumnCount(); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return 0; // fool compiler + return mysql_num_fields(m_pRes); } sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column) { checkColumnIndex(column); + // MYSQL_FIELD::charsetnr is the collation identifier + // _ci postfix means it's insensitive + MYSQL_FIELD* pField = getField(column); + rtl::OUStringBuffer sql{"SHOW COLLATION WHERE Id ="}; + sql.append(rtl::OUString::number(pField->charsetnr)); - try { - return meta->isCaseSensitive(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + Reference< XStatement > stmt = m_rConnection.createStatement(); + Reference< XResultSet > rs = stmt->executeQuery(sql.makeStringAndClear()); + Reference< XRow > xRow( rs, UNO_QUERY_THROW ); + + rs->next(); // fetch first and only row + rtl::OUString sColName = xRow->getString(1); // first column is Collation name + + return !sColName.isEmpty() && !sColName.endsWith("_ci"); } rtl::OUString SAL_CALL OResultSetMetaData::getSchemaName(sal_Int32 column) { checkColumnIndex(column); + MYSQL_FIELD* pField = getField(column); - try { - return convert(meta->getSchemaName(column)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return rtl::OUString(); // fool compiler + return rtl::OStringToOUString(pField->db, m_rConnection.getConnectionEncoding()); } rtl::OUString SAL_CALL OResultSetMetaData::getColumnName(sal_Int32 column) { checkColumnIndex(column); - try { - return convert( meta->getColumnName( column ) ); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return rtl::OUString(); // fool compiler + MYSQL_FIELD* pField = getField(column); + return rtl::OStringToOUString(pField->name, m_rConnection.getConnectionEncoding()); } rtl::OUString SAL_CALL OResultSetMetaData::getTableName(sal_Int32 column) { checkColumnIndex(column); - - try { - return convert(meta->getTableName(column)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return rtl::OUString(); // fool compiler + MYSQL_FIELD* pField = getField(column); + return rtl::OStringToOUString(pField->table, m_rConnection.getConnectionEncoding()); } rtl::OUString SAL_CALL OResultSetMetaData::getCatalogName(sal_Int32 column) { checkColumnIndex(column); - - try { - return convert(meta->getCatalogName(column)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return rtl::OUString(); // fool compiler + MYSQL_FIELD* pField = getField(column); + return rtl::OStringToOUString(pField->catalog, m_rConnection.getConnectionEncoding()); } rtl::OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column) { checkColumnIndex(column); + MYSQL_FIELD* pField = getField(column); - try { - return convert(meta->getColumnTypeName(column)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return rtl::OUString(); // fool compiler + return mysqlc_sdbc_driver::mysqlTypeToStr(pField); } rtl::OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column) { checkColumnIndex(column); - - try { - return convert(meta->getColumnLabel(column)); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return rtl::OUString(); // fool compiler + MYSQL_FIELD* pField = getField(column); + return rtl::OStringToOUString(pField->name, m_rConnection.getConnectionEncoding()); } rtl::OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 column) @@ -182,152 +126,80 @@ rtl::OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 column return aRet; } -sal_Bool SAL_CALL OResultSetMetaData::isCurrency(sal_Int32 column) +sal_Bool SAL_CALL OResultSetMetaData::isCurrency(sal_Int32 /*column*/) { - checkColumnIndex(column); - - try { - return meta->isCurrency(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + return false; // TODO } sal_Bool SAL_CALL OResultSetMetaData::isAutoIncrement(sal_Int32 column) { checkColumnIndex(column); - try { - return meta->isAutoIncrement(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + MYSQL_FIELD* pField = getField(column); + return pField->flags & AUTO_INCREMENT_FLAG; } sal_Bool SAL_CALL OResultSetMetaData::isSigned(sal_Int32 column) { checkColumnIndex(column); - try { - return meta->isSigned(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + MYSQL_FIELD* pField = getField(column); + return !(pField->flags & UNSIGNED_FLAG); } sal_Int32 SAL_CALL OResultSetMetaData::getPrecision(sal_Int32 column) { checkColumnIndex(column); - - try { - return meta->getPrecision(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getPrecision", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return 0; // fool compiler + MYSQL_FIELD* pField = getField(column); + return pField->max_length - pField->decimals; } sal_Int32 SAL_CALL OResultSetMetaData::getScale(sal_Int32 column) { checkColumnIndex(column); - try { - return meta->getScale(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getScale", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return 0; // fool compiler + MYSQL_FIELD* pField = getField(column); + return pField->decimals; } sal_Int32 SAL_CALL OResultSetMetaData::isNullable(sal_Int32 column) { checkColumnIndex(column); - - try { - return sal_Int32(bool(meta->isNullable(column))); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return sal_Int32(false); // fool compiler + MYSQL_FIELD* pField = getField(column); + return !(pField->flags & NOT_NULL_FLAG); } -sal_Bool SAL_CALL OResultSetMetaData::isSearchable(sal_Int32 column) +sal_Bool SAL_CALL OResultSetMetaData::isSearchable(sal_Int32 /*column*/) { - checkColumnIndex(column); - - try { - return meta->isSearchable(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + return true; } sal_Bool SAL_CALL OResultSetMetaData::isReadOnly(sal_Int32 column) { checkColumnIndex(column); - - try { - return meta->isReadOnly(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + MYSQL_FIELD* pField = getField(column); + return !(pField->db && strlen(pField->db)); } sal_Bool SAL_CALL OResultSetMetaData::isDefinitelyWritable(sal_Int32 column) { checkColumnIndex(column); - - try { - return meta->isDefinitelyWritable(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + return !isReadOnly(column); } sal_Bool SAL_CALL OResultSetMetaData::isWritable(sal_Int32 column) { checkColumnIndex(column); - - try { - return meta->isWritable(column); - } catch (const sql::MethodNotImplementedException &) { - mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSetMetaData::getMetaData", *this); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_encoding); - } - return false; // fool compiler + return !isReadOnly(column); } void OResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex) { - if (columnIndex < 1 || columnIndex > static_cast<sal_Int32>(meta->getColumnCount())) { + unsigned nColCount = mysql_num_fields(m_pRes); + if (columnIndex < 1 || columnIndex > static_cast<sal_Int32>(nColCount)) { rtl::OUStringBuffer buf; buf.appendAscii( "Column index out of range (expected 1 to " ); - buf.append( sal_Int32( meta->getColumnCount() ) ); + buf.append( sal_Int32( nColCount ) ); buf.appendAscii( ", got " ); buf.append( columnIndex ); buf.append( '.' ); @@ -335,13 +207,4 @@ void OResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex) } } -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_resultsetmetadata.hxx b/mysqlc/source/mysqlc_resultsetmetadata.hxx index d8ad1217e00b..ff6ed092bfe1 100644 --- a/mysqlc/source/mysqlc_resultsetmetadata.hxx +++ b/mysqlc/source/mysqlc_resultsetmetadata.hxx @@ -23,9 +23,12 @@ #include "mysqlc_connection.hxx" #include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> #include <cppuhelper/implbase1.hxx> #include <cppconn/resultset_metadata.h> +#include <mysql.h> namespace connectivity { @@ -33,6 +36,7 @@ namespace connectivity { using ::com::sun::star::sdbc::SQLException; using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::RuntimeException; //************ Class: ResultSetMetaData @@ -40,13 +44,18 @@ namespace connectivity class OResultSetMetaData final : public OResultSetMetaData_BASE { - sql::ResultSetMetaData * meta; + private: + OConnection& m_rConnection; + MYSQL_RES * m_pRes; rtl_TextEncoding m_encoding; - virtual ~OResultSetMetaData(); + virtual ~OResultSetMetaData() = default; + MYSQL_FIELD* getField(sal_Int32 column) const; public: - OResultSetMetaData( sql::ResultSetMetaData * _meta, rtl_TextEncoding _encoding ) - :meta(_meta) + OResultSetMetaData(OConnection& rConn, + MYSQL_RES * pResult, rtl_TextEncoding _encoding ) + :m_rConnection(rConn) + ,m_pRes(pResult) ,m_encoding( _encoding ) { } diff --git a/mysqlc/source/mysqlc_statement.cxx b/mysqlc/source/mysqlc_statement.cxx index dc032fdc238d..cf13fd0a30af 100644 --- a/mysqlc/source/mysqlc_statement.cxx +++ b/mysqlc/source/mysqlc_statement.cxx @@ -52,11 +52,10 @@ using namespace com::sun::star::io; using namespace com::sun::star::util; using ::osl::MutexGuard; -OCommonStatement::OCommonStatement(OConnection* _pConnection, sql::Statement *_cppStatement) +OCommonStatement::OCommonStatement(OConnection* _pConnection) :OCommonStatement_IBase(m_aMutex) ,OPropertySetHelper(OCommonStatement_IBase::rBHelper) ,m_xConnection(_pConnection) - ,cppStatement(_cppStatement) { } @@ -67,18 +66,18 @@ OCommonStatement::~OCommonStatement() void OCommonStatement::disposeResultSet() { // free the cursor if alive - cppStatement.reset(); + if(m_pMysqlResult != nullptr) + { + mysql_free_result(m_pMysqlResult); + m_pMysqlResult = nullptr; + } } void OCommonStatement::disposing() { MutexGuard aGuard(m_aMutex); - disposeResultSet(); - m_xConnection.clear(); - cppStatement.reset(); - OCommonStatement_IBase::disposing(); } @@ -118,6 +117,7 @@ void SAL_CALL OCommonStatement::close() checkDisposed(rBHelper.bDisposed); } dispose(); + disposeResultSet(); } void SAL_CALL OStatement::clearBatch() @@ -131,30 +131,49 @@ sal_Bool SAL_CALL OCommonStatement::execute(const rtl::OUString& sql) checkDisposed(rBHelper.bDisposed); const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement( sql ); - bool success = false; - try { - success = cppStatement->execute(rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionSettings().encoding).getStr()); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } - return success; + rtl::OString toExec = rtl::OUStringToOString(sSqlStatement, + m_xConnection->getConnectionSettings().encoding); + + MYSQL* pMySql = m_xConnection->getMysqlConnection(); + + // NOTE: differs from mysql c API, wehere mysql_real_escape_string_quote() + // should be used. + // 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_errno(pMySql), *this, m_xConnection->getConnectionEncoding()); + m_nAffectedRows = mysql_affected_rows(pMySql); + + return !failure; } Reference< XResultSet > SAL_CALL OCommonStatement::executeQuery(const rtl::OUString& sql) { MutexGuard aGuard(m_aMutex); checkDisposed(rBHelper.bDisposed); - const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement(sql); - - Reference< XResultSet > xResultSet; - try { - std::unique_ptr< sql::ResultSet > rset(cppStatement->executeQuery(rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionEncoding()).getStr())); - xResultSet = new OResultSet(this, rset.get(), m_xConnection->getConnectionEncoding()); - rset.release(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); + const rtl::OUString sSqlStatement = sql; // TODO m_xConnection->transFormPreparedStatement( sql ); + rtl::OString toExec = rtl::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_errno(pMySql), *this, m_xConnection->getConnectionEncoding()); + + m_pMysqlResult = mysql_store_result(pMySql); + if(m_pMysqlResult == nullptr) + { + mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), + mysql_errno(pMySql), *this, m_xConnection->getConnectionEncoding()); } - return xResultSet; + + m_xResultSet = new OResultSet(*getOwnConnection(),this, m_pMysqlResult, + m_xConnection->getConnectionEncoding()); + return m_xResultSet; } Reference< XConnection > SAL_CALL OCommonStatement::getConnection() @@ -168,7 +187,7 @@ Reference< XConnection > SAL_CALL OCommonStatement::getConnection() sal_Int32 SAL_CALL OCommonStatement::getUpdateCount() { - return cppStatement->getUpdateCount(); + return m_nAffectedRows; } Any SAL_CALL OStatement::queryInterface(const Type & rType) @@ -199,15 +218,9 @@ sal_Int32 SAL_CALL OCommonStatement::executeUpdate(const rtl::OUString& sql) { MutexGuard aGuard(m_aMutex); checkDisposed(rBHelper.bDisposed); - const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement(sql); - sal_Int32 affectedRows = 0; - try { - affectedRows = cppStatement->executeUpdate(rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionEncoding()).getStr()); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } - return affectedRows; + execute(sql); + return m_nAffectedRows; } Reference< XResultSet > SAL_CALL OCommonStatement::getResultSet() @@ -215,23 +228,12 @@ Reference< XResultSet > SAL_CALL OCommonStatement::getResultSet() MutexGuard aGuard(m_aMutex); checkDisposed(rBHelper.bDisposed); - Reference< XResultSet > xResultSet; - try { - std::unique_ptr< sql::ResultSet > rset(cppStatement->getResultSet()); - xResultSet = new OResultSet(this, rset.get(), m_xConnection->getConnectionEncoding()); - rset.release(); - } catch (const sql::SQLException &e) { - mysqlc_sdbc_driver::translateAndThrow(e, *this, m_xConnection->getConnectionEncoding()); - } - return xResultSet; + return m_xResultSet; } sal_Bool SAL_CALL OCommonStatement::getMoreResults() { - MutexGuard aGuard(m_aMutex); - checkDisposed(rBHelper.bDisposed); - - return cppStatement->getMoreResults(); + return false; // TODO IMPL } Any SAL_CALL OCommonStatement::getWarnings() @@ -370,13 +372,4 @@ Reference< css::beans::XPropertySetInfo > SAL_CALL OCommonStatement::getProperty return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); } -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/mysqlc/source/mysqlc_statement.hxx b/mysqlc/source/mysqlc_statement.hxx index 6ac561f1e447..a26988a5a9ac 100644 --- a/mysqlc/source/mysqlc_statement.hxx +++ b/mysqlc/source/mysqlc_statement.hxx @@ -66,7 +66,11 @@ namespace connectivity protected: rtl::Reference<OConnection> m_xConnection; // The owning Connection object - std::unique_ptr<sql::Statement> cppStatement; + css::uno::Reference<css::sdbc::XResultSet> m_xResultSet; + MYSQL_RES* m_pMysqlResult = nullptr; + + // number of rows affected by an UPDATE, DELETE or INSERT statement. + sal_Int32 m_nAffectedRows = 0; protected: void disposeResultSet(); @@ -85,7 +89,7 @@ namespace connectivity virtual ~OCommonStatement(); protected: - OCommonStatement(OConnection* _pConnection, sql::Statement *_cppStatement); + OCommonStatement(OConnection* _pConnection); public: using OCommonStatement_IBase::rBHelper; @@ -152,8 +156,8 @@ namespace connectivity public: // A constructor which is required for the return of the objects - OStatement(OConnection* _pConnection, sql::Statement *_cppStatement) : - OCommonStatement(_pConnection, _cppStatement) {} + OStatement(OConnection* _pConnection) : + OCommonStatement(_pConnection) {} virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE; |