diff options
Diffstat (limited to 'connectivity/source/drivers/mysqlc')
42 files changed, 1888 insertions, 309 deletions
diff --git a/connectivity/source/drivers/mysqlc/DataAccess.xcu b/connectivity/source/drivers/mysqlc/DataAccess.xcu deleted file mode 100644 index 2b652ec87649..000000000000 --- a/connectivity/source/drivers/mysqlc/DataAccess.xcu +++ /dev/null @@ -1,35 +0,0 @@ -<!-- - * 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 . - --> -<oor:node xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="DataAccess" oor:package="org.openoffice.Office"> - <node oor:name="UserDefinedDriverSettings"> - <node oor:name="org.openoffice.comp.connectivity.mysql_native.Driver" oor:op="replace"> - <prop oor:name="DriverName"> - <value>org.openoffice.comp.connectivity.mysql_native.Driver</value> - </prop> - <prop oor:name="DriverPageDisplayName"> - <value>MySQL native driver</value> - </prop> - <prop oor:name="DriverTypeDisplayName"> - <value>MySQL native driver</value> - </prop> - <prop oor:name="DriverDsnPrefix"> - <value>sdbc:mysqlc:</value> - </prop> - </node> - </node> -</oor:node> diff --git a/connectivity/source/drivers/mysqlc/mysqlc_catalog.cxx b/connectivity/source/drivers/mysqlc/mysqlc_catalog.cxx new file mode 100644 index 000000000000..d72ab1f65d72 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_catalog.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_catalog.hxx" +#include "mysqlc_tables.hxx" +#include "mysqlc_views.hxx" +#include "mysqlc_users.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <comphelper/types.hxx> + +connectivity::mysqlc::Catalog::Catalog( + const css::uno::Reference<css::sdbc::XConnection>& rConnection) + : OCatalog(rConnection) + , m_xConnection(rConnection) +{ +} + +//----- OCatalog ------------------------------------------------------------- +void connectivity::mysqlc::Catalog::refreshTables() +{ + css::uno::Reference<css::sdbc::XResultSet> xTables + = m_xMetaData->getTables(css::uno::Any(), "%", "%", {}); + + if (!xTables.is()) + return; + + ::std::vector<OUString> aTableNames; + + fillNames(xTables, aTableNames); + + if (!m_pTables) + m_pTables.reset(new Tables(m_xConnection->getMetaData(), *this, m_aMutex, aTableNames)); + else + m_pTables->reFill(aTableNames); +} + +void connectivity::mysqlc::Catalog::refreshViews() +{ + css::uno::Reference<css::sdbc::XResultSet> xViews + = m_xMetaData->getTables(css::uno::Any(), "%", "%", { "VIEW" }); + + if (!xViews.is()) + return; + + ::std::vector<OUString> aViewNames; + + fillNames(xViews, aViewNames); + + if (!m_pViews) + m_pViews.reset(new Views(m_xConnection, *this, m_aMutex, aViewNames)); + else + m_pViews->reFill(aViewNames); +} + +//----- IRefreshableGroups --------------------------------------------------- +void connectivity::mysqlc::Catalog::refreshGroups() +{ + // TODO: implement me +} + +//----- IRefreshableUsers ---------------------------------------------------- +void connectivity::mysqlc::Catalog::refreshUsers() +{ + css::uno::Reference<css::sdbc::XStatement> statement = m_xConnection->createStatement(); + css::uno::Reference<css::sdbc::XResultSet> xUsers = statement->executeQuery( + "SELECT grantee FROM information_schema.user_privileges GROUP BY grantee"); + + if (!xUsers.is()) + return; + + ::std::vector<OUString> aUserNames; + + css::uno::Reference<css::sdbc::XRow> xRow(xUsers, css::uno::UNO_QUERY); + while (xUsers->next()) + { + aUserNames.push_back(xRow->getString(1)); + } + xRow.clear(); + ::comphelper::disposeComponent(xUsers); + + if (!m_pUsers) + m_pUsers.reset(new Users(m_xConnection->getMetaData(), *this, m_aMutex, aUserNames)); + else + m_pUsers->reFill(aUserNames); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_catalog.hxx b/connectivity/source/drivers/mysqlc/mysqlc_catalog.hxx new file mode 100644 index 000000000000..1bea18c7667b --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_catalog.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <sdbcx/VCatalog.hxx> + +namespace connectivity::mysqlc +{ +class Catalog : public ::connectivity::sdbcx::OCatalog +{ + css::uno::Reference<css::sdbc::XConnection> m_xConnection; + +public: + explicit Catalog(const css::uno::Reference<css::sdbc::XConnection>& rConnection); + + // OCatalog + virtual void refreshTables() override; + virtual void refreshViews() override; + + // IRefreshableGroups + virtual void refreshGroups() override; + + // IRefreshableUsers + virtual void refreshUsers() override; + + sdbcx::OCollection* getPrivateTables() const { return m_pTables.get(); } +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_column.cxx b/connectivity/source/drivers/mysqlc/mysqlc_column.cxx new file mode 100644 index 000000000000..ceb7437386e6 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_column.cxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_column.hxx" + +#include <TConnection.hxx> + +connectivity::mysqlc::Column::Column() + : OColumn(true) // case sensitive +{ + construct(); +} + +void connectivity::mysqlc::Column::construct() +{ + m_sAutoIncrement = "auto_increment"; + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION), + PROPERTY_ID_AUTOINCREMENTCREATION, 0, &m_sAutoIncrement, + cppu::UnoType<decltype(m_sAutoIncrement)>::get()); +} + +::cppu::IPropertyArrayHelper* + connectivity::mysqlc::Column::createArrayHelper(sal_Int32 /*_nId*/) const +{ + return doCreateArrayHelper(); +} + +::cppu::IPropertyArrayHelper& SAL_CALL connectivity::mysqlc::Column::getInfoHelper() +{ + return *Column_PROP::getArrayHelper(isNew() ? 1 : 0); +} + +css::uno::Sequence<OUString> SAL_CALL connectivity::mysqlc::Column::getSupportedServiceNames() +{ + return { "com.sun.star.sdbcx.Column" }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_column.hxx b/connectivity/source/drivers/mysqlc/mysqlc_column.hxx new file mode 100644 index 000000000000..f69ef1afcea7 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_column.hxx @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ +#pragma once + +#include <connectivity/sdbcx/VColumn.hxx> + +namespace connectivity::mysqlc +{ +class Column; +typedef ::comphelper::OIdPropertyArrayUsageHelper<Column> Column_PROP; +class Column : public sdbcx::OColumn, public Column_PROP +{ + OUString m_sAutoIncrement; + +protected: + virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 _nId) const override; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + +public: + Column(); + virtual void construct() override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_columns.cxx b/connectivity/source/drivers/mysqlc/mysqlc_columns.cxx new file mode 100644 index 000000000000..b34b36b45cbe --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_columns.cxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_columns.hxx" +#include "mysqlc_column.hxx" + +connectivity::mysqlc::Columns::Columns(Table& rTable, osl::Mutex& rMutex, + const ::std::vector<OUString>& rVector) + : OColumnsHelper(rTable, + true, // case sensitivity + rMutex, rVector, + /*bUseHardRef*/ true) +{ + OColumnsHelper::setParent(&rTable); +} + +css::uno::Reference<css::beans::XPropertySet> connectivity::mysqlc::Columns::createDescriptor() +{ + return new Column; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_columns.hxx b/connectivity/source/drivers/mysqlc/mysqlc_columns.hxx new file mode 100644 index 000000000000..34230db37bb5 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_columns.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include "mysqlc_table.hxx" + +#include <connectivity/TColumnsHelper.hxx> + +namespace connectivity::mysqlc +{ +class Columns : public ::connectivity::OColumnsHelper +{ +protected: + virtual css::uno::Reference<css::beans::XPropertySet> createDescriptor() override; + +public: + Columns(Table& rTable, ::osl::Mutex& rMutex, const ::std::vector<OUString>& _rVector); +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx b/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx index 4cf9e916f3df..269113383d8d 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx @@ -17,8 +17,10 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include "mysqlc_catalog.hxx" #include "mysqlc_connection.hxx" #include "mysqlc_databasemetadata.hxx" +#include <com/sun/star/sdbc/SQLException.hpp> #include "mysqlc_driver.hxx" #include "mysqlc_statement.hxx" @@ -27,20 +29,17 @@ #include <com/sun/star/beans/NamedValue.hpp> -#include <osl/diagnose.h> -#include <cppuhelper/supportsservice.hxx> +#include <comphelper/servicehelper.hxx> using namespace connectivity::mysqlc; using namespace com::sun::star::uno; using namespace com::sun::star::container; -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 ::osl::MutexGuard; -#define MYSQLC_URI_PREFIX "sdbc:mysqlc:" - namespace { void lcl_executeUpdate(MYSQL* pMySql, const OString& sql) @@ -53,6 +52,7 @@ void lcl_executeUpdate(MYSQL* pMySql, const OString& sql) OConnection::OConnection(MysqlCDriver& _rDriver) : OMetaConnection_BASE(m_aMutex) , m_mysql() + , m_xCatalog(nullptr) , m_xMetaData(nullptr) , m_xDriver(&_rDriver) { @@ -73,10 +73,7 @@ void OConnection::construct(const OUString& url, const Sequence<PropertyValue>& mysql_library_init(0, nullptr, nullptr); mysql_init(&m_mysql); - // use TCP as connection - mysql_protocol_type protocol = MYSQL_PROTOCOL_TCP; - mysql_options(&m_mysql, MYSQL_OPT_PROTOCOL, &protocol); - OString charset_name{ "utf8mb4" }; + OString charset_name{ "utf8mb4"_ostr }; mysql_options(&m_mysql, MYSQL_SET_CHARSET_NAME, charset_name.getStr()); sal_Int32 nIndex; @@ -90,7 +87,7 @@ void OConnection::construct(const OUString& url, const Sequence<PropertyValue>& // parse url. Url has the following format: // external server: sdbc:mysqlc:[hostname]:[port]/[dbname] - if (url.startsWith(MYSQLC_URI_PREFIX)) + if (url.startsWith("sdbc:mysqlc:")) { nIndex = 12; } @@ -164,15 +161,22 @@ void OConnection::construct(const OUString& url, const Sequence<PropertyValue>& OString pass_str = OUStringToOString(aPass, m_settings.encoding); OString schema_str = OUStringToOString(aDbName, m_settings.encoding); OString socket_str; + + // use TCP as connection by default + mysql_protocol_type protocol = MYSQL_PROTOCOL_TCP; if (unixSocketPassed) { socket_str = OUStringToOString(sUnixSocket, m_settings.encoding); + protocol = MYSQL_PROTOCOL_SOCKET; } else if (namedPipePassed) { socket_str = OUStringToOString(sNamedPipe, m_settings.encoding); + protocol = MYSQL_PROTOCOL_PIPE; } + mysql_options(&m_mysql, MYSQL_OPT_PROTOCOL, &protocol); + // 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(), @@ -188,9 +192,8 @@ void OConnection::construct(const OUString& url, const Sequence<PropertyValue>& *this, OUString(), 0, Any()); } - lcl_executeUpdate(&m_mysql, - OString{ "SET session sql_mode='ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO'" }); - lcl_executeUpdate(&m_mysql, OString{ "SET NAMES utf8mb4" }); + lcl_executeUpdate(&m_mysql, "SET session sql_mode='ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO'"_ostr); + lcl_executeUpdate(&m_mysql, "SET NAMES utf8mb4"_ostr); } OUString OConnection::getImplementationName() @@ -253,8 +256,6 @@ Reference<XPreparedStatement> SAL_CALL OConnection::prepareCall(const OUString& OUString SAL_CALL OConnection::nativeSQL(const OUString& /*_sSql*/) { - MutexGuard aGuard(m_aMutex); - // const OUString sSqlStatement = transFormPreparedStatement( _sSql ); // TODO return OUString(); @@ -461,7 +462,7 @@ OUString OConnection::transFormPreparedStatement(const OUString& _sSQL) try { Reference<XConnection> xCon = this; - Sequence<Any> aArgs{ Any(NamedValue("ActiveConnection", makeAny(xCon))) }; + Sequence<Any> aArgs{ Any(NamedValue("ActiveConnection", Any(xCon))) }; m_xParameterSubstitution.set( m_xDriver->getFactory()->createInstanceWithArguments( @@ -485,4 +486,36 @@ OUString OConnection::transFormPreparedStatement(const OUString& _sSQL) return sSqlStatement; } +//----- XUnoTunnel ---------------------------------------------------------- +// virtual +sal_Int64 SAL_CALL OConnection::getSomething(const css::uno::Sequence<sal_Int8>& rId) +{ + return comphelper::getSomethingImpl(rId, this); +} + +// static +const Sequence<sal_Int8>& OConnection::getUnoTunnelId() +{ + static const comphelper::UnoIdInit implId; + return implId.getSeq(); +} + +Reference<XTablesSupplier> OConnection::createCatalog() +{ + MutexGuard aGuard(m_aMutex); + + // m_xCatalog is a weak reference. Reuse it if it still exists. + Reference<XTablesSupplier> xCatalog = m_xCatalog; + if (xCatalog.is()) + { + return xCatalog; + } + else + { + xCatalog = new Catalog(this); + m_xCatalog = xCatalog; + return m_xCatalog; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx b/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx index c75be4724654..3a0ccf36b4ed 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx @@ -24,20 +24,18 @@ #include "mysqlc_types.hxx" #include <com/sun/star/beans/PropertyValue.hpp> -#include <com/sun/star/lang/DisposedException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/lang/XUnoTunnel.hpp> -#include <com/sun/star/sdbc/ColumnSearch.hpp> #include <com/sun/star/sdbc/ColumnValue.hpp> -#include <com/sun/star/sdbc/DataType.hpp> #include <com/sun/star/sdbc/SQLWarning.hpp> #include <com/sun/star/sdbc/XConnection.hpp> #include <com/sun/star/sdbc/XWarningsSupplier.hpp> #include <com/sun/star/util/XStringSubstitution.hpp> -#include <cppuhelper/compbase3.hxx> -#include <cppuhelper/weakref.hxx> -#include <rtl/string.hxx> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase.hxx> #include <rtl/ref.hxx> #include <mysql.h> @@ -56,12 +54,8 @@ class ODatabaseMetaData; namespace mysqlc { -using ::com::sun::star::sdbc::SQLException; -using ::com::sun::star::sdbc::SQLWarning; -using ::com::sun::star::uno::RuntimeException; - -typedef ::cppu::WeakComponentImplHelper3<css::sdbc::XConnection, css::sdbc::XWarningsSupplier, - css::lang::XServiceInfo> +typedef ::cppu::WeakComponentImplHelper<css::sdbc::XConnection, css::sdbc::XWarningsSupplier, + css::lang::XUnoTunnel, css::lang::XServiceInfo> OMetaConnection_BASE; struct ConnectionSettings @@ -82,7 +76,7 @@ typedef OMetaConnection_BASE OConnection_BASE; typedef std::vector<css::uno::WeakReferenceHelper> OWeakRefArray; -class OConnection final : public OBase_Mutex, public OConnection_BASE +class OConnection final : public cppu::BaseMutex, public OConnection_BASE { private: MYSQL m_mysql; @@ -92,6 +86,7 @@ private: // Data attributes + css::uno::WeakReference<css::sdbcx::XTablesSupplier> m_xCatalog; css::uno::WeakReference<css::sdbc::XDatabaseMetaData> m_xMetaData; OWeakRefArray m_aStatements; // vector containing a list @@ -114,6 +109,12 @@ public: rtl_TextEncoding getConnectionEncoding() const { return m_settings.encoding; } + /** + * Create and/or connect to the sdbcx Catalog. This is completely + * unrelated to the SQL "Catalog". + */ + css::uno::Reference<css::sdbcx::XTablesSupplier> createCatalog(); + // OComponentHelper virtual void SAL_CALL disposing() override; @@ -124,6 +125,10 @@ public: virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence<sal_Int8>& rId) override; + static const css::uno::Sequence<sal_Int8>& getUnoTunnelId(); + // XConnection css::uno::Reference<css::sdbc::XStatement> SAL_CALL createStatement() override; diff --git a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx index a96d70f3461e..6d171b661815 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/sdbc/Deferrability.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <comphelper/sequence.hxx> +#include <o3tl/string_view.hxx> #include <sal/log.hxx> #include <rtl/ustrbuf.hxx> @@ -32,7 +33,6 @@ using namespace connectivity::mysqlc; using namespace com::sun::star::uno; using namespace com::sun::star::lang; -using namespace com::sun::star::beans; using namespace com::sun::star::sdbc; static std::string wild("%"); @@ -160,7 +160,7 @@ sal_Bool SAL_CALL ODatabaseMetaData::supportsNonNullableColumns() { return true; OUString SAL_CALL ODatabaseMetaData::getCatalogTerm() { return "n/a"; } -OUString SAL_CALL ODatabaseMetaData::getIdentifierQuoteString() { return "\""; } +OUString SAL_CALL ODatabaseMetaData::getIdentifierQuoteString() { return "`"; } OUString SAL_CALL ODatabaseMetaData::getExtraNameCharacters() { return "#@"; } @@ -564,7 +564,7 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTableTypes() if (m_rConnection.getMysqlVersion() >= requiredVersion[i]) { rRows.push_back( - { { Any(), makeAny(mysqlc_sdbc_driver::convert(table_types[i], encoding)) } }); + { { Any(), Any(mysqlc_sdbc_driver::convert(table_types[i], encoding)) } }); } } lcl_setRows_throw(xResultSet, 5, rRows); @@ -584,17 +584,17 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTypeInfo() while (mysqlc_types[i].typeName) { rRows.push_back( - { { Any(), makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].typeName, encoding)), - makeAny(mysqlc_types[i].dataType), makeAny(mysqlc_types[i].precision), - makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].literalPrefix, encoding)), - makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].literalSuffix, encoding)), - makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].createParams, encoding)), - makeAny(mysqlc_types[i].nullable), makeAny(mysqlc_types[i].caseSensitive), - makeAny(mysqlc_types[i].searchable), makeAny(mysqlc_types[i].isUnsigned), - makeAny(mysqlc_types[i].fixedPrecScale), makeAny(mysqlc_types[i].autoIncrement), - makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].localTypeName, encoding)), - makeAny(mysqlc_types[i].minScale), makeAny(mysqlc_types[i].maxScale), - makeAny(sal_Int32(0)), makeAny(sal_Int32(0)), makeAny(sal_Int32(10)) } }); + { { Any(), Any(mysqlc_sdbc_driver::convert(mysqlc_types[i].typeName, encoding)), + Any(mysqlc_types[i].dataType), Any(mysqlc_types[i].precision), + Any(mysqlc_sdbc_driver::convert(mysqlc_types[i].literalPrefix, encoding)), + Any(mysqlc_sdbc_driver::convert(mysqlc_types[i].literalSuffix, encoding)), + Any(mysqlc_sdbc_driver::convert(mysqlc_types[i].createParams, encoding)), + Any(mysqlc_types[i].nullable), Any(mysqlc_types[i].caseSensitive), + Any(mysqlc_types[i].searchable), Any(mysqlc_types[i].isUnsigned), + Any(mysqlc_types[i].fixedPrecScale), Any(mysqlc_types[i].autoIncrement), + Any(mysqlc_sdbc_driver::convert(mysqlc_types[i].localTypeName, encoding)), + Any(mysqlc_types[i].minScale), Any(mysqlc_types[i].maxScale), Any(sal_Int32(0)), + Any(sal_Int32(0)), Any(sal_Int32(10)) } }); i++; } @@ -618,14 +618,11 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getSchemas() UNO_QUERY); std::vector<std::vector<Any>> rRows; - OUString sSql - = m_rConnection.getMysqlVersion() > 49999 - ? OUString{ "SELECT SCHEMA_NAME AS TABLE_SCHEM, CATALOG_NAME AS TABLE_CATALOG " - "FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY SCHEMA_NAME" } - : OUString{ "SHOW DATABASES" }; - Reference<XStatement> statement = m_rConnection.createStatement(); - Reference<XInterface> executed = statement->executeQuery(sSql); + Reference<XInterface> executed = statement->executeQuery( + u"SELECT SCHEMA_NAME AS TABLE_SCHEM, CATALOG_NAME AS TABLE_CATALOG FROM INFORMATION_SCHEMA.SCHEMATA \ + WHERE SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema') \ + ORDER BY SCHEMA_NAME"_ustr); Reference<XResultSet> rs(executed, UNO_QUERY_THROW); Reference<XResultSetMetaDataSupplier> supp(executed, UNO_QUERY_THROW); Reference<XResultSetMetaData> rs_meta = supp->getMetaData(); @@ -635,20 +632,12 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getSchemas() while (rs->next()) { std::vector<Any> aRow{ Any() }; - bool informationSchema = false; for (sal_uInt32 i = 1; i <= columns; i++) { OUString columnStringValue = xRow->getString(i); - if (i == 1) - { // TABLE_SCHEM - informationSchema = columnStringValue.equalsIgnoreAsciiCase("information_schema"); - } - aRow.push_back(makeAny(columnStringValue)); - } - if (!informationSchema) - { - rRows.push_back(aRow); + aRow.push_back(Any(columnStringValue)); } + rRows.push_back(aRow); } lcl_setRows_throw(xResultSet, 1, rRows); @@ -743,25 +732,25 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getColumns(const Any& /*catalo std::vector<Any> aRow{ Any() }; // 0. element is unused // catalog name - aRow.push_back(makeAny(xRow->getString(1))); + aRow.emplace_back(xRow->getString(1)); // schema name - aRow.push_back(makeAny(xRow->getString(2))); + aRow.emplace_back(xRow->getString(2)); // table name - aRow.push_back(makeAny(xRow->getString(3))); + aRow.emplace_back(xRow->getString(3)); // column name - aRow.push_back(makeAny(xRow->getString(4))); + aRow.emplace_back(xRow->getString(4)); // data type OUString sDataType = xRow->getString(5); - aRow.push_back(makeAny(mysqlc_sdbc_driver::mysqlStrToOOOType(sDataType))); + aRow.emplace_back(mysqlc_sdbc_driver::mysqlStrToOOOType(sDataType)); // type name - aRow.push_back(makeAny(sDataType)); // TODO + aRow.emplace_back(sDataType); // TODO // column size sal_Int32 nColumnSize = 0; 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 + nColumnSize = o3tl::toInt32(sColumnType.subView(6, 1)); // 'year(' length is 5 else if (sDataType.equalsIgnoreAsciiCase("date")) nColumnSize = 10; else if (sDataType.equalsIgnoreAsciiCase("time")) @@ -773,34 +762,34 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getColumns(const Any& /*catalo nColumnSize = xRow->getShort(7); // numeric precision else nColumnSize = nCharMaxLen; - aRow.push_back(makeAny(nColumnSize)); - aRow.push_back(Any()); // buffer length - unused + aRow.emplace_back(nColumnSize); + aRow.emplace_back(); // buffer length - unused // decimal digits (scale) - aRow.push_back(makeAny(xRow->getShort(8))); + aRow.emplace_back(xRow->getShort(8)); // num_prec_radix - aRow.push_back(makeAny(sal_Int32(10))); + aRow.emplace_back(sal_Int32(10)); // nullable OUString sIsNullable = xRow->getString(13); if (xRow->wasNull()) - aRow.push_back(makeAny(ColumnValue::NULLABLE_UNKNOWN)); + aRow.emplace_back(ColumnValue::NULLABLE_UNKNOWN); else if (sIsNullable.equalsIgnoreAsciiCase("YES")) - aRow.push_back(makeAny(ColumnValue::NULLABLE)); + aRow.emplace_back(ColumnValue::NULLABLE); else - aRow.push_back(makeAny(ColumnValue::NO_NULLS)); + aRow.emplace_back(ColumnValue::NO_NULLS); // remarks - aRow.push_back(makeAny(xRow->getString(9))); + aRow.emplace_back(xRow->getString(9)); // default - aRow.push_back(makeAny(xRow->getString(10))); + aRow.emplace_back(xRow->getString(10)); - aRow.push_back(Any{}); // sql_data_type - unused - aRow.push_back(Any{}); // sql_datetime_sub - unused + aRow.emplace_back(); // sql_data_type - unused + aRow.emplace_back(); // sql_datetime_sub - unused // character octet length - aRow.push_back(makeAny(xRow->getString(11))); + aRow.emplace_back(xRow->getString(11)); // ordinal position - aRow.push_back(makeAny(xRow->getString(12))); + aRow.emplace_back(xRow->getString(12)); // is nullable - aRow.push_back(makeAny(sIsNullable)); + aRow.emplace_back(sIsNullable); aRows.push_back(aRow); } lcl_setRows_throw(xResultSet, 1, aRows); @@ -816,25 +805,20 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTables(const Any& /*catalog "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 '?' " + "FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', " + "'performance_schema') AND TABLE_SCHEMA LIKE '?' AND TABLE_NAME LIKE '?' " }; if (types.getLength() == 1) { - buffer.append("AND TABLE_TYPE LIKE '"); - buffer.append(types[0]); - buffer.append("'"); + buffer.append("AND TABLE_TYPE LIKE '" + types[0] + "'"); } else if (types.getLength() > 1) { - buffer.append("AND (TABLE_TYPE LIKE '"); - buffer.append(types[0]); - buffer.append("'"); + buffer.append("AND (TABLE_TYPE LIKE '" + types[0] + "'"); for (sal_Int32 i = 1; i < types.getLength(); ++i) { - buffer.append(" OR TABLE_TYPE LIKE '"); - buffer.append(types[i]); - buffer.append("'"); + buffer.append(" OR TABLE_TYPE LIKE '" + types[i] + "'"); } buffer.append(")"); } @@ -938,34 +922,34 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getImportedKeys(const Any& /*c std::vector<Any> aRow{ Any() }; // 0. element is unused // primary key catalog - aRow.push_back(makeAny(xRow->getString(3))); + aRow.push_back(Any(xRow->getString(3))); // primary key schema - aRow.push_back(makeAny(xRow->getString(4))); + aRow.push_back(Any(xRow->getString(4))); // primary key table - aRow.push_back(makeAny(xRow->getString(5))); + aRow.push_back(Any(xRow->getString(5))); // primary column name - aRow.push_back(makeAny(xRow->getString(6))); + aRow.push_back(Any(xRow->getString(6))); // fk table catalog - aRow.push_back(makeAny(xRow->getString(1))); + aRow.push_back(Any(xRow->getString(1))); // fk schema - aRow.push_back(makeAny(xRow->getString(11))); + aRow.push_back(Any(xRow->getString(11))); // fk table - aRow.push_back(makeAny(xRow->getString(10))); + aRow.push_back(Any(xRow->getString(10))); // fk column name - aRow.push_back(makeAny(xRow->getString(2))); + aRow.push_back(Any(xRow->getString(2))); // KEY_SEQ - aRow.push_back(makeAny(sal_Int32{ 0 })); // TODO + aRow.push_back(Any(sal_Int32{ 0 })); // TODO // update rule - aRow.push_back(makeAny(xRow->getShort(7))); + aRow.push_back(Any(xRow->getShort(7))); // delete rule - aRow.push_back(makeAny(xRow->getShort(8))); + aRow.push_back(Any(xRow->getShort(8))); // foreign key name - aRow.push_back(makeAny(xRow->getString(9))); + aRow.push_back(Any(xRow->getString(9))); // primary key name - aRow.push_back(makeAny(OUString{})); // TODO + aRow.push_back(Any(OUString{})); // TODO // deferrability - aRow.push_back(makeAny(Deferrability::NONE)); + aRow.push_back(Any(Deferrability::NONE)); aRows.push_back(aRow); } lcl_setRows_throw(xResultSet, 1, aRows); @@ -1026,11 +1010,23 @@ Reference<XResultSet> SAL_CALL ODatabaseMetaData::getBestRowIdentifier(const Any } Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTablePrivileges( - const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& /*tableNamePattern*/) + const Any& /* catalog */, const OUString& schemaPattern, const OUString& tableNamePattern) { - // TODO - SAL_WARN("connectivity.mysqlc", "method not implemented"); - throw SQLException("getTablePrivileges method not implemented", *this, "IM001", 0, Any()); + OUString query("SELECT TABLE_SCHEMA TABLE_CAT, " + "NULL TABLE_SCHEM, " + "TABLE_NAME, " + "NULL GRANTOR," + "GRANTEE, " + "PRIVILEGE_TYPE PRIVILEGE, " + "IS_GRANTABLE " + "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES " + "WHERE TABLE_SCHEMA LIKE '?' " + "AND TABLE_NAME='?'"); + query = query.replaceFirst("?", schemaPattern); + query = query.replaceFirst("?", tableNamePattern); + Reference<XStatement> statement = m_rConnection.createStatement(); + Reference<XResultSet> rs = statement->executeQuery(query); + return rs; } Reference<XResultSet> SAL_CALL ODatabaseMetaData::getCrossReference( diff --git a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx index b56a460e0843..caed92f20e80 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx @@ -177,7 +177,7 @@ public: css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getSchemas() override; css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getCatalogs() override; css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getTableTypes() override; - css::uno::Reference<css::sdbc::XResultSet> + virtual css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getColumns(const Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const OUString& columnNamePattern) override; diff --git a/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx b/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx index 5e5b83625e90..79a514a57898 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx @@ -18,15 +18,16 @@ */ #include "mysqlc_driver.hxx" #include "mysqlc_connection.hxx" +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/servicehelper.hxx> using namespace css::uno; using namespace css::lang; using namespace css::beans; using namespace css::sdbc; +using namespace css::sdbcx; using namespace connectivity::mysqlc; -#include <cppuhelper/supportsservice.hxx> - MysqlCDriver::MysqlCDriver(const Reference<XMultiServiceFactory>& _rxFactory) : ODriver_BASE(m_aMutex) , m_xFactory(_rxFactory) @@ -59,7 +60,7 @@ OUString MysqlCDriver::getImplementationName_Static() Sequence<OUString> MysqlCDriver::getSupportedServiceNames_Static() { - return { "com.sun.star.sdbc.Driver" }; + return { "com.sun.star.sdbc.Driver", "com.sun.star.sdbcx.Driver" }; } OUString SAL_CALL MysqlCDriver::getImplementationName() { return getImplementationName_Static(); } @@ -84,7 +85,6 @@ Reference<XConnection> SAL_CALL MysqlCDriver::connect(const OUString& url, return nullptr; } - Reference<XConnection> xConn; // create a new connection with the given properties and append it to our vector rtl::Reference<OConnection> pCon = new OConnection(*this); @@ -114,6 +114,21 @@ sal_Int32 SAL_CALL MysqlCDriver::getMajorVersion() { return MARIADBC_VERSION_MAJ sal_Int32 SAL_CALL MysqlCDriver::getMinorVersion() { return MARIADBC_VERSION_MINOR; } +Reference<XTablesSupplier> + SAL_CALL MysqlCDriver::getDataDefinitionByConnection(const Reference<XConnection>& rConnection) +{ + if (OConnection* pConnection = comphelper::getFromUnoTunnel<OConnection>(rConnection)) + return pConnection->createCatalog(); + return {}; +} + +Reference<XTablesSupplier> SAL_CALL +MysqlCDriver::getDataDefinitionByURL(const OUString& rURL, const Sequence<PropertyValue>& rInfo) +{ + Reference<XConnection> xConnection = connect(rURL, rInfo); + return getDataDefinitionByConnection(xConnection); +} + namespace connectivity::mysqlc { Reference<XInterface> MysqlCDriver_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) diff --git a/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx b/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx index fec80288b59a..a29040892577 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx @@ -21,24 +21,21 @@ #include "mysqlc_connection.hxx" #include <com/sun/star/sdbc/XDriver.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> - -#include <cppuhelper/compbase2.hxx> -#include <osl/module.h> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <cppuhelper/compbase.hxx> namespace connectivity::mysqlc { -using css::sdbc::SQLException; -using css::uno::Exception; using css::uno::Reference; -using css::uno::RuntimeException; using css::uno::Sequence; Reference<css::uno::XInterface> MysqlCDriver_CreateInstance(const Reference<css::lang::XMultiServiceFactory>& _rxFactory); -typedef ::cppu::WeakComponentImplHelper2<css::sdbc::XDriver, css::lang::XServiceInfo> ODriver_BASE; +typedef ::cppu::WeakComponentImplHelper<css::sdbc::XDriver, css::sdbcx::XDataDefinitionSupplier, + css::lang::XServiceInfo> + ODriver_BASE; typedef void* (*OMysqlCConnection_CreateInstanceFunction)(void* _pDriver); @@ -50,10 +47,6 @@ protected: OWeakRefArray m_xConnections; // vector containing a list // of all the Connection objects // for this Driver -#ifdef BUNDLE_MARIADB - oslModule m_hCConnModule; - bool m_bAttemptedLoadCConn; -#endif public: explicit MysqlCDriver(const Reference<css::lang::XMultiServiceFactory>& _rxFactory); @@ -82,6 +75,12 @@ public: const Reference<css::lang::XMultiServiceFactory>& getFactory() const { return m_xFactory; } static rtl_TextEncoding getDefaultEncoding() { return RTL_TEXTENCODING_UTF8; } + + // XDataDefinitionSupplier + virtual css::uno::Reference<css::sdbcx::XTablesSupplier> SAL_CALL getDataDefinitionByConnection( + const css::uno::Reference<css::sdbc::XConnection>& rxConnection) override; + virtual css::uno::Reference<css::sdbcx::XTablesSupplier> SAL_CALL getDataDefinitionByURL( + const OUString& rsURL, const css::uno::Sequence<css::beans::PropertyValue>& rInfo) override; }; } /* connectivity::mysqlc */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.cxx b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx index 35ecfee84750..bc57770413f5 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_general.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx @@ -20,6 +20,7 @@ #include <sal/log.hxx> #include <rtl/ustring.hxx> +#include <o3tl/string_view.hxx> #include <com/sun/star/sdbc/DataType.hpp> @@ -164,6 +165,9 @@ sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept return css::sdbc::DataType::VARCHAR; case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: if (charsetnr == 63) return css::sdbc::DataType::LONGVARBINARY; return css::sdbc::DataType::LONGVARCHAR; @@ -189,50 +193,58 @@ sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept return css::sdbc::DataType::VARCHAR; } -sal_Int32 mysqlStrToOOOType(const OUString& sType) +sal_Int32 mysqlStrToOOOType(std::u16string_view sType) { // TODO other types. - if (sType.equalsIgnoreAsciiCase("tiny") || sType.equalsIgnoreAsciiCase("tinyint")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"tiny") + || o3tl::equalsIgnoreAsciiCase(sType, u"tinyint")) return css::sdbc::DataType::TINYINT; - if (sType.equalsIgnoreAsciiCase("smallint") || sType.equalsIgnoreAsciiCase("year")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"smallint") + || o3tl::equalsIgnoreAsciiCase(sType, u"year")) return css::sdbc::DataType::SMALLINT; - if (sType.equalsIgnoreAsciiCase("int") || sType.equalsIgnoreAsciiCase("mediumint")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"int") + || o3tl::equalsIgnoreAsciiCase(sType, u"mediumint")) return css::sdbc::DataType::INTEGER; - if (sType.equalsIgnoreAsciiCase("varchar") || sType.equalsIgnoreAsciiCase("set") - || sType.equalsIgnoreAsciiCase("enum")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"varchar") || o3tl::equalsIgnoreAsciiCase(sType, u"set") + || o3tl::equalsIgnoreAsciiCase(sType, u"enum")) return css::sdbc::DataType::VARCHAR; - if (sType.equalsIgnoreAsciiCase("bigint")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"bigint")) return css::sdbc::DataType::BIGINT; - if (sType.equalsIgnoreAsciiCase("blob") || sType.equalsIgnoreAsciiCase("longblob") - || sType.equalsIgnoreAsciiCase("tinyblob") || sType.equalsIgnoreAsciiCase("mediumblob")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"blob") + || o3tl::equalsIgnoreAsciiCase(sType, u"longblob") + || o3tl::equalsIgnoreAsciiCase(sType, u"tinyblob") + || o3tl::equalsIgnoreAsciiCase(sType, u"mediumblob")) return css::sdbc::DataType::BLOB; - if (sType.equalsIgnoreAsciiCase("varbinary")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"varbinary")) return css::sdbc::DataType::VARBINARY; - if (sType.equalsIgnoreAsciiCase("char")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"char")) return css::sdbc::DataType::CHAR; - if (sType.equalsIgnoreAsciiCase("tinytext")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"tinytext")) return css::sdbc::DataType::VARCHAR; - if (sType.equalsIgnoreAsciiCase("text")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"text")) return css::sdbc::DataType::LONGVARCHAR; - if (sType.equalsIgnoreAsciiCase("mediumtext") || sType.equalsIgnoreAsciiCase("longtext")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"mediumtext") + || o3tl::equalsIgnoreAsciiCase(sType, u"longtext")) return css::sdbc::DataType::CLOB; - if (sType.equalsIgnoreAsciiCase("binary")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"binary")) return css::sdbc::DataType::BINARY; - if (sType.equalsIgnoreAsciiCase("time")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"time")) return css::sdbc::DataType::TIME; - if (sType.equalsIgnoreAsciiCase("date")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"date")) return css::sdbc::DataType::DATE; - if (sType.equalsIgnoreAsciiCase("datetime") || sType.equalsIgnoreAsciiCase("timestamp")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"datetime") + || o3tl::equalsIgnoreAsciiCase(sType, u"timestamp")) return css::sdbc::DataType::TIMESTAMP; - if (sType.equalsIgnoreAsciiCase("decimal")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"decimal")) return css::sdbc::DataType::DECIMAL; - if (sType.equalsIgnoreAsciiCase("real") || sType.equalsIgnoreAsciiCase("float")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"real") || o3tl::equalsIgnoreAsciiCase(sType, u"float")) return css::sdbc::DataType::REAL; - if (sType.equalsIgnoreAsciiCase("double")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"double")) return css::sdbc::DataType::DOUBLE; - if (sType.equalsIgnoreAsciiCase("bit")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"bit")) return css::sdbc::DataType::BIT; - if (sType.equalsIgnoreAsciiCase("bool") || sType.equalsIgnoreAsciiCase("boolean")) + if (o3tl::equalsIgnoreAsciiCase(sType, u"bool") + || o3tl::equalsIgnoreAsciiCase(sType, u"boolean")) return css::sdbc::DataType::BOOLEAN; OSL_FAIL("Unknown type name from string, failing back to varchar."); return css::sdbc::DataType::VARCHAR; diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx index 2a78c7628879..16236e1530ed 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx @@ -108,7 +108,7 @@ sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept; OUString mysqlTypeToStr(unsigned mysql_type, unsigned mysql_flags); -sal_Int32 mysqlStrToOOOType(const OUString& sType); +sal_Int32 mysqlStrToOOOType(std::u16string_view sType); OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding); } diff --git a/connectivity/source/drivers/mysqlc/mysqlc_indexes.cxx b/connectivity/source/drivers/mysqlc/mysqlc_indexes.cxx new file mode 100644 index 000000000000..c496f9c21cde --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_indexes.cxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_indexes.hxx" + +connectivity::mysqlc::Indexes::Indexes(Table* pTable, osl::Mutex& rMutex, + const std::vector<OUString>& rVector) + : OIndexesHelper(pTable, rMutex, rVector) +{ +} + +// XDrop +void connectivity::mysqlc::Indexes::dropObject(sal_Int32 /*nPosition*/, + const OUString& /* sIndexName */) +{ + // TODO: implement +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_indexes.hxx b/connectivity/source/drivers/mysqlc/mysqlc_indexes.hxx new file mode 100644 index 000000000000..4c918d1846fd --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_indexes.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include "mysqlc_table.hxx" + +#include <connectivity/TIndexes.hxx> + +namespace connectivity::mysqlc +{ +class Indexes : public ::connectivity::OIndexesHelper +{ +private: + // TODO: useful? + // Table* m_pTable; + +protected: + // XDrop + void dropObject(sal_Int32 nPosition, const OUString& sIndexName); + +public: + Indexes(Table* pTable, ::osl::Mutex& rMutex, const std::vector<OUString>& rVector); +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_keys.cxx b/connectivity/source/drivers/mysqlc/mysqlc_keys.cxx new file mode 100644 index 000000000000..7706844f238c --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_keys.cxx @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_keys.hxx" +#include "mysqlc_table.hxx" + +connectivity::mysqlc::Keys::Keys(Table* pTable, osl::Mutex& rMutex, + const ::std::vector<OUString>& rNames) + : OKeysHelper(pTable, rMutex, rNames) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_keys.hxx b/connectivity/source/drivers/mysqlc/mysqlc_keys.hxx new file mode 100644 index 000000000000..9d0a9ef1cc43 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_keys.hxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <connectivity/TKeys.hxx> + +namespace connectivity::mysqlc +{ +class Table; + +class Keys : public ::connectivity::OKeysHelper +{ +public: + Keys(Table* pTable, ::osl::Mutex& rMutex, const ::std::vector<OUString>& rNames); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx index 8360700434fc..e11476dc9805 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx @@ -31,10 +31,10 @@ #include <cppuhelper/typeprovider.hxx> #include <sal/log.hxx> -using namespace rtl; - #include <cstdlib> +#include <typeindex> +using namespace rtl; using namespace connectivity::mysqlc; using namespace connectivity; using namespace cppu; @@ -46,11 +46,8 @@ 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 <typeindex> - namespace { std::type_index getTypeFromMysqlType(enum_field_types type) @@ -107,12 +104,24 @@ bool OPreparedResultSet::fetchResult() } for (sal_Int32 i = 0; i < m_nColumnCount; ++i) { + bool bIsBlobType = false; + switch (m_aFields[i].type) + { + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + bIsBlobType = true; + break; + default: + bIsBlobType = false; + } m_aMetaData[i].is_null = false; m_aMetaData[i].length = 0l; m_aMetaData[i].error = false; 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].buffer_length = bIsBlobType ? 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; @@ -171,7 +180,7 @@ OPreparedResultSet::OPreparedResultSet(OConnection& rConn, OPreparedStatement* p : OPreparedResultSet_BASE(m_aMutex) , OPropertySetHelper(OPreparedResultSet_BASE::rBHelper) , m_rConnection(rConn) - , m_aStatement(static_cast<OWeakObject*>(pStmt)) + , m_aStatement(css::uno::Reference(cppu::getXWeak(pStmt))) , m_pStmt(pMyStmt) , m_encoding(rConn.getConnectionEncoding()) , m_nColumnCount(mysql_stmt_field_count(pMyStmt)) @@ -189,7 +198,7 @@ void OPreparedResultSet::disposing() MutexGuard aGuard(m_aMutex); - m_aStatement = nullptr; + m_aStatement.clear(); m_xMetaData = nullptr; } @@ -322,8 +331,21 @@ template <> OUString OPreparedResultSet::retrieveValue(sal_Int32 column) { // redirect call to the appropriate method if needed // BLOB can be simply read out as string + bool bIsBlobType = false; + switch (m_aFields[column - 1].type) + { + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + bIsBlobType = true; + break; + default: + bIsBlobType = false; + } + if (getTypeFromMysqlType(m_aFields[column - 1].type) != std::type_index(typeid(OUString)) - && m_aFields[column - 1].type != MYSQL_TYPE_BLOB) + && !bIsBlobType) return getRowSetValue(column).getString(); const char* sStr = static_cast<const char*>(m_aData[column - 1].buffer); @@ -363,6 +385,9 @@ ORowSetValue OPreparedResultSet::getRowSetValue(sal_Int32 nColumnIndex) case MYSQL_TYPE_NEWDECIMAL: return getString(nColumnIndex); case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: throw SQLException("Column with type BLOB cannot be converted", *this, "22000", 1, Any()); default: @@ -1002,21 +1027,16 @@ uno::Sequence<sal_Int32> 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); + return new OPropertyArrayHelper{ + { { "FetchDirection", PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0 }, + { "FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0 }, + { "IsBookmarkable", PROPERTY_ID_ISBOOKMARKABLE, cppu::UnoType<bool>::get(), + PropertyAttribute::READONLY }, + { "ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY, + cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY }, + { "ResultSetType", PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), + PropertyAttribute::READONLY } } + }; } IPropertyArrayHelper& OPreparedResultSet::getInfoHelper() { return *getArrayHelper(); } diff --git a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx index 018595b770ba..40912c5534a7 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx @@ -41,9 +41,7 @@ namespace connectivity::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, @@ -52,7 +50,7 @@ typedef ::cppu::WeakComponentImplHelper12< css::sdbc::XColumnLocate, css::lang::XServiceInfo> OPreparedResultSet_BASE; -class OPreparedResultSet final : public OBase_Mutex, +class OPreparedResultSet final : public cppu::BaseMutex, public OPreparedResultSet_BASE, public ::cppu::OPropertySetHelper, public OPropertyArrayUsageHelper<OPreparedResultSet> diff --git a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx index a50b14bbb3b4..2e7be0894040 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx @@ -23,6 +23,7 @@ #include "mysqlc_propertyids.hxx" #include "mysqlc_resultsetmetadata.hxx" +#include <o3tl/safeint.hxx> #include <sal/log.hxx> #include <com/sun/star/sdbc/DataType.hpp> @@ -31,8 +32,6 @@ using namespace connectivity::mysqlc; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; -using namespace com::sun::star::beans; using namespace com::sun::star::sdbc; using namespace com::sun::star::container; using namespace com::sun::star::io; @@ -432,7 +431,7 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo(sal_Int32 parameterIndex, co { OString sAscii = OUStringToOString(sValue, getOwnConnection()->getConnectionEncoding()); - std::stringstream sStream{ sAscii.getStr() }; + std::stringstream sStream{ std::string(sAscii) }; sStream >> nValue; m_binds[nIndex].buffer_type = MYSQL_TYPE_DOUBLE; mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &nValue, MYSQL_TYPE_DOUBLE, @@ -492,9 +491,10 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 parameter, const Sequence<s checkParameterIndex(parameter); 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_binds[nIndex].buffer_type = MYSQL_TYPE_BLOB; + mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x[0], MYSQL_TYPE_BLOB, x.getLength()); m_bindMetas[nIndex].is_null = false; + m_bindMetas[nIndex].length = x.getLength(); } void SAL_CALL OPreparedStatement::setCharacterStream(sal_Int32 parameter, @@ -569,7 +569,7 @@ void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, con void OPreparedStatement::checkParameterIndex(sal_Int32 column) { - if (column < 1 || column > static_cast<sal_Int32>(m_paramCount)) + if (column < 1 || o3tl::make_unsigned(column) > m_paramCount) { throw SQLException("Parameter index out of range", *this, OUString(), 1, Any()); } diff --git a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx index d280bd935ae3..e1743d91dbc4 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx @@ -30,11 +30,9 @@ namespace connectivity::mysqlc { -using ::com::sun::star::sdbc::SQLException; using ::com::sun::star::sdbc::XResultSetMetaData; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::Type; #if defined MYSQL_VERSION_ID && (MYSQL_VERSION_ID >= 80000) && !defined MARIADB_BASE_VERSION diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx index 7a11020ea8e0..397ea7cbab64 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx @@ -30,6 +30,8 @@ #include <cppuhelper/supportsservice.hxx> #include <cppuhelper/typeprovider.hxx> #include <comphelper/seqstream.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> using namespace rtl; @@ -51,14 +53,13 @@ namespace { // copied from string misc, it should be replaced when library is not an // extension anymore -std::vector<OString> lcl_split(const OString& rStr, char cSeparator) +std::vector<OString> lcl_split(std::string_view rStr, char cSeparator) { std::vector<OString> vec; sal_Int32 idx = 0; do { - OString kw = rStr.getToken(0, cSeparator, idx); - kw = kw.trim(); + OString kw(o3tl::trim(o3tl::getToken(rStr, 0, cSeparator, idx))); if (!kw.isEmpty()) { vec.push_back(kw); @@ -107,7 +108,7 @@ OResultSet::OResultSet(OConnection& rConn, OCommonStatement* pStmt, MYSQL_RES* p : OResultSet_BASE(m_aMutex) , OPropertySetHelper(OResultSet_BASE::rBHelper) , m_pMysql(rConn.getMysqlConnection()) - , m_aStatement(static_cast<OWeakObject*>(pStmt)) + , m_aStatement(css::uno::Reference(cppu::getXWeak(pStmt))) , m_pResult(pResult) , m_encoding(_encoding) { @@ -138,8 +139,8 @@ void OResultSet::ensureFieldInfoFetched() MYSQL_FIELD* pFields = mysql_fetch_fields(m_pResult); m_aFields.reserve(nFieldCount); for (unsigned i = 0; i < nFieldCount; ++i) - m_aFields.push_back(OUString{ - pFields[i].name, static_cast<sal_Int32>(strlen(pFields[i].name)), m_encoding }); + m_aFields.emplace_back(pFields[i].name, static_cast<sal_Int32>(strlen(pFields[i].name)), + m_encoding); } void OResultSet::fetchResult() @@ -155,11 +156,11 @@ void OResultSet::fetchResult() { MYSQL_ROW data = mysql_fetch_row(m_pResult); unsigned long* lengths = mysql_fetch_lengths(m_pResult); - m_aRows.push_back(DataFields{}); + m_aRows.emplace_back(); // MYSQL_ROW is char**, array of strings for (std::size_t col = 0; col < m_aFields.size(); ++col) { - m_aRows.back().push_back(OString{ data[col], static_cast<sal_Int32>(lengths[col]) }); + m_aRows.back().emplace_back(data[col], static_cast<sal_Int32>(lengths[col])); } } unsigned errorNum = mysql_errno(m_pMysql); @@ -181,7 +182,7 @@ void OResultSet::disposing() mysql_free_result(m_pResult); m_pResult = nullptr; } - m_aStatement = nullptr; + m_aStatement.clear(); m_xMetaData = nullptr; } @@ -292,24 +293,23 @@ Date SAL_CALL OResultSet::getDate(sal_Int32 column) if (checkNull(column)) return d; - OString dateStr = m_aRows[m_nRowPosition][column - 1]; + const OString& dateStr = m_aRows[m_nRowPosition][column - 1]; - OString dateString(dateStr); - OString token; + std::string_view dateString(dateStr); sal_Int32 nIndex = 0, i = 0; do { - token = dateString.getToken(0, '-', nIndex); + std::string_view token = o3tl::getToken(dateString, 0, '-', nIndex); switch (i) { case 0: - d.Year = static_cast<sal_uInt16>(token.toUInt32()); + d.Year = static_cast<sal_uInt16>(o3tl::toUInt32(token)); break; case 1: - d.Month = static_cast<sal_uInt16>(token.toUInt32()); + d.Month = static_cast<sal_uInt16>(o3tl::toUInt32(token)); break; case 2: - d.Day = static_cast<sal_uInt16>(token.toUInt32()); + d.Day = static_cast<sal_uInt16>(o3tl::toUInt32(token)); break; default:; } @@ -467,25 +467,28 @@ Time SAL_CALL OResultSet::getTime(sal_Int32 column) if (checkNull(column)) return t; - OString sVal = m_aRows[m_nRowPosition][column - 1]; - OString timeString{ sVal.getStr(), getDataLength(column) }; - OString token; + const OString& sVal = m_aRows[m_nRowPosition][column - 1]; + std::string_view timeString{ sVal.getStr(), o3tl::make_unsigned(getDataLength(column)) }; sal_Int32 nIndex, i = 0; - nIndex = timeString.indexOf(' ') + 1; + size_t idx = timeString.find(' '); + if (idx == std::string_view::npos) + nIndex = 0; + else + nIndex = idx + 1; do { - token = timeString.getToken(0, ':', nIndex); + std::string_view token = o3tl::getToken(timeString, 0, ':', nIndex); switch (i) { case 0: - t.Hours = static_cast<sal_uInt16>(token.toUInt32()); + t.Hours = static_cast<sal_uInt16>(o3tl::toUInt32(token)); break; case 1: - t.Minutes = static_cast<sal_uInt16>(token.toUInt32()); + t.Minutes = static_cast<sal_uInt16>(o3tl::toUInt32(token)); break; case 2: - t.Seconds = static_cast<sal_uInt16>(token.toUInt32()); + t.Seconds = static_cast<sal_uInt16>(o3tl::toUInt32(token)); break; } i++; @@ -506,8 +509,7 @@ DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 column) OString sVal = m_aRows[m_nRowPosition][column - 1]; // YY-MM-DD HH:MM:SS - std::vector<OString> dateAndTime - = lcl_split(OString{ sVal.getStr(), getDataLength(column) }, ' '); + std::vector<OString> dateAndTime = lcl_split(sVal.subView(0, getDataLength(column)), ' '); auto dateParts = lcl_split(dateAndTime.at(0), '-'); auto timeParts = lcl_split(dateAndTime.at(1), ':'); @@ -1007,21 +1009,16 @@ uno::Sequence<sal_Int32> SAL_CALL OResultSet::deleteRows(const uno::Sequence<Any IPropertyArrayHelper* OResultSet::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); + return new OPropertyArrayHelper{ + { { "FetchDirection", PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0 }, + { "FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0 }, + { "IsBookmarkable", PROPERTY_ID_ISBOOKMARKABLE, cppu::UnoType<bool>::get(), + PropertyAttribute::READONLY }, + { "ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY, + cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY }, + { "ResultSetType", PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), + PropertyAttribute::READONLY } } + }; } IPropertyArrayHelper& OResultSet::getInfoHelper() { return *getArrayHelper(); } @@ -1097,7 +1094,7 @@ css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL OResultSet::getProper void OResultSet::checkColumnIndex(sal_Int32 index) { - if (index < 1 || index > static_cast<int>(m_aFields.size())) + if (index < 1 || o3tl::make_unsigned(index) > m_aFields.size()) { /* static object for efficiency or thread safety is a problem ? */ throw SQLException("index out of range", *this, OUString(), 1, Any()); diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx index 461e81286cb6..3e43853d364e 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx @@ -40,9 +40,7 @@ namespace connectivity::mysqlc { -using ::com::sun::star::sdbc::SQLException; using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::RuntimeException; /* ** OResultSet @@ -54,7 +52,7 @@ typedef ::cppu::WeakComponentImplHelper12< css::sdbc::XColumnLocate, css::lang::XServiceInfo> OResultSet_BASE; -class OResultSet final : public OBase_Mutex, +class OResultSet final : public cppu::BaseMutex, public OResultSet_BASE, public ::cppu::OPropertySetHelper, public OPropertyArrayUsageHelper<OResultSet> diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx index 3d0ac9ce8411..21dd0fafc686 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx @@ -21,11 +21,11 @@ #include "mysqlc_general.hxx" #include <com/sun/star/sdbc/XRow.hpp> -#include <rtl/ustrbuf.hxx> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <o3tl/safeint.hxx> using namespace connectivity::mysqlc; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::sdbc; OResultSetMetaData::OResultSetMetaData(OConnection& rConn, MYSQL_RES* pResult) @@ -199,7 +199,7 @@ sal_Bool SAL_CALL OResultSetMetaData::isWritable(sal_Int32 column) void OResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex) { auto nColCount = m_fields.size(); - if (columnIndex < 1 || columnIndex > static_cast<sal_Int32>(nColCount)) + if (columnIndex < 1 || o3tl::make_unsigned(columnIndex) > nColCount) { OUString str = "Column index out of range (expected 1 to " + OUString::number(sal_Int32(nColCount)) + ", got " diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx index c2e5db5f3375..aa84ac05586c 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx @@ -30,10 +30,6 @@ namespace connectivity::mysqlc { -using ::com::sun::star::sdbc::SQLException; -using ::com::sun::star::uno::RuntimeException; -using ::com::sun::star::uno::RuntimeException; - struct MySqlFieldInfo { OUString columnName; diff --git a/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx b/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx index 6e14d9ec60bc..bcb6d3a6cafc 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx @@ -34,9 +34,7 @@ using namespace com::sun::star::uno; 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 ::osl::MutexGuard; @@ -282,7 +280,7 @@ Any SAL_CALL OCommonStatement::getWarnings() MutexGuard aGuard(m_aMutex); checkDisposed(rBHelper.bDisposed); - return makeAny(m_aLastWarning); + return Any(m_aLastWarning); } void SAL_CALL OCommonStatement::clearWarnings() @@ -297,31 +295,19 @@ void SAL_CALL OCommonStatement::clearWarnings() { // this properties are define by the service statement // they must in alphabetic order - Sequence<Property> aProps(10); - Property* pProperties = aProps.getArray(); - sal_Int32 nPos = 0; - pProperties[nPos++] - = Property("CursorName", PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0); - pProperties[nPos++] - = Property("EscapeProcessing", PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 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("MaxFieldSize", PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0); - pProperties[nPos++] - = Property("MaxRows", PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0); - pProperties[nPos++] - = Property("QueryTimeOut", PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0); - pProperties[nPos++] = Property("ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY, - cppu::UnoType<sal_Int32>::get(), 0); - pProperties[nPos++] - = Property("ResultSetType", PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0); - pProperties[nPos++] - = Property("UseBookmarks", PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0); - - return new ::cppu::OPropertyArrayHelper(aProps); + return new ::cppu::OPropertyArrayHelper{ + { { "CursorName", PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0 }, + { "EscapeProcessing", PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0 }, + { "FetchDirection", PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0 }, + { "FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0 }, + { "MaxFieldSize", PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0 }, + { "MaxRows", PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0 }, + { "QueryTimeOut", PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0 }, + { "ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY, + cppu::UnoType<sal_Int32>::get(), 0 }, + { "ResultSetType", PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0 }, + { "UseBookmarks", PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0 } } + }; } ::cppu::IPropertyArrayHelper& OCommonStatement::getInfoHelper() { return *getArrayHelper(); } diff --git a/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx b/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx index 14750309ad87..c710b0b46a6d 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx @@ -36,10 +36,8 @@ namespace connectivity::mysqlc { -using ::com::sun::star::sdbc::SQLException; using ::com::sun::star::sdbc::SQLWarning; using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::Type; typedef ::cppu::WeakComponentImplHelper3<css::sdbc::XWarningsSupplier, css::util::XCancellable, @@ -49,7 +47,7 @@ typedef ::cppu::WeakComponentImplHelper3<css::sdbc::XWarningsSupplier, css::util //************ Class: OCommonStatement // is a base class for the normal statement and for the prepared statement -class OCommonStatement : public OBase_Mutex, +class OCommonStatement : public cppu::BaseMutex, public OCommonStatement_IBase, public ::cppu::OPropertySetHelper, public OPropertyArrayUsageHelper<OCommonStatement> diff --git a/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx b/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx index d0847aedc5d6..edba70a935ab 100644 --- a/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx +++ b/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx @@ -106,12 +106,6 @@ template <class TYPE>::cppu::IPropertyArrayHelper* OPropertyArrayUsageHelper<TYP return s_pProps; } -class OBase_Mutex -{ -public: - ::osl::Mutex m_aMutex; -}; - namespace internal { template <class T> void implCopySequence(const T* _pSource, T*& _pDest, sal_Int32 _nSourceLen) diff --git a/connectivity/source/drivers/mysqlc/mysqlc_table.cxx b/connectivity/source/drivers/mysqlc/mysqlc_table.cxx new file mode 100644 index 000000000000..eedcb35d6164 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_table.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_columns.hxx" +#include "mysqlc_indexes.hxx" +#include "mysqlc_keys.hxx" +#include "mysqlc_table.hxx" + +#include <TConnection.hxx> + +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> + +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +connectivity::mysqlc::Table::Table( + Tables* pTables, osl::Mutex& rMutex, + const css::uno::Reference<OMetaConnection::XConnection>& rConnection) + : OTableHelper(pTables, rConnection, true) + , m_rMutex(rMutex) + , m_nPrivileges(0) +{ + construct(); +} + +connectivity::mysqlc::Table::Table( + Tables* pTables, osl::Mutex& rMutex, + const css::uno::Reference<OMetaConnection::XConnection>& rConnection, const OUString& rCatalog, + const OUString& rSchema, const OUString& rName, const OUString& rType, + const OUString& rDescription) + : OTableHelper(pTables, rConnection, true, rName, rType, rDescription, rSchema, rCatalog) + , m_rMutex(rMutex) + , m_nPrivileges(0) +{ + construct(); +} + +void connectivity::mysqlc::Table::construct() +{ + OTableHelper::construct(); + if (isNew()) + return; + + // TODO: get privileges when in non-embedded mode. + m_nPrivileges = css::sdbcx::Privilege::DROP | css::sdbcx::Privilege::REFERENCE + | css::sdbcx::Privilege::ALTER | css::sdbcx::Privilege::CREATE + | css::sdbcx::Privilege::READ | css::sdbcx::Privilege::DELETE + | css::sdbcx::Privilege::UPDATE | css::sdbcx::Privilege::INSERT + | css::sdbcx::Privilege::SELECT; + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES), + PROPERTY_ID_PRIVILEGES, css::beans::PropertyAttribute::READONLY, + &m_nPrivileges, cppu::UnoType<decltype(m_nPrivileges)>::get()); +} +//----- OTableHelper --------------------------------------------------------- +connectivity::sdbcx::OCollection* +connectivity::mysqlc::Table::createColumns(const ::std::vector<OUString>& rNames) +{ + return new Columns(*this, m_rMutex, rNames); +} + +connectivity::sdbcx::OCollection* +connectivity::mysqlc::Table::createKeys(const ::std::vector<OUString>& rNames) +{ + return new Keys(this, m_rMutex, rNames); +} + +connectivity::sdbcx::OCollection* +connectivity::mysqlc::Table::createIndexes(const ::std::vector<OUString>& rNames) +{ + return new Indexes(this, m_rMutex, rNames); +} + +//----- XAlterTable ----------------------------------------------------------- +void SAL_CALL connectivity::mysqlc::Table::alterColumnByName( + const OUString& rColName, const css::uno::Reference<XPropertySet>& rDescriptor) +{ + osl::MutexGuard aGuard(m_rMutex); + checkDisposed(WeakComponentImplHelperBase::rBHelper.bDisposed); + + css::uno::Reference<XPropertySet> xColumn(m_xColumns->getByName(rColName), css::uno::UNO_QUERY); + + // sdbcx::Descriptor + const bool bNameChanged + = xColumn->getPropertyValue("Name") != rDescriptor->getPropertyValue("Name"); + // sdbcx::ColumnDescriptor + const bool bTypeChanged + = xColumn->getPropertyValue("Type") != rDescriptor->getPropertyValue("Type"); + const bool bTypeNameChanged = !comphelper::getString(xColumn->getPropertyValue("TypeName")) + .equalsIgnoreAsciiCase(comphelper::getString( + rDescriptor->getPropertyValue("TypeName"))); + const bool bPrecisionChanged + = xColumn->getPropertyValue("Precision") != rDescriptor->getPropertyValue("Precision"); + const bool bScaleChanged + = xColumn->getPropertyValue("Scale") != rDescriptor->getPropertyValue("Scale"); + + const bool bIsNullableChanged + = xColumn->getPropertyValue("IsNullable") != rDescriptor->getPropertyValue("IsNullable"); + + const bool bIsAutoIncrementChanged = xColumn->getPropertyValue("IsAutoIncrement") + != rDescriptor->getPropertyValue("IsAutoIncrement"); + + // there's also DefaultValue but not related to database directly, it seems completely internal to LO + // so no need to test it + // TODO: remainder -- these are all "optional" so have to detect presence and change. + if (bTypeChanged || bTypeNameChanged || bPrecisionChanged || bScaleChanged || bIsNullableChanged + || bIsAutoIncrementChanged) + { + // If bPrecisionChanged this will only succeed if we have increased the + // precision, otherwise an exception is thrown -- however the base + // gui then offers to delete and recreate the column. + OUStringBuffer sSql(300); + sSql.append(getAlterTableColumnPart() + " MODIFY COLUMN `" + rColName + "` " + + ::dbtools::createStandardTypePart(rDescriptor, getConnection())); + + if (comphelper::getBOOL(rDescriptor->getPropertyValue("IsAutoIncrement"))) + sSql.append(" auto_increment"); + + // see ColumnValue: NO_NULLS = 0, NULLABLE = 1, NULLABLE_UNKNOWN + // so entry required = yes corresponds to NO_NULLS = 0 and only in this case + // NOT NULL + if (comphelper::getINT32(rDescriptor->getPropertyValue("IsNullable")) == 0) + sSql.append(" NOT NULL"); + + getConnection()->createStatement()->execute(sSql.makeStringAndClear()); + } + + if (bNameChanged) + { + OUString sNewColName; + rDescriptor->getPropertyValue("Name") >>= sNewColName; + OUString sSql(getAlterTableColumnPart() + " RENAME COLUMN `" + rColName + "` TO `" + + sNewColName + "`"); + + getConnection()->createStatement()->execute(sSql); + } + + m_xColumns->refresh(); +} + +void SAL_CALL connectivity::mysqlc::Table::alterColumnByIndex( + sal_Int32 index, const css::uno::Reference<css::beans::XPropertySet>& descriptor) +{ + osl::MutexGuard aGuard(m_rMutex); + css::uno::Reference<XPropertySet> xColumn(m_xColumns->getByIndex(index), + css::uno::UNO_QUERY_THROW); + alterColumnByName(comphelper::getString(xColumn->getPropertyValue( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))), + descriptor); +} + +OUString connectivity::mysqlc::Table::getAlterTableColumnPart() const +{ + return "ALTER TABLE " + + ::dbtools::composeTableName(getMetaData(), m_CatalogName, m_SchemaName, m_Name, true, + ::dbtools::EComposeRule::InTableDefinitions); +} + +OUString connectivity::mysqlc::Table::getRenameStart() const { return "RENAME TABLE "; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_table.hxx b/connectivity/source/drivers/mysqlc/mysqlc_table.hxx new file mode 100644 index 000000000000..7487f1bc7b34 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_table.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include "mysqlc_tables.hxx" + +#include <connectivity/TTableHelper.hxx> + +namespace connectivity::mysqlc +{ +class Table : public OTableHelper +{ +private: + ::osl::Mutex& m_rMutex; + sal_Int32 m_nPrivileges; + +protected: + void construct() override; + +public: + Table(Tables* pTables, ::osl::Mutex& rMutex, + const css::uno::Reference<css::sdbc::XConnection>& _xConnection); + Table(Tables* pTables, ::osl::Mutex& rMutex, + const css::uno::Reference<css::sdbc::XConnection>& _xConnection, const OUString& rCatalog, + const OUString& rSchema, const OUString& rName, const OUString& rType, + const OUString& rDescription); + + // OTableHelper + virtual ::connectivity::sdbcx::OCollection* + createColumns(const ::std::vector<OUString>& rNames) override; + virtual ::connectivity::sdbcx::OCollection* + createKeys(const ::std::vector<OUString>& rNames) override; + virtual ::connectivity::sdbcx::OCollection* + createIndexes(const ::std::vector<OUString>& rNames) override; + + /** Returns always "RENAME TABLE " even for views. + * + * \return The start of the rename statement. + * @see http://dev.mysql.com/doc/refman/5.1/de/rename-table.html + */ + virtual OUString getRenameStart() const override; + + // XAlterTable + /** + * See css::sdbcx::ColumnDescriptor for details of + * rDescriptor. + */ + virtual void SAL_CALL + alterColumnByName(const OUString& rColName, + const css::uno::Reference<css::beans::XPropertySet>& rDescriptor) override; + + virtual void SAL_CALL alterColumnByIndex( + sal_Int32 index, const css::uno::Reference<css::beans::XPropertySet>& descriptor) override; + + /** returns the ALTER TABLE XXX statement + */ + OUString getAlterTableColumnPart() const; +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx b/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx new file mode 100644 index 000000000000..81498978d3a5 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_tables.cxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "mysqlc_table.hxx" +#include "mysqlc_tables.hxx" +#include "mysqlc_catalog.hxx" + +#include <TConnection.hxx> + +#include <connectivity/dbtools.hxx> + +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <comphelper/types.hxx> + +//----- OCollection ----------------------------------------------------------- +void connectivity::mysqlc::Tables::impl_refresh() +{ + static_cast<Catalog&>(m_rParent).refreshTables(); +} + +static void lcl_unescape(OUString& rName) +{ + // Remove ending ` if there's one + sal_Int32 nLastIndexBacktick = rName.lastIndexOf("`"); + if ((nLastIndexBacktick > 0) && (nLastIndexBacktick == (rName.getLength() - 1))) + { + rName = rName.copy(0, nLastIndexBacktick); + } + + // Remove beginning ` + nLastIndexBacktick = rName.indexOf("`"); + if (nLastIndexBacktick == 0) + { + rName = rName.copy(1, rName.getLength() - 1); + } + + // Replace double ` by simple ` + rName = rName.replaceAll("``", "`"); +} + +connectivity::sdbcx::ObjectType connectivity::mysqlc::Tables::createObject(const OUString& rName) +{ + OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents(m_xMetaData, rName, sCatalog, sSchema, sTable, + ::dbtools::EComposeRule::InDataManipulation); + + css::uno::Any aCatalog; + if (!sCatalog.isEmpty()) + { + lcl_unescape(sCatalog); + aCatalog <<= sCatalog; + } + + lcl_unescape(sSchema); + lcl_unescape(sTable); + + // Only retrieving a single table, so table type is irrelevant (param 4) + css::uno::Reference<css::sdbc::XResultSet> xTables + = m_xMetaData->getTables(aCatalog, sSchema, sTable, css::uno::Sequence<OUString>()); + + if (!xTables.is()) + throw css::uno::RuntimeException("Could not acquire table."); + + css::uno::Reference<css::sdbc::XRow> xRow(xTables, css::uno::UNO_QUERY_THROW); + + if (!xTables->next()) + throw css::uno::RuntimeException(); + + connectivity::sdbcx::ObjectType xRet( + new Table(this, m_rMutex, m_xMetaData->getConnection(), + xRow->getString(1), // Catalog + xRow->getString(2), // Schema + xRow->getString(3), // Name + xRow->getString(4), // Type + xRow->getString(5))); // Description / Remarks / Comments + + if (xTables->next()) + throw css::uno::RuntimeException("Found more tables than expected."); + + return xRet; +} + +css::uno::Reference<css::beans::XPropertySet> connectivity::mysqlc::Tables::createDescriptor() +{ + // There is some internal magic so that the same class can be used as either + // a descriptor or as a normal table. See VTable.cxx for the details. In our + // case we just need to ensure we use the correct constructor. + return new Table(this, m_rMutex, m_xMetaData->getConnection()); +} + +//----- XAppend --------------------------------------------------------------- +void connectivity::mysqlc::Tables::createTable( + const css::uno::Reference<css::beans::XPropertySet>& descriptor) +{ + const css::uno::Reference<css::sdbc::XConnection> xConnection = m_xMetaData->getConnection(); + OUString aSql = ::dbtools::createSqlCreateTableStatement(descriptor, xConnection); + + css::uno::Reference<css::sdbc::XStatement> xStmt = xConnection->createStatement(); + if (xStmt.is()) + { + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } +} + +// XAppend +connectivity::sdbcx::ObjectType connectivity::mysqlc::Tables::appendObject( + const OUString& _rForName, const css::uno::Reference<css::beans::XPropertySet>& descriptor) +{ + createTable(descriptor); + return createObject(_rForName); +} + +void connectivity::mysqlc::Tables::appendNew(const OUString& _rsNewTable) +{ + insertElement(_rsNewTable, nullptr); + + // notify our container listeners + css::container::ContainerEvent aEvent(static_cast<XContainer*>(this), + css::uno::Any(_rsNewTable), css::uno::Any(), + css::uno::Any()); + comphelper::OInterfaceIteratorHelper3 aListenerLoop(m_aContainerListeners); + while (aListenerLoop.hasMoreElements()) + aListenerLoop.next()->elementInserted(aEvent); +} + +OUString +connectivity::mysqlc::Tables::getNameForObject(const connectivity::sdbcx::ObjectType& _xObject) +{ + OSL_ENSURE(_xObject.is(), "OTables::getNameForObject: Object is NULL!"); + return ::dbtools::composeTableName(m_xMetaData, _xObject, + ::dbtools::EComposeRule::InDataManipulation, false) + .replaceAll(u"`", u"̀ `"); +} + +//----- XDrop ----------------------------------------------------------------- +void connectivity::mysqlc::Tables::dropObject(sal_Int32 nPosition, const OUString& sName) +{ + css::uno::Reference<css::beans::XPropertySet> xTable(getObject(nPosition)); + + if (connectivity::sdbcx::ODescriptor::isNew(xTable)) + return; + + OUString sType; + xTable->getPropertyValue("Type") >>= sType; + + m_xMetaData->getConnection()->createStatement()->execute("DROP " + sType + " " + sName); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_tables.hxx b/connectivity/source/drivers/mysqlc/mysqlc_tables.hxx new file mode 100644 index 000000000000..8b05c5afaf9f --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_tables.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> + +#include <connectivity/sdbcx/VCollection.hxx> +#include <utility> + +namespace connectivity::mysqlc +{ +/** +* This implements com.sun.star.sdbcx.Container, which seems to be +* also known by the name of Tables and Collection. +*/ +class Tables : public ::connectivity::sdbcx::OCollection +{ +protected: + css::uno::Reference<css::sdbc::XDatabaseMetaData> m_xMetaData; + + // OCollection + virtual void impl_refresh() override; + virtual ::connectivity::sdbcx::ObjectType createObject(const OUString& rName) override; + virtual css::uno::Reference<css::beans::XPropertySet> createDescriptor() override; + virtual ::connectivity::sdbcx::ObjectType + appendObject(const OUString& rName, + const css::uno::Reference<css::beans::XPropertySet>& rDescriptor) override; + + void createTable(const css::uno::Reference<css::beans::XPropertySet>& descriptor); + virtual OUString getNameForObject(const sdbcx::ObjectType& _xObject) override; + // XDrop + virtual void dropObject(sal_Int32 nPosition, const OUString& rName) override; + +public: + Tables(css::uno::Reference<css::sdbc::XDatabaseMetaData> xMetaData, + ::cppu::OWeakObject& rParent, ::osl::Mutex& rMutex, + ::std::vector<OUString> const& rNames) + : sdbcx::OCollection(rParent, true, rMutex, rNames) + , m_xMetaData(std::move(xMetaData)) + { + } + + void appendNew(const OUString& _rsNewTable); + // TODO: should we also implement XDataDescriptorFactory, XRefreshable, + // XAppend, etc. ? +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_user.cxx b/connectivity/source/drivers/mysqlc/mysqlc_user.cxx new file mode 100644 index 000000000000..6e8c3d734a67 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_user.cxx @@ -0,0 +1,211 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <utility> + +#include "mysqlc_user.hxx" +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbcx/PrivilegeObject.hpp> +#include <TConnection.hxx> + +using namespace ::connectivity; +using namespace ::connectivity::mysqlc; +using namespace ::connectivity::sdbcx; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; + +User::User(css::uno::Reference<css::sdbc::XConnection> xConnection) + : OUser(true) // Case Sensitive + , m_xConnection(std::move(xConnection)) +{ +} + +User::User(css::uno::Reference<css::sdbc::XConnection> xConnection, const OUString& rName) + : OUser(rName, + true) // Case Sensitive + , m_xConnection(std::move(xConnection)) +{ +} + +OUserExtend::OUserExtend(const css::uno::Reference<css::sdbc::XConnection>& xConnection, + const OUString& rName) + : User(xConnection, rName) +{ + construct(); +} + +void OUserExtend::construct() +{ + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME), + PROPERTY_ID_NAME, 0, &m_Name, ::cppu::UnoType<OUString>::get()); + + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), + PROPERTY_ID_PASSWORD, 0, &m_Password, ::cppu::UnoType<OUString>::get()); +} + +void User::changePassword(const OUString& /* oldPassword */, const OUString& newPassword) +{ + css::uno::Reference<XStatement> statement = m_xConnection->createStatement(); + statement->execute("SET PASSWORD FOR " + m_Name + " = PASSWORD('" + newPassword + "')"); + ::comphelper::disposeComponent(statement); +} + +cppu::IPropertyArrayHelper* OUserExtend::createArrayHelper() const +{ + css::uno::Sequence<css::beans::Property> aProps; + describeProperties(aProps); + return new cppu::OPropertyArrayHelper(aProps); +} + +cppu::IPropertyArrayHelper& OUserExtend::getInfoHelper() +{ + return *OUserExtend_PROP::getArrayHelper(); +} + +typedef connectivity::sdbcx::OUser_BASE OUser_BASE_RBHELPER; + +sal_Int32 SAL_CALL User::getPrivileges(const OUString& objName, sal_Int32 objType) +{ + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(OUser_BASE_RBHELPER::rBHelper.bDisposed); + + sal_Int32 nRights, nRightsWithGrant; + findPrivilegesAndGrantPrivileges(objName, objType, nRights, nRightsWithGrant); + return nRights; +} + +void User::findPrivilegesAndGrantPrivileges(const OUString& objName, sal_Int32 objType, + sal_Int32& nRights, sal_Int32& nRightsWithGrant) +{ + nRightsWithGrant = nRights = 0; + // first we need to create the sql stmt to select the privs + css::uno::Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents(xMeta, objName, sCatalog, sSchema, sTable, + ::dbtools::EComposeRule::InDataManipulation); + css::uno::Reference<XResultSet> xRes; + switch (objType) + { + case css::sdbcx::PrivilegeObject::TABLE: + case css::sdbcx::PrivilegeObject::VIEW: + { + css::uno::Any aCatalog; + if (!sCatalog.isEmpty()) + aCatalog <<= sCatalog; + xRes = xMeta->getTablePrivileges(aCatalog, sSchema, sTable); + } + break; + + case css::sdbcx::PrivilegeObject::COLUMN: + { + css::uno::Any aCatalog; + if (!sCatalog.isEmpty()) + aCatalog <<= sCatalog; + xRes = xMeta->getColumnPrivileges(aCatalog, sSchema, sTable, "%"); + } + break; + } + + if (!xRes.is()) + return; + + static const char sYes[] = "YES"; + + nRightsWithGrant = nRights = 0; + + css::uno::Reference<XRow> xCurrentRow(xRes, css::uno::UNO_QUERY); + while (xCurrentRow.is() && xRes->next()) + { + OUString sGrantee = xCurrentRow->getString(5); + OUString sPrivilege = xCurrentRow->getString(6); + OUString sGrantable = xCurrentRow->getString(7); + + if (!m_Name.equalsIgnoreAsciiCase(sGrantee)) + continue; + + if (sPrivilege.equalsIgnoreAsciiCase("SELECT")) + { + nRights |= Privilege::SELECT; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::SELECT; + } + else if (sPrivilege.equalsIgnoreAsciiCase("INSERT")) + { + nRights |= Privilege::INSERT; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::INSERT; + } + else if (sPrivilege.equalsIgnoreAsciiCase("UPDATE")) + { + nRights |= Privilege::UPDATE; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::UPDATE; + } + else if (sPrivilege.equalsIgnoreAsciiCase("DELETE")) + { + nRights |= Privilege::DELETE; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::DELETE; + } + else if (sPrivilege.equalsIgnoreAsciiCase("READ")) + { + nRights |= Privilege::READ; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::READ; + } + else if (sPrivilege.equalsIgnoreAsciiCase("CREATE")) + { + nRights |= Privilege::CREATE; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::CREATE; + } + else if (sPrivilege.equalsIgnoreAsciiCase("ALTER")) + { + nRights |= Privilege::ALTER; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::ALTER; + } + else if (sPrivilege.equalsIgnoreAsciiCase("REFERENCES")) + { + nRights |= Privilege::REFERENCE; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::REFERENCE; + } + else if (sPrivilege.equalsIgnoreAsciiCase("DROP")) + { + nRights |= Privilege::DROP; + if (sGrantable.equalsIgnoreAsciiCase(sYes)) + nRightsWithGrant |= Privilege::DROP; + } + } + ::comphelper::disposeComponent(xRes); +} + +sal_Int32 SAL_CALL User::getGrantablePrivileges(const OUString& objName, sal_Int32 objType) +{ + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(OUser_BASE_RBHELPER::rBHelper.bDisposed); + + sal_Int32 nRights, nRightsWithGrant; + findPrivilegesAndGrantPrivileges(objName, objType, nRights, nRightsWithGrant); + return nRightsWithGrant; +} + +//----- IRefreshableGroups ---------------------------------------------------- +void User::refreshGroups() +{ + // TODO: implement. +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_user.hxx b/connectivity/source/drivers/mysqlc/mysqlc_user.hxx new file mode 100644 index 000000000000..6bebbaa64a11 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_user.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <sdbcx/VUser.hxx> +#include <com/sun/star/sdbc/XConnection.hpp> + +namespace connectivity::mysqlc +{ +/** +* This implements com.sun.star.sdbcx.Container. +*/ +class User : public ::connectivity::sdbcx::OUser +{ + css::uno::Reference<css::sdbc::XConnection> m_xConnection; + +public: + /** + * Create a "new" descriptor, which isn't yet in the database. + */ + User(css::uno::Reference<css::sdbc::XConnection> xConnection); + /** + * For a user that already exists in the db. + */ + User(css::uno::Reference<css::sdbc::XConnection> xConnection, const OUString& rName); + + // XAuthorizable + virtual void SAL_CALL changePassword(const OUString&, const OUString& newPassword) override; + virtual sal_Int32 SAL_CALL getPrivileges(const OUString&, sal_Int32) override; + // return the privileges and additional the grant rights + /// @throws css::sdbc::SQLException + /// @throws css::uno::RuntimeException + void findPrivilegesAndGrantPrivileges(const OUString& objName, sal_Int32 objType, + sal_Int32& nRights, sal_Int32& nRightsWithGrant); + + virtual sal_Int32 SAL_CALL getGrantablePrivileges(const OUString&, sal_Int32) override; + + // IRefreshableGroups:: + virtual void refreshGroups() override; +}; + +class OUserExtend; +typedef ::comphelper::OPropertyArrayUsageHelper<OUserExtend> OUserExtend_PROP; + +class OUserExtend : public User, public OUserExtend_PROP +{ + OUString m_Password; + +protected: + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override; + +public: + OUserExtend(const css::uno::Reference<css::sdbc::XConnection>& _xConnection, + const OUString& rName); + + virtual void construct() override; +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_users.cxx b/connectivity/source/drivers/mysqlc/mysqlc_users.cxx new file mode 100644 index 000000000000..296377c1be94 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_users.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <utility> + +#include "mysqlc_user.hxx" +#include "mysqlc_users.hxx" +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <TConnection.hxx> + +using namespace ::connectivity; +using namespace ::connectivity::mysqlc; +using namespace ::connectivity::sdbcx; +using namespace ::cppu; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; + +Users::Users(const uno::Reference<XDatabaseMetaData>& rMetaData, OWeakObject& rParent, + Mutex& rMutex, ::std::vector<OUString> const& rNames) + : OCollection(rParent, true, rMutex, rNames) + , m_xMetaData(rMetaData) +{ +} + +//----- OCollection ----------------------------------------------------------- +void Users::impl_refresh() +{ + // TODO: IMPLEMENT ME +} + +ObjectType Users::createObject(const OUString& rName) +{ + return new OUserExtend(m_xMetaData->getConnection(), rName); +} + +uno::Reference<XPropertySet> Users::createDescriptor() +{ + // There is some internal magic so that the same class can be used as either + // a descriptor or as a normal user. See VUser.cxx for the details. In our + // case we just need to ensure we use the correct constructor. + return new OUserExtend(m_xMetaData->getConnection(), ""); +} + +//----- XAppend --------------------------------------------------------------- +ObjectType Users::appendObject(const OUString& rName, + const uno::Reference<XPropertySet>& descriptor) +{ + OUString aSql("GRANT USAGE ON * TO "); + OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + aSql += ::dbtools::quoteName(aQuote, rName) + " @\"%\" "; + OUString sPassword; + descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) + >>= sPassword; + if (!sPassword.isEmpty()) + { + aSql += " IDENTIFIED BY '" + sPassword + "'"; + } + + Reference<XStatement> statement = m_xMetaData->getConnection()->createStatement(); + if (statement.is()) + statement->execute(aSql); + ::comphelper::disposeComponent(statement); + + return createObject(rName); +} + +//----- XDrop ----------------------------------------------------------------- +void Users::dropObject(sal_Int32 nPosition, const OUString& rName) +{ + uno::Reference<XPropertySet> xUser(getObject(nPosition)); + + if (!ODescriptor::isNew(xUser)) + { + Reference<XStatement> statement = m_xMetaData->getConnection()->createStatement(); + if (statement.is()) + { + statement->execute("DROP USER " + rName); + ::comphelper::disposeComponent(statement); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_users.hxx b/connectivity/source/drivers/mysqlc/mysqlc_users.hxx new file mode 100644 index 000000000000..d4c4d3558e42 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_users.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <connectivity/sdbcx/VCollection.hxx> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> + +namespace connectivity::mysqlc +{ +class Users : public ::connectivity::sdbcx::OCollection +{ + css::uno::Reference<css::sdbc::XDatabaseMetaData> m_xMetaData; + +protected: + // OCollection + virtual void impl_refresh() override; + virtual ::connectivity::sdbcx::ObjectType createObject(const OUString& rName) override; + virtual css::uno::Reference<css::beans::XPropertySet> createDescriptor() override; + virtual ::connectivity::sdbcx::ObjectType + appendObject(const OUString& rName, + const css::uno::Reference<css::beans::XPropertySet>& rDescriptor) override; + +public: + Users(const css::uno::Reference<css::sdbc::XDatabaseMetaData>& rMetaData, + ::cppu::OWeakObject& rParent, ::osl::Mutex& rMutex, + ::std::vector<OUString> const& rNames); + + // TODO: we should also implement XDataDescriptorFactory, XRefreshable, + // XAppend, etc., but all are optional. + + // XDrop + virtual void dropObject(sal_Int32 nPosition, const OUString& rName) override; +}; +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_view.cxx b/connectivity/source/drivers/mysqlc/mysqlc_view.cxx new file mode 100644 index 000000000000..86837381d2bc --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_view.cxx @@ -0,0 +1,98 @@ +/* -*- 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_view.hxx" + +#include <propertyids.hxx> + +#include <com/sun/star/sdbc/XRow.hpp> + +namespace connectivity::mysqlc +{ +View::View(const css::uno::Reference<css::sdbc::XConnection>& _rxConnection, bool _bCaseSensitive, + const OUString& _rSchemaName, const OUString& _rName) + : View_Base(_bCaseSensitive, _rName, _rxConnection->getMetaData(), OUString(), _rSchemaName, + OUString()) + , m_xConnection(_rxConnection) +{ +} + +View::~View() {} + +void SAL_CALL View::acquire() noexcept { View_Base::acquire(); }; +void SAL_CALL View::release() noexcept { View_Base::release(); }; +css::uno::Any SAL_CALL View::queryInterface(const css::uno::Type& _rType) +{ + css::uno::Any aReturn = View_Base::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = View_IBASE::queryInterface(_rType); + return aReturn; +} + +css::uno::Sequence<css::uno::Type> SAL_CALL View::getTypes() +{ + return ::comphelper::concatSequences(View_Base::getTypes(), View_IBASE::getTypes()); +} + +css::uno::Sequence<sal_Int8> SAL_CALL View::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +void SAL_CALL View::alterCommand(const OUString& _rNewCommand) +{ + OUString aCommand = "ALTER VIEW " + m_SchemaName + "." + m_Name + " AS " + _rNewCommand; + m_xMetaData->getConnection()->createStatement()->execute(aCommand); +} + +void SAL_CALL View::getFastPropertyValue(css::uno::Any& _rValue, sal_Int32 _nHandle) const +{ + if (_nHandle == PROPERTY_ID_COMMAND) + { + // retrieve the very current command, don't rely on the base classes cached value + // (which we initialized empty, anyway) + _rValue <<= impl_getCommand(); + return; + } + + View_Base::getFastPropertyValue(_rValue, _nHandle); +} + +OUString View::impl_getCommand() const +{ + OUString aCommand("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '" + + m_SchemaName + "' AND TABLE_NAME = '" + m_Name + "'"); + //::utl::SharedUNOComponent< XStatement > xStatement; xStatement.set( m_xConnection->createStatement(), UNO_QUERY_THROW ); + css::uno::Reference<css::sdbc::XResultSet> xResult( + m_xMetaData->getConnection()->createStatement()->executeQuery(aCommand), + css::uno::UNO_SET_THROW); + if (!xResult->next()) + { + // hmm. There is no view the name as we know it. Can only mean some other instance + // dropped this view meanwhile... + std::abort(); + } + + css::uno::Reference<css::sdbc::XRow> xRow(xResult, css::uno::UNO_QUERY_THROW); + return xRow->getString(1); +} + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_view.hxx b/connectivity/source/drivers/mysqlc/mysqlc_view.hxx new file mode 100644 index 000000000000..8450152499c0 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_view.hxx @@ -0,0 +1,72 @@ +/* -*- 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 . + */ + +#pragma once + +#include <connectivity/sdbcx/VView.hxx> + +#include <com/sun/star/sdbcx/XAlterView.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> + +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase1.hxx> + +namespace connectivity::mysqlc +{ +typedef ::connectivity::sdbcx::OView View_Base; +typedef ::cppu::ImplHelper1<css::sdbcx::XAlterView> View_IBASE; + +class View : public View_Base, public View_IBASE +{ +public: + View(const css::uno::Reference<css::sdbc::XConnection>& _rxConnection, bool _bCaseSensitive, + const OUString& _rSchemaName, const OUString& _rName); + + // UNO + virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& aType) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + virtual css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() override; + virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId() override; + + // XAlterView + virtual void SAL_CALL alterCommand(const OUString& NewCommand) override; + +protected: + virtual ~View() override; + +protected: + // OPropertyContainer + virtual void SAL_CALL getFastPropertyValue(css::uno::Any& _rValue, + sal_Int32 _nHandle) const override; + +private: + /** retrieves the current command of the View */ + OUString impl_getCommand() const; + +private: + css::uno::Reference<css::sdbc::XConnection> m_xConnection; + + using View_Base::getFastPropertyValue; +}; + +} // namespace connectivity::mysqlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_views.cxx b/connectivity/source/drivers/mysqlc/mysqlc_views.cxx new file mode 100644 index 000000000000..1c79c9225d44 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_views.cxx @@ -0,0 +1,113 @@ +/* -*- 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_tables.hxx" +#include "mysqlc_views.hxx" +#include "mysqlc_view.hxx" +#include "mysqlc_catalog.hxx" +#include <connectivity/dbtools.hxx> +#include <comphelper/types.hxx> +#include <TConnection.hxx> + +connectivity::mysqlc::Views::Views(const css::uno::Reference<css::sdbc::XConnection>& _rxConnection, + ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, + const ::std::vector<OUString>& _rVector) + : sdbcx::OCollection(_rParent, true, _rMutex, _rVector) + , m_xConnection(_rxConnection) + , m_xMetaData(_rxConnection->getMetaData()) +{ +} + +connectivity::sdbcx::ObjectType connectivity::mysqlc::Views::createObject(const OUString& _rName) +{ + OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents(m_xMetaData, _rName, sCatalog, sSchema, sTable, + ::dbtools::EComposeRule::InDataManipulation); + return new View(m_xConnection, isCaseSensitive(), sSchema, sTable); +} + +void connectivity::mysqlc::Views::impl_refresh() +{ + static_cast<Catalog&>(m_rParent).refreshViews(); +} + +css::uno::Reference<css::beans::XPropertySet> connectivity::mysqlc::Views::createDescriptor() +{ + return new connectivity::sdbcx::OView(true, m_xMetaData); +} + +// XAppend +connectivity::sdbcx::ObjectType connectivity::mysqlc::Views::appendObject( + const OUString& _rForName, const css::uno::Reference<css::beans::XPropertySet>& descriptor) +{ + createView(descriptor); + return createObject(_rForName); +} + +// XDrop +void connectivity::mysqlc::Views::dropObject(sal_Int32 _nPos, const OUString& /*_sElementName*/) +{ + css::uno::Reference<XInterface> xObject(getObject(_nPos)); + bool bIsNew = connectivity::sdbcx::ODescriptor::isNew(xObject); + if (!bIsNew) + { + OUString aSql("DROP VIEW"); + + css::uno::Reference<css::beans::XPropertySet> xProp(xObject, css::uno::UNO_QUERY); + aSql += ::dbtools::composeTableName(m_xMetaData, xProp, + ::dbtools::EComposeRule::InTableDefinitions, true); + + css::uno::Reference<css::sdbc::XConnection> xConnection = m_xMetaData->getConnection(); + css::uno::Reference<css::sdbc::XStatement> xStmt = xConnection->createStatement(); + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } +} + +void connectivity::mysqlc::Views::createView( + const css::uno::Reference<css::beans::XPropertySet>& descriptor) +{ + css::uno::Reference<css::sdbc::XConnection> xConnection = m_xMetaData->getConnection(); + + OUString sCommand; + descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_COMMAND)) + >>= sCommand; + + OUString aSql = "CREATE VIEW " + + ::dbtools::composeTableName(m_xMetaData, descriptor, + ::dbtools::EComposeRule::InTableDefinitions, true) + + " AS " + sCommand; + + css::uno::Reference<css::sdbc::XStatement> xStmt = xConnection->createStatement(); + if (xStmt.is()) + { + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + connectivity::mysqlc::Tables* pTables = static_cast<connectivity::mysqlc::Tables*>( + static_cast<connectivity::mysqlc::Catalog&>(m_rParent).getPrivateTables()); + if (pTables) + { + OUString sName = ::dbtools::composeTableName( + m_xMetaData, descriptor, ::dbtools::EComposeRule::InDataManipulation, false); + pTables->appendNew(sName); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/mysqlc/mysqlc_views.hxx b/connectivity/source/drivers/mysqlc/mysqlc_views.hxx new file mode 100644 index 000000000000..14570fc8d9a9 --- /dev/null +++ b/connectivity/source/drivers/mysqlc/mysqlc_views.hxx @@ -0,0 +1,50 @@ +/* -*- 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 . + */ +#pragma once + +#include <connectivity/sdbcx/VCollection.hxx> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +namespace connectivity::mysqlc +{ +class Views final : public connectivity::sdbcx::OCollection +{ + css::uno::Reference<css::sdbc::XConnection> m_xConnection; + css::uno::Reference<css::sdbc::XDatabaseMetaData> m_xMetaData; + + // OCollection + virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override; + virtual void impl_refresh() override; + virtual css::uno::Reference<css::beans::XPropertySet> createDescriptor() override; + virtual sdbcx::ObjectType + appendObject(const OUString& _rForName, + const css::uno::Reference<css::beans::XPropertySet>& descriptor) override; + + void createView(const css::uno::Reference<css::beans::XPropertySet>& descriptor); + +public: + Views(const css::uno::Reference<css::sdbc::XConnection>& _rxConnection, + ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, + const ::std::vector<OUString>& _rVector); + + // XDrop + virtual void dropObject(sal_Int32 _nPos, const OUString& _sElementName) override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |