diff options
author | Tamás Zolnai <tamas.zolnai@collabora.com> | 2016-09-27 05:08:51 +0200 |
---|---|---|
committer | Tamás Zolnai <tamas.zolnai@collabora.com> | 2016-09-27 05:26:02 +0200 |
commit | 3b64a198568d5b2bb14066581aca112cc6182fd7 (patch) | |
tree | 9f0c7dab5062a1de141d71f8186d47ff09e1e17d | |
parent | 622bb4bc72ee6e8eae3193e80e13748be150e1e0 (diff) |
bnc#957991: Improve pivot cache reading performance
Performance problem was caused by grouping. Pivot
tables with the same source are linked to each other
by the pivot cache and so all the pivot tables were
updated when one group was added to one of the tables.
This code change first of all fixes a functional issue:
group name was wrongly imported and so pivot tables using
group fields were broken. This caused by calling
RefreshPivotTableGroups() on a pivot table which is not part
of the cache yet and so update was not called on this table.
Calling ReloadGroupTableData() solve this problem.
Second part of the codechange is about the consistency
of the pivot cache. We have an invariant in this code to
have the same groups for tabels with the same source.
To keep this invariant we update every newly inserted
tables adding the neccessary groups.
The performance improvement here is that until the table
is not part of the cache, it does not updates other tables.
Group syncronization is done when the table is inserted to
the ScDPCollection.
Change-Id: Iaff55ffa3ed9c9b48cb18bd150eb4e1f7b617353
-rw-r--r-- | sc/inc/dpobject.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/dpobject.cxx | 74 | ||||
-rw-r--r-- | sc/source/ui/docshell/dbdocfun.cxx | 54 |
3 files changed, 114 insertions, 16 deletions
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 92ceff14fa0a..747bcfbac18c 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -365,6 +365,7 @@ public: sal_uLong ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs); bool ReloadGroupsInCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs); + bool GetReferenceGroups(const ScDPObject& rDPObj, const ScDPDimensionSaveData** pGroups) const; SC_DLLPUBLIC size_t GetCount() const; SC_DLLPUBLIC ScDPObject& operator[](size_t nIndex); @@ -389,6 +390,7 @@ public: void FreeTable(ScDPObject* pDPObj); SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj); + bool HasTable(ScDPObject* pDPObj) const; SC_DLLPUBLIC SheetCaches& GetSheetCaches(); SC_DLLPUBLIC const SheetCaches& GetSheetCaches() const; diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 4ba4398aae69..302eea5bcbfa 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -3545,6 +3545,68 @@ bool ScDPCollection::ReloadGroupsInCache(ScDPObject* pDPObj, std::set<ScDPObject return true; } +bool ScDPCollection::GetReferenceGroups(const ScDPObject& rDPObj, const ScDPDimensionSaveData** pGroups) const +{ + for (const std::unique_ptr<ScDPObject>& aTable : maTables) + { + const ScDPObject& rRefObj = *aTable.get(); + + if (rDPObj.IsSheetData()){ + if(!rRefObj.IsSheetData()) + continue; + + const ScSheetSourceDesc* pDesc = rDPObj.GetSheetDesc(); + const ScSheetSourceDesc* pRefDesc = rRefObj.GetSheetDesc(); + if (pDesc == nullptr || pRefDesc == nullptr) + continue; + + if (pDesc->HasRangeName()) + { + if (!pRefDesc->HasRangeName()) + continue; + + if (pDesc->GetRangeName() == pRefDesc->GetRangeName()) + { + *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData(); + return true; + } + } + else + { + if (pRefDesc->HasRangeName()) + continue; + + if (pDesc->GetSourceRange() == pRefDesc->GetSourceRange()) + { + *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData(); + return true; + } + } + } + else if (rDPObj.IsImportData()) + { + if (!rRefObj.IsImportData ()) + continue; + + const ScImportSourceDesc* pDesc = rDPObj.GetImportSourceDesc(); + const ScImportSourceDesc* pRefDesc = rRefObj.GetImportSourceDesc(); + if (pDesc == nullptr || pRefDesc == nullptr) + continue; + + if (pDesc->aDBName.equals(pRefDesc->aDBName) && + pDesc->aObject.equals(pRefDesc->aObject) && + pDesc->GetCommandType() == pRefDesc->GetCommandType()) + { + *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData(); + return true; + } + + } + } + return false; +} + + void ScDPCollection::DeleteOnTab( SCTAB nTab ) { maTables.erase( std::remove_if(maTables.begin(), maTables.end(), MatchByTable(nTab)), maTables.end()); @@ -3724,6 +3786,18 @@ bool ScDPCollection::InsertNewTable(ScDPObject* pDPObj) return true; } +bool ScDPCollection::HasTable(ScDPObject* pDPObj) const +{ + for (const std::unique_ptr<ScDPObject>& aTable : maTables) + { + if (aTable.get() == pDPObj) + { + return true; + } + } + return false; +} + ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches() { return maSheetCaches; diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 2dfee907fb9e..3b7cdbfeb74c 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -1386,6 +1386,19 @@ bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName())) rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below + // Syncronize groups between linked tables + { + bool bRefFound = false; + const ScDPDimensionSaveData* pGroups = nullptr; + bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups); + if (bRefFound) + { + ScDPSaveData* pSaveData = rDestObj.GetSaveData(); + if (pSaveData) + pSaveData->SetDimensionData(pGroups); + } + } + if (!rDoc.GetDPCollection()->InsertNewTable(pDestObj.release())) // Insertion into collection failed. return false; @@ -1567,25 +1580,34 @@ void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj) if (!pSaveData) return; - std::set<ScDPObject*> aRefs; - if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs)) - return; - - // We allow pDimData being NULL. - const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData(); - std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end(); - for (; it != itEnd; ++it) + // Update all linked tables, if this table is part of the cache (ScDPCollection) + if (pDPs->HasTable(pDPObj)) { - ScDPObject* pObj = *it; - if (pObj != pDPObj) + std::set<ScDPObject*> aRefs; + if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs)) + return; + + // We allow pDimData being NULL. + const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData(); + std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end(); + for (; it != itEnd; ++it) { - pSaveData = pObj->GetSaveData(); - if (pSaveData) - pSaveData->SetDimensionData(pDimData); - } + ScDPObject* pObj = *it; + if (pObj != pDPObj) + { + pSaveData = pObj->GetSaveData(); + if (pSaveData) + pSaveData->SetDimensionData(pDimData); + } - // This action is intentionally not undoable since it modifies cache. - UpdatePivotTable(*pObj, false, false); + // This action is intentionally not undoable since it modifies cache. + UpdatePivotTable(*pObj, false, false); + } + } + else // Otherwise update only this single table + { + // This table is under construction so no need for a whole update (UpdatePivotTable()). + pDPObj->ReloadGroupTableData(); } } |