From 92c6a725b8825e4ffe16edbe27c37b940367759f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Dec 2025 23:09:55 -0600 Subject: [PATCH] tdf#139467 correctly handle DatabaseLocation for Calc cell ranges svx::ODataAccessDescriptor contains properties for both a database name and a local file database location. It parses a given name via setDataSource() and puts the value into the correct property depending on whether it starts with "file://" or not. But this means that code which directly checks properties of the ODataAccessDescriptor cannot just look for "DataSource" but must also handle the "DatabaseLocation" property. Net effect was that saving a Calc sheet with a cell range backed by a database query from a local file database that was NOT registered with LibreOffice would not save the database URL to the .ods file, and on reload would lose the reference to the database. This caused failures when trying to refresh the database query. On the UNO side creating import descriptors for a cell range from a file with a database location would also fail to read in the location. Fix that. Change-Id: I7340f2d9f2f0552f436682f2b96249f39413c1fb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195173 Reviewed-by: Michael Weghorn Tested-by: Hossein Tested-by: Jenkins Reviewed-by: Hossein --- sc/CppunitTest_sc_filter_xml.mk | 83 +++++ ...nitTest_sc_importdescriptorcellrangeobj.mk | 14 + sc/Module_sc.mk | 2 + sc/common_unoapi_tests.mk | 2 + .../extras/scimportdescriptorcellrangeobj.cxx | 75 +++++ sc/qa/extras/testdocuments/tdf139467.fods | 306 +++++++++++++++++ sc/qa/filter/xml/data/sheet1.fods | 309 ++++++++++++++++++ sc/qa/filter/xml/xml.cxx | 54 +++ .../filter/xml/XMLExportDatabaseRanges.cxx | 8 +- sc/source/ui/unoobj/datauno.cxx | 5 +- 10 files changed, 851 insertions(+), 7 deletions(-) create mode 100644 sc/CppunitTest_sc_filter_xml.mk create mode 100644 sc/CppunitTest_sc_importdescriptorcellrangeobj.mk create mode 100644 sc/qa/extras/scimportdescriptorcellrangeobj.cxx create mode 100644 sc/qa/extras/testdocuments/tdf139467.fods create mode 100644 sc/qa/filter/xml/data/sheet1.fods create mode 100644 sc/qa/filter/xml/xml.cxx diff --git a/sc/CppunitTest_sc_filter_xml.mk b/sc/CppunitTest_sc_filter_xml.mk new file mode 100644 index 000000000000..c4e85d8bb915 --- /dev/null +++ b/sc/CppunitTest_sc_filter_xml.mk @@ -0,0 +1,83 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,sc_filter_xml)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_filter_xml)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sc_filter_xml, \ + sc/qa/filter/xml/xml \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sc_filter_xml, \ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sc_filter_xml, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + drawinglayercore \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sc \ + scqahelper \ + sfx \ + sot \ + subsequenttest \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tk \ + tl \ + ucbhelper \ + unotest \ + utl \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_set_include,sc_filter_xml,\ + -I$(SRCDIR)/sc/source/ui/inc \ + -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/qa/unit \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_api,sc_filter_xml,\ + udkapi \ + offapi \ + oovbaapi \ +)) + +$(eval $(call gb_CppunitTest_use_packages,sc_filter_xml, \ + filter_xhtml \ + filter_xslt \ +)) + +$(eval $(call gb_CppunitTest_use_ure,sc_filter_xml)) +$(eval $(call gb_CppunitTest_use_vcl,sc_filter_xml)) + +$(eval $(call gb_CppunitTest_use_rdb,sc_filter_xml,services)) + +$(eval $(call gb_CppunitTest_use_configuration,sc_filter_xml)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/CppunitTest_sc_importdescriptorcellrangeobj.mk b/sc/CppunitTest_sc_importdescriptorcellrangeobj.mk new file mode 100644 index 000000000000..0c0a2c0863cd --- /dev/null +++ b/sc/CppunitTest_sc_importdescriptorcellrangeobj.mk @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# 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/. +# +#************************************************************************* + +$(eval $(call sc_unoapi_common,importdescriptorcellrangeobj)) + +# vim: set noet sw=4 ts=4: diff --git a/sc/Module_sc.mk b/sc/Module_sc.mk index f7ff2b0ed80a..9dcdbcb59968 100644 --- a/sc/Module_sc.mk +++ b/sc/Module_sc.mk @@ -106,6 +106,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_vba_macro_test \ CppunitTest_sc_a11y \ CppunitTest_sc_filter_html \ + CppunitTest_sc_filter_xml \ )) ifneq ($(ENABLE_JUMBO_SHEETS),) @@ -202,6 +203,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sc, \ CppunitTest_sc_indexenumeration_tablerowsenumeration \ CppunitTest_sc_indexenumeration_textfieldenumeration \ CppunitTest_sc_importdescriptorbaseobj \ + CppunitTest_sc_importdescriptorcellrangeobj \ CppunitTest_sc_labelrangeobj \ CppunitTest_sc_labelrangesobj \ CppunitTest_sc_modelobj \ diff --git a/sc/common_unoapi_tests.mk b/sc/common_unoapi_tests.mk index 829a478d9b71..34cc34e45a71 100644 --- a/sc/common_unoapi_tests.mk +++ b/sc/common_unoapi_tests.mk @@ -36,6 +36,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_$(1), \ sal \ salhelper \ sc \ + sfx \ subsequenttest \ test \ unotest \ @@ -46,6 +47,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sc_$(1), \ $(eval $(call gb_CppunitTest_set_include,sc_$(1),\ -I$(SRCDIR)/sc/inc \ + -I$(SRCDIR)/sc/source/ui/inc \ $$(INCLUDE) \ )) diff --git a/sc/qa/extras/scimportdescriptorcellrangeobj.cxx b/sc/qa/extras/scimportdescriptorcellrangeobj.cxx new file mode 100644 index 000000000000..2a2f1b9b4961 --- /dev/null +++ b/sc/qa/extras/scimportdescriptorcellrangeobj.cxx @@ -0,0 +1,75 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +#include + +using namespace css; +using namespace css::uno; +using namespace com::sun::star; + +namespace sc_apitest +{ +class ScImportDescriptorCellRangeObj : public UnoApiTest +{ +public: + ScImportDescriptorCellRangeObj() + : UnoApiTest(u"/sc/qa/extras/testdocuments"_ustr) + { + } + + void testDatabaseLocation() + { + loadFromFile(u"tdf139467.fods"); + + SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(mxComponent); + CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell); + ScDocShell* xDocSh = dynamic_cast(pFoundShell); + CPPUNIT_ASSERT(xDocSh); + + // Ensure that a cell range import descriptor for a range with an embedded + // database query that contains a local file URL database-name survives the + // import process + ScRange aRange(0, 0, 0, 2, 6, 0); + rtl::Reference aCellRange = new ScCellRangeObj(xDocSh, aRange); + uno::Sequence aPropValues = aCellRange->createImportDescriptor(false); + + bool found = false; + for (auto& rPropValue : aPropValues) + { + if (rPropValue.Name == "DatabaseName") + { + OUString aValue; + rPropValue.Value >>= aValue; + CPPUNIT_ASSERT_EQUAL(u"file:///path/to/Database.odb"_ustr, aValue); + found = true; + } + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("DatabaseName property not found", true, found); + } + + CPPUNIT_TEST_SUITE(ScImportDescriptorCellRangeObj); + CPPUNIT_TEST(testDatabaseLocation); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ScImportDescriptorCellRangeObj); + +} // end namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/qa/extras/testdocuments/tdf139467.fods b/sc/qa/extras/testdocuments/tdf139467.fods new file mode 100644 index 000000000000..ff58c4a7bc20 --- /dev/null +++ b/sc/qa/extras/testdocuments/tdf139467.fods @@ -0,0 +1,306 @@ + + + + 2025-12-03T11:15:37.6763870002025-12-06T08:52:44.303210000PT44S3LibreOfficeDev/26.2.0.0.alpha1$MacOSX_AARCH64 LibreOffice_project/7bf494112bb05a600fd244f131720abe19fd9d6f + + + 0 + 0 + 4516 + 2709 + + + true + true + true + 0 + true + true + false + true + false + 12632256 + true + true + 0 + false + false + true + true + false + 3 + false + + false + AAA= + false + 1270 + 1270 + 1 + 1 + true + false + false + true + true + true + true + true + 7 + true + + + Sheet1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + ID + + + name + + + + + 1 + + + chair + + + + + 2 + + + table + + + + + 3 + + + lamp + + + + + 4 + + + plate + + + + + 5 + + + cup + + + + + + + + + + + + diff --git a/sc/qa/filter/xml/data/sheet1.fods b/sc/qa/filter/xml/data/sheet1.fods new file mode 100644 index 000000000000..c8264560d6e5 --- /dev/null +++ b/sc/qa/filter/xml/data/sheet1.fods @@ -0,0 +1,309 @@ + + + + 2025-12-03T11:15:37.6763870002025-12-03T11:15:52.846676000PT17S1LibreOfficeDev/26.2.0.0.alpha1$MacOSX_AARCH64 LibreOffice_project/7bf494112bb05a600fd244f131720abe19fd9d6f + + + 2709 + 0 + 4516 + 2710 + + + true + true + true + 0 + true + true + false + true + false + 12632256 + true + true + 0 + false + false + true + true + false + 3 + false + + false + AAA= + false + 1270 + 1270 + 1 + 1 + true + false + false + true + true + true + true + true + 7 + true + + + Sheet1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ??? + + + + + Page 1 + + + + + + + + ???(???) + + + 00/00/0000, 00:00:00 + + + + + + Page 1/ 99 + + + + + + + + + + + + + + + + ID + + + name + + + + + 1 + + + chair + + + + + 2 + + + table + + + + + 3 + + + lamp + + + + + 4 + + + plate + + + + + 5 + + + cup + + + + + + + + + + + + diff --git a/sc/qa/filter/xml/xml.cxx b/sc/qa/filter/xml/xml.cxx new file mode 100644 index 000000000000..4eacc0a5a2d5 --- /dev/null +++ b/sc/qa/filter/xml/xml.cxx @@ -0,0 +1,54 @@ +/* -*- 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 + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +using namespace com::sun::star; + +namespace +{ +/// Covers sc/source/filter/xml/ fixes. +class Test : public ScModelTestBase +{ +public: + Test() + : ScModelTestBase(u"/sc/qa/filter/xml/data/"_ustr) + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testDatabaseLocationRoundTrip) +{ + createScDoc("sheet1.fods"); + + save(TestFilter::ODS); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + assertXPath(pXmlDoc, + "/office:document-content/office:body/office:spreadsheet/" + "table:database-ranges/table:database-range/table:database-source-query", + "database-name", u"file:///path/to/Database.odb"); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx index b93d54be867e..bef2ae3dd5dd 100644 --- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx @@ -292,12 +292,10 @@ private: OUString sConRes; svx::ODataAccessDescriptor aDescriptor; + // Normalize data source to handle both Name and Location formats aDescriptor.setDataSource(aParam.aDBName); - if (aDescriptor.has(svx::DataAccessDescriptorProperty::DataSource)) - { - sDatabaseName = aParam.aDBName; - } - else if (aDescriptor.has(svx::DataAccessDescriptorProperty::ConnectionResource)) + sDatabaseName = aDescriptor.getDataSource(); + if (sDatabaseName.isEmpty() && aDescriptor.has(svx::DataAccessDescriptorProperty::ConnectionResource)) { sConRes = aParam.aDBName; } diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx index c3a67d959b32..a0454f8937bf 100644 --- a/sc/source/ui/unoobj/datauno.cxx +++ b/sc/source/ui/unoobj/datauno.cxx @@ -187,10 +187,11 @@ void ScImportDescriptor::FillProperties( uno::Sequence& rS svx::ODataAccessDescriptor aDescriptor; aDescriptor.setDataSource(rParam.aDBName); - if (aDescriptor.has( svx::DataAccessDescriptorProperty::DataSource )) + if (aDescriptor.has( svx::DataAccessDescriptorProperty::DataSource ) || + aDescriptor.has( svx::DataAccessDescriptorProperty::DatabaseLocation )) { pArray[0].Name = SC_UNONAME_DBNAME; - pArray[0].Value <<= rParam.aDBName; + pArray[0].Value <<= aDescriptor.getDataSource(); } else if (aDescriptor.has( svx::DataAccessDescriptorProperty::ConnectionResource )) {