diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-07-05 11:17:19 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2012-07-05 11:22:17 -0400 |
commit | fcc90b132168405e5a862fa4db8cfdcdcf632f65 (patch) | |
tree | f736e35bba101e540fa73685d33ec5db26852ad8 /sc/source/core/data | |
parent | f6ce48485c6dc5d278f94565de3745b18bda9992 (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.cxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/dpobject.cxx | 17 | ||||
-rw-r--r-- | sc/source/core/data/dpsave.cxx | 65 | ||||
-rw-r--r-- | sc/source/core/data/dpsdbtab.cxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/dpshttab.cxx | 5 |
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) {} |