From 0adff3f2476f797843fb62d6810de90bfb333e10 Mon Sep 17 00:00:00 2001 From: Julien Nabet Date: Wed, 26 Jan 2022 23:09:40 +0100 Subject: [PATCH] tdf#126960, tdf#131330: FB make views editable+refresh auto after creation Change-Id: I78783056659a26cc8139d74eefc225de1a11ca7a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129011 Tested-by: Jenkins Reviewed-by: Julien Nabet --- connectivity/Library_firebird_sdbc.mk | 2 + .../source/drivers/firebird/Catalog.cxx | 17 ++- .../source/drivers/firebird/Catalog.hxx | 2 + .../source/drivers/firebird/Tables.cxx | 14 +++ .../source/drivers/firebird/Tables.hxx | 2 + connectivity/source/drivers/firebird/View.cxx | 90 ++++++++++++++ connectivity/source/drivers/firebird/View.hxx | 60 ++++++++++ .../source/drivers/firebird/Views.cxx | 112 ++++++++++++++++++ .../source/drivers/firebird/Views.hxx | 42 +++++++ 9 files changed, 339 insertions(+), 2 deletions(-) create mode 100644 connectivity/source/drivers/firebird/View.cxx create mode 100644 connectivity/source/drivers/firebird/View.hxx create mode 100644 connectivity/source/drivers/firebird/Views.cxx create mode 100644 connectivity/source/drivers/firebird/Views.hxx diff --git a/connectivity/Library_firebird_sdbc.mk b/connectivity/Library_firebird_sdbc.mk index ce0dbe6902ed..720dfeb878f7 100644 --- a/connectivity/Library_firebird_sdbc.mk +++ b/connectivity/Library_firebird_sdbc.mk @@ -61,6 +61,8 @@ $(eval $(call gb_Library_add_exception_objects,firebird_sdbc,\ connectivity/source/drivers/firebird/User \ connectivity/source/drivers/firebird/Users \ connectivity/source/drivers/firebird/Util \ + connectivity/source/drivers/firebird/View \ + connectivity/source/drivers/firebird/Views \ )) # vim: set noet sw=4 ts=4: diff --git a/connectivity/source/drivers/firebird/Catalog.cxx b/connectivity/source/drivers/firebird/Catalog.cxx index c743b42cc75f..2ef4f514b12a 100644 --- a/connectivity/source/drivers/firebird/Catalog.cxx +++ b/connectivity/source/drivers/firebird/Catalog.cxx @@ -10,6 +10,7 @@ #include "Catalog.hxx" #include "Tables.hxx" #include "Users.hxx" +#include "Views.hxx" #include @@ -53,8 +54,20 @@ void Catalog::refreshTables() void Catalog::refreshViews() { - // TODO: implement me. - // Sets m_pViews (OCatalog) + css::uno::Reference xViews + = m_xMetaData->getTables(css::uno::Any(), "%", "%", { "VIEW" }); + + if (!xViews.is()) + return; + + ::std::vector aViewNames; + + fillNames(xViews, aViewNames); + + if (!m_pViews) + m_pViews.reset(new Views(m_xConnection, *this, m_aMutex, aViewNames)); + else + m_pViews->reFill(aViewNames); } //----- IRefreshableGroups --------------------------------------------------- diff --git a/connectivity/source/drivers/firebird/Catalog.hxx b/connectivity/source/drivers/firebird/Catalog.hxx index 4a562e22a26e..b6bf02f6b69d 100644 --- a/connectivity/source/drivers/firebird/Catalog.hxx +++ b/connectivity/source/drivers/firebird/Catalog.hxx @@ -30,6 +30,8 @@ namespace connectivity::firebird // IRefreshableUsers virtual void refreshUsers() override; + + sdbcx::OCollection* getPrivateTables() const { return m_pTables.get(); } }; } // namespace connectivity::firebird diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx index b686f66ecb9c..9c59f65f436c 100644 --- a/connectivity/source/drivers/firebird/Tables.cxx +++ b/connectivity/source/drivers/firebird/Tables.cxx @@ -204,4 +204,18 @@ void Tables::dropObject(sal_Int32 nPosition, const OUString& sName) "DROP " + sType + " " + ::dbtools::quoteName(sQuoteString,sName)); } +void connectivity::firebird::Tables::appendNew(const OUString& _rsNewTable) +{ + insertElement(_rsNewTable, nullptr); + + // notify our container listeners + css::container::ContainerEvent aEvent(static_cast(this), + css::uno::makeAny(_rsNewTable), css::uno::Any(), + css::uno::Any()); + comphelper::OInterfaceIteratorHelper3 aListenerLoop(m_aContainerListeners); + while (aListenerLoop.hasMoreElements()) + aListenerLoop.next()->elementInserted(aEvent); +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/firebird/Tables.hxx b/connectivity/source/drivers/firebird/Tables.hxx index d7fe019ef2a6..7d84edb2084a 100644 --- a/connectivity/source/drivers/firebird/Tables.hxx +++ b/connectivity/source/drivers/firebird/Tables.hxx @@ -51,6 +51,8 @@ namespace connectivity::firebird // XDrop virtual void dropObject(sal_Int32 nPosition, const OUString& rName) override; + void appendNew(const OUString& _rsNewTable); + }; } // namespace connectivity::firebird diff --git a/connectivity/source/drivers/firebird/View.cxx b/connectivity/source/drivers/firebird/View.cxx new file mode 100644 index 000000000000..506cafb40463 --- /dev/null +++ b/connectivity/source/drivers/firebird/View.cxx @@ -0,0 +1,90 @@ +/* -*- 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 "View.hxx" +#include + +#include + +#include + +namespace connectivity::firebird +{ +View::View(const css::uno::Reference& _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 SAL_CALL View::getTypes() +{ + return ::comphelper::concatSequences(View_Base::getTypes(), View_IBASE::getTypes()); +} + +css::uno::Sequence SAL_CALL View::getImplementationId() +{ + return css::uno::Sequence(); +} + +void SAL_CALL View::alterCommand(const OUString& _rNewCommand) +{ + OUString aCommand = "ALTER VIEW \"" + 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 RDB$VIEW_SOURCE FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = '" + + m_Name + "'"); + std::cerr << "TODO aCommand=" << aCommand << "\n"; + // 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 statement = m_xConnection->createStatement(); + css::uno::Reference xResult = statement->executeQuery(aCommand); + + css::uno::Reference xRow(xResult, css::uno::UNO_QUERY_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(); + } + + return xRow->getString(1); +} + +} // namespace connectivity::firebird +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/firebird/View.hxx b/connectivity/source/drivers/firebird/View.hxx new file mode 100644 index 000000000000..2b300a8d06d9 --- /dev/null +++ b/connectivity/source/drivers/firebird/View.hxx @@ -0,0 +1,60 @@ +/* -*- 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 + +#include +#include + +#include +#include + +namespace connectivity::firebird +{ +typedef ::connectivity::sdbcx::OView View_Base; +typedef ::cppu::ImplHelper1 View_IBASE; + +class View : public View_Base, public View_IBASE +{ +public: + View(const css::uno::Reference& _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 SAL_CALL getTypes() override; + virtual css::uno::Sequence 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 m_xConnection; + + using View_Base::getFastPropertyValue; +}; + +} // namespace connectivity::firebird +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/firebird/Views.cxx b/connectivity/source/drivers/firebird/Views.cxx new file mode 100644 index 000000000000..2e5bec42adc3 --- /dev/null +++ b/connectivity/source/drivers/firebird/Views.cxx @@ -0,0 +1,112 @@ +/* -*- 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 "Tables.hxx" +#include "Views.hxx" +#include "View.hxx" +#include "Catalog.hxx" +#include +#include +#include + +connectivity::firebird::Views::Views( + const css::uno::Reference& _rxConnection, ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, const ::std::vector& _rVector) + : sdbcx::OCollection(_rParent, true, _rMutex, _rVector) + , m_xConnection(_rxConnection) + , m_xMetaData(_rxConnection->getMetaData()) + , m_bInDrop(false) +{ +} + +connectivity::sdbcx::ObjectType connectivity::firebird::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::firebird::Views::impl_refresh() +{ + static_cast(m_rParent).refreshViews(); +} + +css::uno::Reference connectivity::firebird::Views::createDescriptor() +{ + return new connectivity::sdbcx::OView(true, m_xMetaData); +} + +// XAppend +connectivity::sdbcx::ObjectType connectivity::firebird::Views::appendObject( + const OUString& _rForName, const css::uno::Reference& descriptor) +{ + createView(descriptor); + return createObject(_rForName); +} + +// XDrop +void connectivity::firebird::Views::dropObject(sal_Int32 _nPos, const OUString& /*_sElementName*/) +{ + if (m_bInDrop) + return; + + css::uno::Reference xObject(getObject(_nPos)); + bool bIsNew = connectivity::sdbcx::ODescriptor::isNew(xObject); + if (!bIsNew) + { + OUString aSql("DROP VIEW"); + + css::uno::Reference xProp(xObject, css::uno::UNO_QUERY); + aSql += ::dbtools::composeTableName(m_xMetaData, xProp, + ::dbtools::EComposeRule::InTableDefinitions, true); + + css::uno::Reference xConnection = m_xMetaData->getConnection(); + css::uno::Reference xStmt = xConnection->createStatement(); + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } +} + +void connectivity::firebird::Views::dropByNameImpl(const OUString& elementName) +{ + m_bInDrop = true; + connectivity::sdbcx::OCollection::dropByName(elementName); + m_bInDrop = false; +} + +void connectivity::firebird::Views::createView( + const css::uno::Reference& descriptor) +{ + css::uno::Reference 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 xStmt = xConnection->createStatement(); + if (xStmt.is()) + { + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + connectivity::firebird::Tables* pTables = static_cast( + static_cast(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 cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/connectivity/source/drivers/firebird/Views.hxx b/connectivity/source/drivers/firebird/Views.hxx new file mode 100644 index 000000000000..6887bdc66ed0 --- /dev/null +++ b/connectivity/source/drivers/firebird/Views.hxx @@ -0,0 +1,42 @@ +/* -*- 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 +#include +namespace connectivity::firebird +{ +class Views final : public connectivity::sdbcx::OCollection +{ + css::uno::Reference m_xConnection; + css::uno::Reference m_xMetaData; + bool m_bInDrop; + + // OCollection + virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override; + virtual void impl_refresh() override; + virtual css::uno::Reference createDescriptor() override; + virtual sdbcx::ObjectType + appendObject(const OUString& _rForName, + const css::uno::Reference& descriptor) override; + + void createView(const css::uno::Reference& descriptor); + +public: + Views(const css::uno::Reference& _rxConnection, + ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, + const ::std::vector& _rVector); + + // XDrop + virtual void dropObject(sal_Int32 _nPos, const OUString& _sElementName) override; + + void dropByNameImpl(const OUString& elementName); +}; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */