From 561b044d62f4701e51abb4a7c47ce3b07f788f8e Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Mon, 23 Jan 2012 16:34:15 -0500 Subject: Fix refresh problem on pivot tables whose data cache have not been created. --- sc/inc/dpobject.hxx | 7 +++ sc/source/core/data/dpobject.cxx | 121 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index a894833f07d0..f7126b12e421 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -328,6 +328,7 @@ public: ScDocument* mpDoc; public: DBCaches(ScDocument* pDoc); + bool hasCache(sal_Int32 nSdbType, const rtl::OUString& rDBName, const rtl::OUString& rCommand) const; const ScDPCache* getCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); private: @@ -382,6 +383,12 @@ private: /** Only to be called from ScDPCache::RemoveReference(). */ void RemoveCache(const ScDPCache* pCache); + void GetAllTables(const ScRange& rSrcRange, std::set& rRefs) const; + void GetAllTables(const rtl::OUString& rSrcName, std::set& rRefs) const; + void GetAllTables( + sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand, + std::set& rRefs) const; + private: typedef ::boost::ptr_vector TablesType; diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 984d3de55bf1..d5ac78805b4b 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -2680,6 +2680,13 @@ bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& ScDPCollection::DBCaches::DBCaches(ScDocument* pDoc) : mpDoc(pDoc) {} +bool ScDPCollection::DBCaches::hasCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) const +{ + DBType aType(nSdbType, rDBName, rCommand); + CachesType::const_iterator itr = maCaches.find(aType); + return itr != maCaches.end(); +} + const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) { DBType aType(nSdbType, rDBName, rCommand); @@ -2872,13 +2879,27 @@ sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set& { // cache by named range ScDPCollection::NameCaches& rCaches = GetNameCaches(); - rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs); + if (rCaches.hasCache(pDesc->GetRangeName())) + rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs); + else + { + // Not cached yet. Collect all tables that use this named + // range as data source. + GetAllTables(pDesc->GetRangeName(), rRefs); + } } else { // cache by cell range ScDPCollection::SheetCaches& rCaches = GetSheetCaches(); - rCaches.updateCache(pDesc->GetSourceRange(), rRefs); + if (rCaches.hasCache(pDesc->GetSourceRange())) + rCaches.updateCache(pDesc->GetSourceRange(), rRefs); + else + { + // Not cached yet. Collect all tables that use this range as + // data source. + GetAllTables(pDesc->GetSourceRange(), rRefs); + } } } else if (pDPObj->IsImportData()) @@ -2889,8 +2910,15 @@ sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set& return STR_ERR_DATAPILOTSOURCE; ScDPCollection::DBCaches& rCaches = GetDBCaches(); - rCaches.updateCache( - pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs); + if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject)) + rCaches.updateCache( + pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs); + else + { + // Not cached yet. Collect all tables that use this range as + // data source. + GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs); + } } return 0; } @@ -3116,6 +3144,91 @@ void ScDPCollection::RemoveCache(const ScDPCache* pCache) return; } +void ScDPCollection::GetAllTables(const ScRange& rSrcRange, std::set& rRefs) const +{ + std::set aRefs; + TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end(); + for (; it != itEnd; ++it) + { + const ScDPObject& rObj = *it; + if (!rObj.IsSheetData()) + // Source is not a sheet range. + continue; + + const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc(); + if (!pDesc) + continue; + + if (pDesc->HasRangeName()) + // This table has a range name as its source. + continue; + + if (pDesc->GetSourceRange() != rSrcRange) + // Different source range. + continue; + + aRefs.insert(const_cast(&rObj)); + } + + rRefs.swap(aRefs); +} + +void ScDPCollection::GetAllTables(const rtl::OUString& rSrcName, std::set& rRefs) const +{ + std::set aRefs; + TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end(); + for (; it != itEnd; ++it) + { + const ScDPObject& rObj = *it; + if (!rObj.IsSheetData()) + // Source is not a sheet range. + continue; + + const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc(); + if (!pDesc) + continue; + + if (!pDesc->HasRangeName()) + // This table probably has a sheet range as its source. + continue; + + if (pDesc->GetRangeName() != rSrcName) + // Different source name. + continue; + + aRefs.insert(const_cast(&rObj)); + } + + rRefs.swap(aRefs); +} + +void ScDPCollection::GetAllTables( + sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand, + std::set& rRefs) const +{ + std::set aRefs; + TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end(); + for (; it != itEnd; ++it) + { + const ScDPObject& rObj = *it; + if (!rObj.IsImportData()) + // Source data is not a database. + continue; + + const ScImportSourceDesc* pDesc = rObj.GetImportSourceDesc(); + if (!pDesc) + continue; + + if (!pDesc->aDBName.equals(rDBName) || !pDesc->aObject.equals(rCommand) || pDesc->GetCommandType() != nSdbType) + // Different database source. + continue; + + aRefs.insert(const_cast(&rObj)); + } + + rRefs.swap(aRefs); +} + bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right) { if (left.mnSdbType != right.mnSdbType) -- cgit v1.2.3