summaryrefslogtreecommitdiff
path: root/sc/source/core/data
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2012-07-05 11:17:19 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2012-07-05 11:22:17 -0400
commitfcc90b132168405e5a862fa4db8cfdcdcf632f65 (patch)
treef736e35bba101e540fa73685d33ec5db26852ad8 /sc/source/core/data
parentf6ce48485c6dc5d278f94565de3745b18bda9992 (diff)
fdo#51266: Sync dimension members in several places upon refresh.
Or else the pivot table would generate erroneous results or crash after refresh. Change-Id: Ia14a6e3d25112e6ecd62d21928639f75e6a8ba7c
Diffstat (limited to 'sc/source/core/data')
-rw-r--r--sc/source/core/data/dpgroup.cxx5
-rw-r--r--sc/source/core/data/dpobject.cxx17
-rw-r--r--sc/source/core/data/dpsave.cxx65
-rw-r--r--sc/source/core/data/dpsdbtab.cxx5
-rw-r--r--sc/source/core/data/dpshttab.cxx5
5 files changed, 97 insertions, 0 deletions
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 9b5bf9b5763c..2959a65621b6 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -789,6 +789,11 @@ const ScDPCacheTable& ScDPGroupTableData::GetCacheTable() const
return pSourceData->GetCacheTable();
}
+void ScDPGroupTableData::ClearCacheTable()
+{
+ pSourceData->ClearCacheTable();
+}
+
void ScDPGroupTableData::FillGroupValues(vector<SCROW>& rItems, const vector<long>& rDims)
{
long nGroupedColumns = aGroups.size();
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index b4b62cfdc278..369307b012f2 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -699,6 +699,23 @@ void ScDPObject::BuildAllDimensionMembers()
pSaveData->BuildAllDimensionMembers(GetTableData());
}
+void ScDPObject::SyncAllDimensionMembers()
+{
+ if (!pSaveData)
+ return;
+
+ // #i111857# don't always create empty mpTableData for external service.
+ // Ideally, xSource should be used instead of mpTableData.
+ if (pServDesc)
+ return;
+
+ ScDPTableData* pData = GetTableData();
+ // Refresh the cache wrapper since the cache may have changed.
+ pData->ClearCacheTable();
+ pData->CreateCacheTable();
+ pSaveData->SyncAllDimensionMembers(pData);
+}
+
bool ScDPObject::GetMemberNames( sal_Int32 nDim, Sequence<OUString>& rNames )
{
vector<ScDPLabelData::Member> aMembers;
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
index 2bc011a8e548..fc289b93f2bf 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -37,6 +37,7 @@
#include "global.hxx"
#include "dptabsrc.hxx"
#include "dputil.hxx"
+#include "stlalgorithm.hxx"
#include <sal/types.h>
#include "comphelper/string.hxx"
@@ -732,6 +733,30 @@ bool ScDPSaveDimension::HasInvisibleMember() const
return false;
}
+void ScDPSaveDimension::RemoveObsoleteMembers(const MemberSetType& rMembers)
+{
+ maMemberHash.clear();
+ MemberList aNew;
+ MemberList::iterator it = maMemberList.begin(), itEnd = maMemberList.end();
+ for (; it != itEnd; ++it)
+ {
+ ScDPSaveMember* pMem = *it;
+ if (rMembers.count(pMem->GetName()))
+ {
+ // This member still exists.
+ maMemberHash.insert(MemberHash::value_type(pMem->GetName(), pMem));
+ aNew.push_back(pMem);
+ }
+ else
+ {
+ // This member no longer exists.
+ delete pMem;
+ }
+ }
+
+ maMemberList.swap(aNew);
+}
+
ScDPSaveData::ScDPSaveData() :
pDimensionData( NULL ),
nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
@@ -1260,6 +1285,46 @@ void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
mbDimensionMembersBuilt = true;
}
+void ScDPSaveData::SyncAllDimensionMembers(ScDPTableData* pData)
+{
+ typedef boost::unordered_map<rtl::OUString, long, rtl::OUStringHash> NameIndexMap;
+
+ // First, build a dimension name-to-index map.
+ NameIndexMap aMap;
+ long nColCount = pData->GetColumnCount();
+ for (long i = 0; i < nColCount; ++i)
+ aMap.insert(NameIndexMap::value_type(pData->getDimensionName(i), i));
+
+ NameIndexMap::const_iterator itMapEnd = aMap.end();
+
+ DimsType::iterator it = aDimList.begin(), itEnd = aDimList.end();
+ for (it = aDimList.begin(); it != itEnd; ++it)
+ {
+ const ::rtl::OUString& rDimName = it->GetName();
+ if (rDimName.isEmpty())
+ // empty dimension name. It must be data layout.
+ continue;
+
+ NameIndexMap::const_iterator itMap = aMap.find(rDimName);
+ if (itMap == itMapEnd)
+ // dimension name not in the data. This should never happen!
+ continue;
+
+ ScDPSaveDimension::MemberSetType aMemNames;
+ long nDimIndex = itMap->second;
+ const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
+ size_t nMemberCount = rMembers.size();
+ for (size_t j = 0; j < nMemberCount; ++j)
+ {
+ const ScDPItemData* pMemberData = pData->GetMemberById(nDimIndex, rMembers[j]);
+ rtl::OUString aMemName = pData->GetFormattedString(nDimIndex, *pMemberData);
+ aMemNames.insert(aMemName);
+ }
+
+ it->RemoveObsoleteMembers(aMemNames);
+ }
+}
+
bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
{
ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx
index b085473b2408..27c2ef23834f 100644
--- a/sc/source/core/data/dpsdbtab.cxx
+++ b/sc/source/core/data/dpsdbtab.cxx
@@ -177,6 +177,11 @@ const ScDPCacheTable& ScDatabaseDPData::GetCacheTable() const
return aCacheTable;
}
+void ScDatabaseDPData::ClearCacheTable()
+{
+ aCacheTable.clear();
+}
+
// -----------------------------------------------------------------------
diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx
index 43911c8a5a9f..8e9a982bf5ec 100644
--- a/sc/source/core/data/dpshttab.cxx
+++ b/sc/source/core/data/dpshttab.cxx
@@ -228,6 +228,11 @@ const ScDPCacheTable& ScSheetDPData::GetCacheTable() const
return aCacheTable;
}
+void ScSheetDPData::ClearCacheTable()
+{
+ aCacheTable.clear();
+}
+
ScSheetSourceDesc::ScSheetSourceDesc(ScDocument* pDoc) :
mpDoc(pDoc) {}