From ff9c0cdc28db6e8d04161180773e08272bf48314 Mon Sep 17 00:00:00 2001 From: Andreas Heinisch Date: Sat, 1 Aug 2026 18:58:56 +0200 Subject: [PATCH] tdf#149434 - Use the last separator as table names cannot contain dots Unlike table names schema names may contain dots. Change-Id: I3e918ce8f08e6e013b3872452eb6f966e4367751 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208975 Tested-by: Jenkins Reviewed-by: Andreas Heinisch --- connectivity/qa/connectivity/mysql/mysql.cxx | 59 ++++++++++++++++++++ connectivity/source/commontools/dbtools.cxx | 3 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/connectivity/qa/connectivity/mysql/mysql.cxx b/connectivity/qa/connectivity/mysql/mysql.cxx index 3f1c1805ba51..9fc09cc76dfb 100644 --- a/connectivity/qa/connectivity/mysql/mysql.cxx +++ b/connectivity/qa/connectivity/mysql/mysql.cxx @@ -20,6 +20,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -29,6 +34,8 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; @@ -57,6 +64,7 @@ public: void testNumericConversionPrepared(); void testPreparedStmtIsAfterLast(); void testGetStringFromBlobColumn(); + void testTdf149434DottedDatabaseName(); CPPUNIT_TEST_SUITE(MysqlTestDriver); CPPUNIT_TEST(testDBConnection); @@ -69,6 +77,7 @@ public: CPPUNIT_TEST(testNumericConversionPrepared); CPPUNIT_TEST(testPreparedStmtIsAfterLast); CPPUNIT_TEST(testGetStringFromBlobColumn); + CPPUNIT_TEST(testTdf149434DottedDatabaseName); CPPUNIT_TEST_SUITE_END(); }; @@ -82,6 +91,7 @@ void MysqlTestDriver::tearDown() CPPUNIT_ASSERT(xStatement.is()); xStatement->executeUpdate(u"DROP TABLE IF EXISTS myTestTable"_ustr); xStatement->executeUpdate(u"DROP TABLE IF EXISTS otherTable"_ustr); + xStatement->executeUpdate(u"DROP DATABASE IF EXISTS `tdf149434.test.schema`"_ustr); } test::BootstrapFixture::tearDown(); } @@ -512,6 +522,55 @@ void MysqlTestDriver::testGetStringFromBlobColumn() xStatement->executeUpdate(u"DROP TABLE IF EXISTS myTestTable"_ustr); } +void MysqlTestDriver::testTdf149434DottedDatabaseName() +{ + if (m_sUrl.isEmpty()) + return; + + // Retrieve connection and create sql statement + Reference xConnection = m_xDriver->connect(m_sUrl, m_infos); + CPPUNIT_ASSERT_MESSAGE("cannot connect to data source!", xConnection.is()); + uno::Reference xStatement = xConnection->createStatement(); + CPPUNIT_ASSERT(xStatement.is()); + + // Drop and create database using dots in its name including a test table + static constexpr OUString sDottedSchema = u"tdf149434.test.schema"_ustr; + xStatement->executeUpdate("DROP DATABASE IF EXISTS `" + sDottedSchema + "`"); + xStatement->executeUpdate("CREATE DATABASE `" + sDottedSchema + "`"); + xStatement->executeUpdate("CREATE TABLE `" + sDottedSchema + + "`.tdf149434TestTable (id INTEGER PRIMARY KEY)"); + + // Retrieve table definition using the composed name + Reference xDDSupplier(m_xDriver, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("driver does not support XDataDefinitionSupplier", xDDSupplier.is()); + Reference xTablesSupplier + = xDDSupplier->getDataDefinitionByConnection(xConnection); + CPPUNIT_ASSERT_MESSAGE("cannot get tables supplier", xTablesSupplier.is()); + Reference xTables = xTablesSupplier->getTables(); + CPPUNIT_ASSERT_MESSAGE("cannot get tables container", xTables.is()); + OUString sComposedName = sDottedSchema + ".tdf149434TestTable"; + CPPUNIT_ASSERT_MESSAGE("dotted-schema table not found in tables container", + xTables->hasByName(sComposedName)); + + // Without the fix in place, this test would have failed with + // - An uncaught exception of type com.sun.star.container.NoSuchElementException + // i.e. the composed name was split at the first instead of the last dot + uno::Any aTable; + CPPUNIT_ASSERT_NO_THROW(aTable = xTables->getByName(sComposedName)); + + Reference xNamed(aTable, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("table object does not implement XNamed", xNamed.is()); + CPPUNIT_ASSERT_EQUAL(u"tdf149434TestTable"_ustr, xNamed->getName()); + + Reference xTableProps(aTable, UNO_QUERY); + CPPUNIT_ASSERT_MESSAGE("table object does not implement XPropertySet", xTableProps.is()); + OUString sSchemaName; + xTableProps->getPropertyValue(u"SchemaName"_ustr) >>= sSchemaName; + CPPUNIT_ASSERT_EQUAL(sDottedSchema, sSchemaName); + + xStatement->executeUpdate("DROP DATABASE `" + sDottedSchema + "`"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(MysqlTestDriver); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/connectivity/source/commontools/dbtools.cxx b/connectivity/source/commontools/dbtools.cxx index 391377601b15..960c94da6a6b 100644 --- a/connectivity/source/commontools/dbtools.cxx +++ b/connectivity/source/commontools/dbtools.cxx @@ -895,7 +895,8 @@ void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaDa if ( aNameComps.bSchemas ) { - sal_Int32 nIndex = sName.indexOf('.'); + // tdf#149434 - use the last separator as table names cannot contain dots + sal_Int32 nIndex = sName.lastIndexOf('.'); // OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents: no schema separator!"); if ( nIndex != -1 ) _rSchema = sName.copy(0, nIndex);