[Libreoffice-commits] core.git: sc/inc sc/source

Tamás Zolnai tamas.zolnai at collabora.com
Mon Sep 26 19:24:21 UTC 2016


 sc/inc/dpobject.hxx                |    2 +
 sc/source/core/data/dpobject.cxx   |   74 +++++++++++++++++++++++++++++++++++++
 sc/source/ui/docshell/dbdocfun.cxx |   54 +++++++++++++++++++--------
 3 files changed, 114 insertions(+), 16 deletions(-)

New commits:
commit 3b64a198568d5b2bb14066581aca112cc6182fd7
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
Date:   Tue Sep 27 05:08:51 2016 +0200

    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

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 92ceff1..747bcfb 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 4ba4398..302eea5 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 2dfee90..3b7cdbf 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();
     }
 }
 


More information about the Libreoffice-commits mailing list