summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2012-12-05 12:53:03 -0500
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2012-12-08 02:21:41 +0000
commitf421e804371670001bc5af25b8b66d67dfdb3261 (patch)
tree2e8920a9ce49aa6ecb8d199e93d9afb13e1b876d
parentd0a4a025855d78cdce194885c4df024c499bade6 (diff)
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 Reviewed-on: https://gerrit.libreoffice.org/1247 Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com> Tested-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
-rw-r--r--sc/inc/dpsave.hxx2
-rw-r--r--sc/qa/unit/ucalc.cxx29
-rw-r--r--sc/source/core/data/dpobject.cxx12
-rw-r--r--sc/source/core/data/dpsave.cxx37
-rw-r--r--sc/source/ui/view/dbfunc3.cxx43
5 files changed, 86 insertions, 37 deletions
diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index 14a0032150bd..4225d1b92bd7 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -345,6 +345,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 cab47a690fc6..795bea32a682 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2688,6 +2688,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 f4b39ffcf0e4..8db3c16abf8b 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -567,8 +567,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 5c987da177e8..f86dce4a5ad7 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -1221,6 +1221,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 bd3fa1919a9c..3f3992adc6ac 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -973,52 +973,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 )
{