[Libreoffice-commits] .: sc/inc sc/qa sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Dec 5 09:57:15 PST 2012


 sc/inc/dpsave.hxx                |    2 +
 sc/qa/unit/ucalc.cxx             |   29 ++++++++++++++++++++++++++
 sc/source/core/data/dpobject.cxx |   12 +++++++++-
 sc/source/core/data/dpsave.cxx   |   37 +++++++++++++++++++++++++++++++++
 sc/source/ui/view/dbfunc3.cxx    |   43 ++++++---------------------------------
 5 files changed, 86 insertions(+), 37 deletions(-)

New commits:
commit 56bb08e75c12cb85041607f7f34451018b09414f
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Dec 5 12:53:03 2012 -0500

    fdo#57497: Remove group table data when all group dimensions are gone.
    
    Otherwise ungrouping date grouped dimension may crash, or produce
    incorrect results.
    
    Change-Id: I3634e3c0bf8336fc1221f5d234cb7e01eb1f07c6

diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index 5a97b54..948117b 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -336,6 +336,8 @@ public:
     const ScDPDimensionSaveData* GetExistingDimensionData() const
         { return pDimensionData; }
 
+    void RemoveAllGroupDimensions( const rtl::OUString& rSrcDimName, std::vector<rtl::OUString>* pDeletedNames = NULL );
+
     SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there
     void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied
     void BuildAllDimensionMembers(ScDPTableData* pData);
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index e3de176..2509400 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2964,6 +2964,35 @@ void Test::testPivotTableDateGrouping()
         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
     }
 
+    // Remove all date grouping. The source dimension "Date" has two
+    // external dimensions ("Years" and "Quarters") and one internal ("Date"
+    // the same name but different hierarchy).  Remove all of them.
+    pSaveData = pDPObj->GetSaveData();
+    pSaveData->RemoveAllGroupDimensions(aBaseDimName);
+    pDPObj->SetSaveData(*pSaveData);
+    pDPObj->ReloadGroupTableData();
+    pDPObj->InvalidateData();
+
+    aOutRange = refresh(pDPObj);
+    {
+        // Expected output table content.  0 = empty cell
+        const char* aOutputCheck[][2] = {
+            { "Date", 0 },
+            { "2011-01-01", "1" },
+            { "2011-03-02", "2" },
+            { "2011-09-03", "7" },
+            { "2012-01-04", "3" },
+            { "2012-02-23", "4" },
+            { "2012-02-24", "5" },
+            { "2012-03-15", "6" },
+            { "2012-12-25", "8" },
+            { "Total Result", "36" }
+        };
+
+        bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Remove all date grouping.");
+        CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
+    }
+
     pDPs->FreeTable(pDPObj);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 529de6b..9b78336 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -710,8 +710,18 @@ void ScDPObject::ReloadGroupTableData()
 
     const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
     if (!pDimData || !pDimData->HasGroupDimensions())
-        // No group dimensions exist.
+    {
+        // No group dimensions exist.  Check if it currently has group
+        // dimensions, and if so, remove all of them.
+        ScDPGroupTableData* pData = dynamic_cast<ScDPGroupTableData*>(mpTableData.get());
+        if (pData)
+        {
+            // Replace the existing group table data with the source data.
+            shared_ptr<ScDPTableData> pSource = pData->GetSourceTableData();
+            mpTableData = pSource;
+        }
         return;
+    }
 
     ScDPGroupTableData* pData = dynamic_cast<ScDPGroupTableData*>(mpTableData.get());
     if (pData)
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
index 3a9f174..5fcd8d7 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -1209,6 +1209,43 @@ bool ScDPSaveData::IsEmpty() const
     return true; // no entries that are not hidden
 }
 
+void ScDPSaveData::RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames )
+{
+    if (!pDimensionData)
+        // No group dimensions exist.  Nothing to do.
+        return;
+
+    // Remove numeric group dimension (exists once at most). No need to delete
+    // anything in save data (grouping was done inplace in an existing base
+    // dimension).
+    pDimensionData->RemoveNumGroupDimension(rSrcDimName);
+
+    // Remove named group dimension(s). Dimensions have to be removed from
+    // dimension save data and from save data too.
+    const ScDPSaveGroupDimension* pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
+    while ( pExistingGroup )
+    {
+        rtl::OUString aGroupDimName = pExistingGroup->GetGroupDimName();
+        pDimensionData->RemoveGroupDimension(aGroupDimName);     // pExistingGroup is deleted
+
+        // also remove SaveData settings for the dimension that no longer exists
+        RemoveDimensionByName(aGroupDimName);
+
+        if (pDeletedNames)
+            pDeletedNames->push_back(aGroupDimName);
+
+        // see if there are more group dimensions
+        pExistingGroup = pDimensionData->GetGroupDimForBase(rSrcDimName);
+
+        if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
+        {
+            // still get the same group dimension?
+            OSL_FAIL("couldn't remove group dimension");
+            pExistingGroup = NULL;      // avoid endless loop
+        }
+    }
+}
+
 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
 {
     if (!pDimensionData)
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index 5f58d70..5925e3f 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -946,52 +946,23 @@ void ScDBFunc::DateGroupDataPilot( const ScDPNumGroupInfo& rInfo, sal_Int32 nPar
     if (aEntries.empty())
         return;
 
+    std::vector<rtl::OUString> aDeletedNames;
     bool bIsDataLayout;
     OUString aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
 
     ScDPSaveData aData( *pDPObj->GetSaveData() );
     ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
 
-    // find original base
+    // find the source dimension name.
     rtl::OUString aBaseDimName = aDimName;
     if( const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ) )
         aBaseDimName = pBaseGroupDim->GetSourceDimName();
 
-    // remove all existing parts (the grouping is built completely new)
-
-    /*  Remove numeric group dimension (exists once at most). No need
-        to delete anything in save data (grouping was done inplace in
-        an existing base dimension). */
-    pDimData->RemoveNumGroupDimension( aBaseDimName );
-
-    /*  Remove named group dimension(s). Collect deleted dimension
-        names which may be reused while recreating the groups.
-        Dimensions have to be removed from dimension save data and from
-        save data too. */
-    std::vector<rtl::OUString> aDeletedNames;
-    const ScDPSaveGroupDimension* pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName );
-    while ( pExistingGroup )
-    {
-        rtl::OUString aGroupDimName = pExistingGroup->GetGroupDimName();
-        pDimData->RemoveGroupDimension( aGroupDimName );     // pExistingGroup is deleted
-
-        // also remove SaveData settings for the dimension that no longer exists
-        aData.RemoveDimensionByName( aGroupDimName );
-
-        /*  The name can be used for the new group dimensions, although
-            it is still in use with the DataPilotSource. */
-        aDeletedNames.push_back( aGroupDimName );
-
-        // see if there are more group dimensions
-        pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName );
-
-        if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
-        {
-            // still get the same group dimension?
-            OSL_FAIL("couldn't remove group dimension");
-            pExistingGroup = NULL;      // avoid endless loop
-        }
-    }
+    // Remove all group dimensions associated with this source dimension. For
+    // date grouping, we need to remove all existing groups for the affected
+    // source dimension and build new one(s) from scratch.  Keep the deleted
+    // names so that they can be reused during re-construction.
+    aData.RemoveAllGroupDimensions(aBaseDimName, &aDeletedNames);
 
     if ( nParts )
     {


More information about the Libreoffice-commits mailing list