sw/inc/doc.hxx | 3 ++- sw/source/core/docnode/ndtbl.cxx | 7 +++++-- sw/source/core/unocore/unotbl.cxx | 33 ++++++++++++++++++--------------- sw/source/filter/xml/xmlimp.cxx | 3 ++- sw/source/filter/xml/xmlimp.hxx | 7 +++++++ sw/source/filter/xml/xmltbli.cxx | 19 ++++++++++++++++--- 6 files changed, 50 insertions(+), 22 deletions(-)
New commits: commit b398c4b9f2e360a712884d69232228c8048a23b4 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Mar 31 17:38:42 2023 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Mar 31 20:00:50 2023 +0200 tdf#154486: Use known name when inserting the table into the document ... instead of assinging a unique name at insertion time, then changing to the final value. As discussed in commit 1dd71d79e15bd8098e7c17c8fcea3748592a902f (tdf#154486: use importer-local map to deduplicate table names, 2023-03-31), the lookup for a unique table name has an O(n^2) complexity, and can make loading of thousands tables impossible. This changes import time from 23 s to ~2.5 s, and the time now depends on the number of tables linearly (e.g., 200 000 tables load in ~45 s). Change-Id: I0f2b5e37db2d370bccbc8c3430f895c864d9a4c2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149840 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit 18e4c95a59809f4109f13934f2f072aee1cea000) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149874 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 4a399b839896..428e64bcd9c7 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -1176,7 +1176,8 @@ public: const SwTableAutoFormat* pTAFormat = nullptr, const std::vector<sal_uInt16> *pColArr = nullptr, bool bCalledFromShell = false, - bool bNewModel = true ); + bool bNewModel = true, + const OUString& rTableName = {} ); // If index is in a table, return TableNode, else 0. static SwTableNode* IsIdxInTable( const SwNodeIndex& rIdx ); diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx index 77f7a4d3e97c..b4ea4cfe80d2 100644 --- a/sw/source/core/docnode/ndtbl.cxx +++ b/sw/source/core/docnode/ndtbl.cxx @@ -340,7 +340,8 @@ const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTableOpts, const SwTableAutoFormat* pTAFormat, const std::vector<sal_uInt16> *pColArr, bool bCalledFromShell, - bool bNewModel ) + bool bNewModel, + const OUString& rTableName ) { assert(nRows && "Table without line?"); assert(nCols && "Table without rows?"); @@ -357,7 +358,9 @@ const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTableOpts, pColArr = nullptr; } - OUString aTableName = GetUniqueTableName(); + OUString aTableName = rTableName; + if (aTableName.isEmpty() || FindTableFormatByName(aTableName) != nullptr) + aTableName = GetUniqueTableName(); if( GetIDocumentUndoRedo().DoesUndo() ) { diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx index f1d697a36c81..76b439cd6d11 100644 --- a/sw/source/core/unocore/unotbl.cxx +++ b/sw/source/core/unocore/unotbl.cxx @@ -2121,11 +2121,28 @@ SwXTextTable::attach(const uno::Reference<text::XTextRange> & xTextRange) pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam); aPam.DeleteMark(); } + + OUString tableName; + if (const::uno::Any* pName; + m_pImpl->m_pTableProps->GetProperty(FN_UNO_TABLE_NAME, 0, pName)) + { + tableName = pName->get<OUString>(); + } + else if (!m_pImpl->m_sTableName.isEmpty()) + { + sal_uInt16 nIndex = 1; + tableName = m_pImpl->m_sTableName; + while (pDoc->FindTableFormatByName(tableName, true) && nIndex < USHRT_MAX) + tableName = m_pImpl->m_sTableName + OUString::number(nIndex++); + } + pTable = pDoc->InsertTable(SwInsertTableOptions( SwInsertTableFlags::Headline | SwInsertTableFlags::DefaultBorder | SwInsertTableFlags::SplitLayout, 0 ), *aPam.GetPoint(), m_pImpl->m_nRows, m_pImpl->m_nColumns, - text::HoriOrientation::FULL); + text::HoriOrientation::FULL, + nullptr, nullptr, false, true, + tableName); if(pTable) { // here, the properties of the descriptor need to be analyzed @@ -2135,20 +2152,6 @@ SwXTextTable::attach(const uno::Reference<text::XTextRange> & xTextRange) m_pImpl->SetFrameFormat(*pTableFormat); - if (!m_pImpl->m_sTableName.isEmpty()) - { - sal_uInt16 nIndex = 1; - OUString sTmpNameIndex(m_pImpl->m_sTableName); - while(pDoc->FindTableFormatByName(sTmpNameIndex, true) && nIndex < USHRT_MAX) - { - sTmpNameIndex = m_pImpl->m_sTableName + OUString::number(nIndex++); - } - pDoc->SetTableName( *pTableFormat, sTmpNameIndex); - } - - const::uno::Any* pName; - if (m_pImpl->m_pTableProps->GetProperty(FN_UNO_TABLE_NAME, 0, pName)) - setName(pName->get<OUString>()); m_pImpl->m_pTableProps.reset(); } pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr ); diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx index fec24079defc..acc01482cda4 100644 --- a/sw/source/filter/xml/xmltbli.cxx +++ b/sw/source/filter/xml/xmltbli.cxx @@ -53,6 +53,7 @@ #include <swtable.hxx> #include <swtblfmt.hxx> #include <pam.hxx> +#include <unoprnms.hxx> #include <unotbl.hxx> #include <unotextrange.hxx> #include <cellatr.hxx> @@ -1212,6 +1213,8 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, if( xTable.is() ) { xTable->initialize( 1, 1 ); + if (css::uno::Reference<css::beans::XPropertySet> xPropSet{ xTable, css::uno::UNO_QUERY }) + xPropSet->setPropertyValue(UNO_NAME_TABLE_NAME, css::uno::Any(sTableName)); try { @@ -1251,8 +1254,6 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, m_pTableNode = pTable->GetTableNode(); OSL_ENSURE( m_pTableNode, "table node missing" ); - pTableFrameFormat->SetFormatName( sTableName ); - SwTableLine *pLine1 = m_pTableNode->GetTable().GetTabLines()[0U]; m_pBox1 = pLine1->GetTabBoxes()[0U]; m_pSttNd1 = m_pBox1->GetSttNd(); commit f75553b3f9071d8aa0deb4d9d4a5d4db431a8abd Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Mar 31 10:51:32 2023 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Mar 31 20:00:37 2023 +0200 tdf#154486: use importer-local map to deduplicate table names ... instead of SwDoc::GetUniqueTableName. The latter is expensive with many tables, has O(n^2) complexity with rather large O, and in corner cases of thousands tables with no or duplicate names, is unacceptably slow. Changes the test case import time from 39 s to 23 s on my system. Change-Id: Ia461c860d56cbbfdcb25bacbb9cca4961ced885e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149817 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit 2548f3c65ceb2a1a341b52ecdbde6846decc0fdc) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149796 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx index 2cb58cf2aa47..5ef66a1bf36f 100644 --- a/sw/source/filter/xml/xmlimp.cxx +++ b/sw/source/filter/xml/xmlimp.cxx @@ -324,7 +324,8 @@ SwXMLImport::SwXMLImport( m_bBlock( false ), m_bOrganizerMode( false ), m_bInititedXForms( false ), - m_pDoc( nullptr ) + m_pDoc( nullptr ), + m_sDefTableName(SwResId(STR_TABLE_DEFNAME)) { InitItemImport(); } diff --git a/sw/source/filter/xml/xmlimp.hxx b/sw/source/filter/xml/xmlimp.hxx index 22f012c4dbfc..8791958fc69c 100644 --- a/sw/source/filter/xml/xmlimp.hxx +++ b/sw/source/filter/xml/xmlimp.hxx @@ -84,6 +84,10 @@ class SwXMLImport: public SvXMLImport SwDoc* m_pDoc; // cached for getDoc() + // Optimization for new table name lookup + OUString m_sDefTableName; // See STR_TABLE_DEFNAME + std::map<OUString, sal_uInt32> m_aTableNameMap; // Last used indices for duplicating table names + void InitItemImport(); void FinitItemImport(); void UpdateTextCollConditions( SwDoc *pDoc ); @@ -167,6 +171,9 @@ public: const SwDoc* getDoc() const; SwDoc* getDoc(); + + const OUString& GetDefTableName() { return m_sDefTableName; } + std::map<OUString, sal_uInt32>& GetTableNameMap() { return m_aTableNameMap; } }; inline const SvXMLImportItemMapper& SwXMLImport::GetTableItemMapper() const diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx index 44ae125d30b0..fec24079defc 100644 --- a/sw/source/filter/xml/xmltbli.cxx +++ b/sw/source/filter/xml/xmltbli.cxx @@ -1178,7 +1178,19 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, } if( sTableName.isEmpty() ) { - sTableName = pDoc->GetUniqueTableName(); + // Optimization: use import's own map to create unique names, because + // SwDoc::GetUniqueTableName scans all the already present tables, + // builds a bitset using rather complex rules, and that has quadratic + // complexity. Try once, then fallback to SwDoc::GetUniqueTableName + auto& tableNameMap = rImport.GetTableNameMap(); + sal_Int32 nextIx = ++tableNameMap[aName]; + OUString test = aName.isEmpty() + ? OUString(rImport.GetDefTableName() + OUString::number(nextIx)) + : OUString(aName + "_" + OUString::number(nextIx)); + if (const SwTableFormat* pExisting = pDoc->FindTableFormatByName(test); !pExisting) + sTableName = test; + else + sTableName = pDoc->GetUniqueTableName(); GetImport().GetTextImport() ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE, aName, sTableName ); }