[Libreoffice-commits] .: sc/inc sc/source
Kohei Yoshida
kohei at kemper.freedesktop.org
Thu Jul 5 08:18:56 PDT 2012
sc/inc/dpcachetable.hxx | 6 +++
sc/inc/dpgroup.hxx | 1
sc/inc/dpobject.hxx | 6 +++
sc/inc/dpsave.hxx | 5 ++
sc/inc/dpsdbtab.hxx | 1
sc/inc/dpshttab.hxx | 1
sc/inc/dptabdat.hxx | 1
sc/source/core/data/dpgroup.cxx | 5 ++
sc/source/core/data/dpobject.cxx | 17 +++++++++
sc/source/core/data/dpsave.cxx | 65 +++++++++++++++++++++++++++++++++++++
sc/source/core/data/dpsdbtab.cxx | 5 ++
sc/source/core/data/dpshttab.cxx | 5 ++
sc/source/ui/docshell/dbdocfun.cxx | 1
13 files changed, 119 insertions(+)
New commits:
commit fa2b7eff2d40b6455970b521306c5961e4e3cec4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Thu Jul 5 11:17:19 2012 -0400
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
diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx
index f104d3b..d834910 100644
--- a/sc/inc/dpcachetable.hxx
+++ b/sc/inc/dpcachetable.hxx
@@ -56,6 +56,12 @@ class ScRange;
struct ScDPValueData;
struct ScQueryParam;
+/**
+ * Despite the name, this class is only a wrapper to the actual cache, to
+ * provide filtering on the raw data based on the query filter and/or page
+ * field filters. I will rename this class to a more appropriate name in the
+ * future.
+ */
class SC_DLLPUBLIC ScDPCacheTable
{
struct RowFlag
diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx
index 4bf9972..5d48af0 100644
--- a/sc/inc/dpgroup.hxx
+++ b/sc/inc/dpgroup.hxx
@@ -182,6 +182,7 @@ public:
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
virtual void CalcResults(CalcInfo& rInfo, bool bAutoShow);
virtual const ScDPCacheTable& GetCacheTable() const;
+ virtual void ClearCacheTable();
virtual sal_Bool IsBaseForGroup(long nDim) const;
virtual long GetGroupBase(long nGroupDim) const;
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index da0fc09..e163ef1 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -239,6 +239,12 @@ public:
void BuildAllDimensionMembers();
+ /**
+ * Remove in the save data entries for members that don't exist anymore.
+ * This is called during pivot table refresh.
+ */
+ void SyncAllDimensionMembers();
+
static bool HasRegisteredSources();
static com::sun::star::uno::Sequence<rtl::OUString> GetRegisteredSources();
static com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier>
diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index c4df4ed..28bfafd 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -33,6 +33,7 @@
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
#include <boost/scoped_ptr.hpp>
#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
@@ -122,6 +123,7 @@ private:
::com::sun::star::sheet::DataPilotFieldLayoutInfo* pLayoutInfo; // (level)
public:
+ typedef boost::unordered_set<rtl::OUString, rtl::OUStringHash> MemberSetType;
typedef boost::unordered_map <rtl::OUString, ScDPSaveMember*, rtl::OUStringHash> MemberHash;
typedef std::list <ScDPSaveMember*> MemberList;
@@ -230,6 +232,8 @@ public:
void UpdateMemberVisibility(const ::boost::unordered_map< ::rtl::OUString, bool, ::rtl::OUStringHash>& rData);
bool HasInvisibleMember() const;
+
+ void RemoveObsoleteMembers(const MemberSetType& rMembers);
};
@@ -344,6 +348,7 @@ public:
SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there
void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied
void BuildAllDimensionMembers(ScDPTableData* pData);
+ void SyncAllDimensionMembers(ScDPTableData* pData);
/**
* Check whether a dimension has one or more invisible members.
diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx
index eba6da2..a96b011 100644
--- a/sc/inc/dpsdbtab.hxx
+++ b/sc/inc/dpsdbtab.hxx
@@ -88,6 +88,7 @@ public:
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
virtual void CalcResults(CalcInfo& rInfo, bool bAutoShow);
virtual const ScDPCacheTable& GetCacheTable() const;
+ virtual void ClearCacheTable();
};
diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx
index 3a0fcb3..510105d 100644
--- a/sc/inc/dpshttab.hxx
+++ b/sc/inc/dpshttab.hxx
@@ -128,6 +128,7 @@ public:
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
virtual void CalcResults(CalcInfo& rInfo, bool bAutoShow);
virtual const ScDPCacheTable& GetCacheTable() const;
+ virtual void ClearCacheTable();
};
diff --git a/sc/inc/dptabdat.hxx b/sc/inc/dptabdat.hxx
index 1bbc4d6..f19a6ba 100644
--- a/sc/inc/dptabdat.hxx
+++ b/sc/inc/dptabdat.hxx
@@ -154,6 +154,7 @@ public:
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData) = 0;
virtual void CalcResults(CalcInfo& rInfo, bool bAutoShow) = 0;
virtual const ScDPCacheTable& GetCacheTable() const = 0;
+ virtual void ClearCacheTable() = 0;
// overloaded in ScDPGroupTableData:
virtual sal_Bool IsBaseForGroup(long nDim) const;
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 203dbe9..4a263df 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -784,6 +784,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 5a32643..6d33843 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -696,6 +696,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 41148a4..62bda08 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -34,6 +34,7 @@
#include "global.hxx"
#include "dptabsrc.hxx"
#include "dputil.hxx"
+#include "stlalgorithm.hxx"
#include <sal/types.h>
#include "comphelper/string.hxx"
@@ -729,6 +730,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 ),
@@ -1257,6 +1282,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 b5935c7..f1621eb 100644
--- a/sc/source/core/data/dpsdbtab.cxx
+++ b/sc/source/core/data/dpsdbtab.cxx
@@ -172,6 +172,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 09230f0..797fa27 100644
--- a/sc/source/core/data/dpshttab.cxx
+++ b/sc/source/core/data/dpshttab.cxx
@@ -223,6 +223,11 @@ const ScDPCacheTable& ScSheetDPData::GetCacheTable() const
return aCacheTable;
}
+void ScSheetDPData::ClearCacheTable()
+{
+ aCacheTable.clear();
+}
+
ScSheetSourceDesc::ScSheetSourceDesc(ScDocument* pDoc) :
mpDoc(pDoc) {}
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 2bf2e58..ffcc59e 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -1473,6 +1473,7 @@ sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi)
for (; it != itEnd; ++it)
{
ScDPObject* pObj = *it;
+ pObj->SyncAllDimensionMembers();
// This action is intentionally not undoable since it modifies cache.
DataPilotUpdate(pObj, pObj, false, bApi);
More information about the Libreoffice-commits
mailing list