java-topology/defects/libreoffice-0001/patch/libreoffice-0001.patch

34 lines
1.9 KiB
Diff

# UNDF: UNDF-2026-000001119
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -1404,16 +1404,22 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScD
if (eOrient == sheet::DataPilotFieldOrientation_ROW)
aRowMemberResultData.initLookupFor(pDim->GetName());
else if (eOrient == sheet::DataPilotFieldOrientation_COLUMN)
aColumnMemberResultData.initLookupFor(pDim->GetName());
+ // Build O(1) name-to-index lookup to replace O(C) std::find in the loop below.
+ // Without this map, the loop is O(M * C) where M = aMembers.size() and
+ // C = aCacheFieldItems.size(). Large pivot tables with many distinct values
+ // (e.g. 5000-row data with a text dimension) exhibit quadratic save times.
+ std::unordered_map<OUString, size_t> aCacheItemIndex;
+ aCacheItemIndex.reserve(aCacheFieldItems.size());
+ for (size_t k = 0; k < aCacheFieldItems.size(); ++k)
+ aCacheItemIndex.emplace(aCacheFieldItems[k], k);
+
// The pair contains the member index in cache and if it is hidden
std::vector< std::pair<size_t, bool> > aMemberSequence;
std::set<size_t> aUsedCachePositions;
sal_Int32 nIndex = 0;
for (const auto & rMember : aMembers)
{
- auto it = std::find(aCacheFieldItems.begin(), aCacheFieldItems.end(), rMember.maName);
- if (it != aCacheFieldItems.end())
+ auto mapIt = aCacheItemIndex.find(rMember.maName);
+ if (mapIt != aCacheItemIndex.end())
{
- size_t nCachePos = static_cast<size_t>(std::distance(aCacheFieldItems.begin(), it));
+ size_t nCachePos = mapIt->second;
auto aInserted = aUsedCachePositions.insert(nCachePos);
if (aInserted.second)
{