sc/inc/dpcachetable.hxx | 1 sc/inc/dpobject.hxx | 25 ++ sc/inc/dpsdbtab.hxx | 5 sc/inc/dptablecache.hxx | 10 + sc/qa/unit/ucalc.cxx | 43 +++- sc/source/core/data/documen2.cxx | 6 sc/source/core/data/dpcachetable.cxx | 10 - sc/source/core/data/dpobject.cxx | 311 ++++++++++++++++++++++++++++------- sc/source/core/data/dpsdbtab.cxx | 15 - sc/source/core/data/dpshttab.cxx | 7 sc/source/core/data/dptablecache.cxx | 18 ++ sc/source/ui/unoobj/dapiuno.cxx | 10 - sc/source/ui/view/dbfunc3.cxx | 11 + 13 files changed, 381 insertions(+), 91 deletions(-)
New commits: commit 6d7fcd016e661c07b664b6c9b454c42c02537f10 Author: Kohei Yoshida <kohei.yosh...@suse.com> Date: Thu Jan 12 21:49:24 2012 -0500 Test the new logic of our pivot data cache life cycle. diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 685f7d2..47c1999 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -271,6 +271,7 @@ public: SheetCaches(ScDocument* pDoc); bool hasCache(const ScRange& rRange) const; const ScDPCache* getCache(const ScRange& rRange); + size_t size() const; void updateReference( UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz); @@ -294,6 +295,7 @@ public: NameCaches(ScDocument* pDoc); bool hasCache(const rtl::OUString& rName) const; const ScDPCache* getCache(const ::rtl::OUString& rName, const ScRange& rRange); + size_t size() const; private: void updateCache(const rtl::OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs); void removeCache(const ::rtl::OUString& rName); @@ -329,6 +331,8 @@ public: public: DBCaches(ScDocument* pDoc); const ScDPCache* getCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + size_t size() const; + private: com::sun::star::uno::Reference<com::sun::star::sdbc::XRowSet> createRowSet( sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index d2ebcc2..9b86275 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -1323,6 +1323,7 @@ void Test::testDataPilot() bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output"); CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); } + CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1); // Update the cell values. double aData2[] = { 100, 200, 300, 400, 500, 600 }; @@ -1361,15 +1362,22 @@ void Test::testDataPilot() CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); } + CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1); + // Free the first datapilot object after the 2nd one gets reloaded, to // prevent the data cache from being deleted before the reload. pDPs->FreeTable(pDPObj); + CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1); + // This time clear the cache to refresh the data from the source range. CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData()); std::set<ScDPObject*> aRefs; sal_uLong nErrId = pDPs->ReloadCache(pDPObj2, aRefs); - CPPUNIT_ASSERT_MESSAGE("Cache removal failed.", nErrId == 0); + CPPUNIT_ASSERT_MESSAGE("Cache reload failed.", nErrId == 0); + CPPUNIT_ASSERT_MESSAGE("Reloading a cache shouldn't remove any cache.", + pDPs->GetSheetCaches().size() == 1); + pDPObj2->ClearSource(); pDPObj2->Output(aOutRange.aStart); @@ -1395,6 +1403,8 @@ void Test::testDataPilot() // Swap the two sheets. m_pDoc->MoveTab(1, 0); + CPPUNIT_ASSERT_MESSAGE("Swapping the sheets shouldn't remove the cache.", + pDPs->GetSheetCaches().size() == 1); CPPUNIT_ASSERT_MESSAGE("Cache should have moved.", !pDPs->GetSheetCaches().hasCache(aSrcRange)); aSrcRange.aStart.SetTab(1); aSrcRange.aEnd.SetTab(1); @@ -1404,6 +1414,9 @@ void Test::testDataPilot() CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.", pDPs->GetCount() == 0); + CPPUNIT_ASSERT_MESSAGE("There shouldn't be any more data cache.", + pDPs->GetSheetCaches().size() == 0); + m_pDoc->DeleteTab(1); m_pDoc->DeleteTab(0); } @@ -1673,6 +1686,9 @@ void Test::testDataPilotNamedSource() CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); } + CPPUNIT_ASSERT_MESSAGE("There should be one named range data cache.", + pDPs->GetNameCaches().size() == 1 && pDPs->GetSheetCaches().size() == 0); + // Move the table with pivot table to the left of the source data sheet. m_pDoc->MoveTab(1, 0); rtl::OUString aTabName; @@ -1680,14 +1696,21 @@ void Test::testDataPilotNamedSource() CPPUNIT_ASSERT_MESSAGE("Wrong sheet name.", aTabName.equalsAscii("Table")); CPPUNIT_ASSERT_MESSAGE("Pivot table output is on the wrong sheet!", pDPObj->GetOutRange().aStart.Tab() == 0); + + CPPUNIT_ASSERT_MESSAGE("Moving the pivot table to another sheet shouldn't have changed the cache state.", + pDPs->GetNameCaches().size() == 1 && pDPs->GetSheetCaches().size() == 0); + const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc(); CPPUNIT_ASSERT_MESSAGE("Sheet source description doesn't exist.", pDesc); CPPUNIT_ASSERT_MESSAGE("Named source range has been altered unexpectedly!", pDesc->GetRangeName().equals(aRangeName)); CPPUNIT_ASSERT_MESSAGE("Cache should exist.", pDPs->GetNameCaches().hasCache(aRangeName)); + pDPs->FreeTable(pDPObj); CPPUNIT_ASSERT_MESSAGE("There should be no more tables.", pDPs->GetCount() == 0); + CPPUNIT_ASSERT_MESSAGE("There shouldn't be any more cache stored.", + pDPs->GetNameCaches().size() == 0); pNames->clear(); m_pDoc->DeleteTab(1); diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index bc26c48..3113f1b 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -2499,8 +2499,10 @@ const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange) size_t nIndex = std::distance(maRanges.begin(), it); CachesType::iterator itCache = maCaches.find(nIndex); if (itCache == maCaches.end()) - // cache pool and index pool out-of-sync !!! + { + OSL_FAIL("Cache pool and index pool out-of-sync !!!"); return NULL; + } return itCache->second; } @@ -2532,6 +2534,11 @@ const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange) return p; } +size_t ScDPCollection::SheetCaches::size() const +{ + return maCaches.size(); +} + void ScDPCollection::SheetCaches::updateReference( UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz) { @@ -2579,7 +2586,7 @@ void ScDPCollection::SheetCaches::updateCache(const ScRange& rRange, std::set<Sc CachesType::iterator itCache = maCaches.find(nIndex); if (itCache == maCaches.end()) { - // Cache pool and index pool out-of-sync !!! + OSL_FAIL("Cache pool and index pool out-of-sync !!!"); rRefs.clear(); return; } @@ -2600,8 +2607,10 @@ void ScDPCollection::SheetCaches::removeCache(const ScRange& rRange) size_t nIndex = std::distance(maRanges.begin(), it); CachesType::iterator itCache = maCaches.find(nIndex); if (itCache == maCaches.end()) - // Cache pool and index pool out-of-sync !!! + { + OSL_FAIL("Cache pool and index pool out-of-sync !!!"); return; + } it->SetInvalid(); // Make this slot available for future caches. maCaches.erase(itCache); @@ -2646,6 +2655,11 @@ const ScDPCache* ScDPCollection::NameCaches::getCache(const OUString& rName, con return p; } +size_t ScDPCollection::NameCaches::size() const +{ + return maCaches.size(); +} + void ScDPCollection::NameCaches::updateCache(const OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs) { CachesType::iterator itr = maCaches.find(rName); @@ -2715,6 +2729,11 @@ const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OU return p; } +size_t ScDPCollection::DBCaches::size() const +{ + return maCaches.size(); +} + uno::Reference<sdbc::XRowSet> ScDPCollection::DBCaches::createRowSet( sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand) { commit 65d58adcec970306ac641f49f56404b6be0e1462 Author: Kohei Yoshida <kohei.yosh...@suse.com> Date: Thu Jan 12 21:19:05 2012 -0500 fdo#43077: Finally, remove data cache when nobody references it. Also, removed unnecessary reloading of the whole table data when reference is updated. diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 5010e69..685f7d2 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -253,6 +253,7 @@ public: class ScDPCollection { + friend class ScDPCache; public: /** @@ -277,6 +278,7 @@ public: private: void updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs); void removeCache(const ScRange& rRange); + bool remove(const ScDPCache* p); }; /** @@ -295,6 +297,7 @@ public: private: void updateCache(const rtl::OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs); void removeCache(const ::rtl::OUString& rName); + bool remove(const ScDPCache* p); }; /** @@ -333,6 +336,7 @@ public: void updateCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand, std::set<ScDPObject*>& rRefs); void removeCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + bool remove(const ScDPCache* p); }; ScDPCollection(ScDocument* pDocument); @@ -375,6 +379,10 @@ public: DBCaches& GetDBCaches(); private: + /** Only to be called from ScDPCache::RemoveReference(). */ + void RemoveCache(const ScDPCache* pCache); + +private: typedef ::boost::ptr_vector<ScDPObject> TablesType; ScDocument* pDoc; diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 0a08c8f..d2ebcc2 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -1125,6 +1125,7 @@ ScRange insertDPSourceData(ScDocument* pDoc, DPFieldDef aFields[], size_t nField template<size_t _Size> bool checkDPTableOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* aOutputCheck[][_Size], const char* pCaption) { + bool bResult = true; const ScAddress& s = aOutRange.aStart; const ScAddress& e = aOutRange.aEnd; SheetPrinter printer(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1); @@ -1145,18 +1146,18 @@ bool checkDPTableOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* if (!bEqual) { cerr << "Expected: " << aCheckVal << " Actual: " << aVal << endl; - return false; + bResult = false; } } else if (!aVal.isEmpty()) { cerr << "Empty cell expected" << endl; - return false; + bResult = false; } } } printer.print(pCaption); - return true; + return bResult; } ScDPObject* createDPFromSourceDesc( @@ -1334,10 +1335,9 @@ void Test::testDataPilot() printRange(m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), "Data sheet content (modified)"); // Now, create a copy of the datapilot object for the updated table, but - // don't clear the cache which should force the copy to use the old data + // don't reload the cache which should force the copy to use the old data // from the cache. ScDPObject* pDPObj2 = new ScDPObject(*pDPObj); - pDPs->FreeTable(pDPObj); pDPs->InsertNewTable(pDPObj2); aOutRange = pDPObj2->GetOutRange(); @@ -1361,6 +1361,10 @@ void Test::testDataPilot() CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); } + // Free the first datapilot object after the 2nd one gets reloaded, to + // prevent the data cache from being deleted before the reload. + pDPs->FreeTable(pDPObj); + // This time clear the cache to refresh the data from the source range. CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData()); std::set<ScDPObject*> aRefs; @@ -1396,7 +1400,6 @@ void Test::testDataPilot() aSrcRange.aEnd.SetTab(1); CPPUNIT_ASSERT_MESSAGE("Cache should be here.", pDPs->GetSheetCaches().hasCache(aSrcRange)); - pDPs->FreeTable(pDPObj2); CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.", pDPs->GetCount() == 0); diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 3332ec9..bc26c48 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -774,11 +774,8 @@ void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); if ( eRes != UR_NOTHING ) { - ScSheetSourceDesc aNewDesc(pDoc); - aNewDesc.SetSourceRange(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2)); - - SCsCOL nDiffX = nCol1 - (SCsCOL) pSheetDesc->GetSourceRange().aStart.Col(); - SCsROW nDiffY = nRow1 - (SCsROW) pSheetDesc->GetSourceRange().aStart.Row(); + SCsCOL nDiffX = nCol1 - pSheetDesc->GetSourceRange().aStart.Col(); + SCsROW nDiffY = nRow1 - pSheetDesc->GetSourceRange().aStart.Row(); ScQueryParam aParam = pSheetDesc->GetQueryParam(); aParam.nCol1 = sal::static_int_cast<SCCOL>( aParam.nCol1 + nDiffX ); @@ -790,8 +787,8 @@ void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode, if (aParam.GetEntry(i).bDoQuery) aParam.GetEntry(i).nField += nDiffX; - aNewDesc.SetQueryParam(aParam); - SetSheetDesc( aNewDesc ); // allocates new pSheetDesc + pSheetDesc->SetQueryParam(aParam); + pSheetDesc->SetSourceRange(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2)); } } } @@ -2610,6 +2607,22 @@ void ScDPCollection::SheetCaches::removeCache(const ScRange& rRange) maCaches.erase(itCache); } +bool ScDPCollection::SheetCaches::remove(const ScDPCache* p) +{ + CachesType::iterator it = maCaches.begin(), itEnd = maCaches.end(); + for (; it != itEnd; ++it) + { + if (it->second == p) + { + size_t idx = it->first; + maCaches.erase(it); + maRanges[idx].SetInvalid(); + return true; + } + } + return false; +} + ScDPCollection::NameCaches::NameCaches(ScDocument* pDoc) : mpDoc(pDoc) {} bool ScDPCollection::NameCaches::hasCache(const OUString& rName) const @@ -2655,6 +2668,20 @@ void ScDPCollection::NameCaches::removeCache(const OUString& rName) maCaches.erase(itr); } +bool ScDPCollection::NameCaches::remove(const ScDPCache* p) +{ + CachesType::iterator it = maCaches.begin(), itEnd = maCaches.end(); + for (; it != itEnd; ++it) + { + if (it->second == p) + { + maCaches.erase(it); + return true; + } + } + return false; +} + ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) : mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {} @@ -2794,6 +2821,20 @@ void ScDPCollection::DBCaches::removeCache(sal_Int32 nSdbType, const OUString& r maCaches.erase(itr); } +bool ScDPCollection::DBCaches::remove(const ScDPCache* p) +{ + CachesType::iterator it = maCaches.begin(), itEnd = maCaches.end(); + for (; it != itEnd; ++it) + { + if (it->second == p) + { + maCaches.erase(it); + return true; + } + } + return false; +} + ScDPCollection::ScDPCollection(ScDocument* pDocument) : pDoc( pDocument ), maSheetCaches(pDocument), @@ -3080,6 +3121,21 @@ ScDPCollection::DBCaches& ScDPCollection::GetDBCaches() return maDBCaches; } +void ScDPCollection::RemoveCache(const ScDPCache* pCache) +{ + if (maSheetCaches.remove(pCache)) + // sheet cache removed. + return; + + if (maNameCaches.remove(pCache)) + // named range cache removed. + return; + + if (maDBCaches.remove(pCache)) + // database cache removed. + return; +} + bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right) { if (left.mnSdbType != right.mnSdbType) diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index 4ce5195..57f6ce1 100644 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -37,6 +37,7 @@ #include "queryparam.hxx" #include "dpglobal.hxx" #include "dptabdat.hxx" +#include "dpobject.hxx" #include "docoptio.hxx" #include <unotools/textsearch.hxx> @@ -993,6 +994,8 @@ void ScDPCache::AddReference(ScDPObject* pObj) const void ScDPCache::RemoveReference(ScDPObject* pObj) const { maRefObjects.erase(pObj); + if (maRefObjects.empty()) + mpDoc->GetDPCollection()->RemoveCache(this); } const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const commit e6392d2a17c0bee792cfd0060d177e5c6a71f346 Author: Kohei Yoshida <kohei.yosh...@suse.com> Date: Thu Jan 12 15:22:32 2012 -0500 fdo#43077: Now, refreshing a table should refresh all linked tables. For efficiency reasons. Otherwise, refreshing n tables individually would require reloading the same data cache n times. diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 769e0ac..5010e69 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -37,6 +37,8 @@ #include "pivot.hxx" #include <com/sun/star/sheet/XDimensionsSupplier.hpp> +#include <set> + #include <boost/ptr_container/ptr_list.hpp> #include <boost/ptr_container/ptr_vector.hpp> #include <boost/ptr_container/ptr_map.hpp> @@ -273,6 +275,7 @@ public: UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz); private: + void updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs); void removeCache(const ScRange& rRange); }; @@ -290,6 +293,7 @@ public: bool hasCache(const rtl::OUString& rName) const; const ScDPCache* getCache(const ::rtl::OUString& rName, const ScRange& rRange); private: + void updateCache(const rtl::OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs); void removeCache(const ::rtl::OUString& rName); }; @@ -323,6 +327,11 @@ public: DBCaches(ScDocument* pDoc); const ScDPCache* getCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); private: + com::sun::star::uno::Reference<com::sun::star::sdbc::XRowSet> createRowSet( + sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + + void updateCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand, + std::set<ScDPObject*>& rRefs); void removeCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); }; @@ -330,7 +339,7 @@ public: ScDPCollection(const ScDPCollection& r); ~ScDPCollection(); - sal_uLong ClearCache(ScDPObject* pDPObj); + sal_uLong ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs); SC_DLLPUBLIC size_t GetCount() const; SC_DLLPUBLIC ScDPObject* operator[](size_t nIndex); diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx index a67103d..882f422 100644 --- a/sc/inc/dptablecache.hxx +++ b/sc/inc/dptablecache.hxx @@ -50,10 +50,10 @@ class SC_DLLPUBLIC ScDPCache { public: typedef ::boost::ptr_vector<ScDPItemData> DataListType; + typedef std::set<ScDPObject*> ObjectSetType; private: typedef ::boost::ptr_vector<DataListType> DataGridType; typedef ::boost::ptr_vector< ::std::vector<SCROW> > RowGridType; - typedef std::set<ScDPObject*> ObjectSetType; ScDocument* mpDoc; long mnColumnCount; @@ -96,6 +96,7 @@ private: public: void AddReference(ScDPObject* pObj) const; void RemoveReference(ScDPObject* pObj) const; + const ObjectSetType& GetAllReferences() const; SCROW GetIdByItemData( long nDim, const String& sItemData ) const; SCROW GetIdByItemData( long nDim, const ScDPItemData& rData ) const; diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 419ce63..0a08c8f 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -1363,7 +1363,8 @@ void Test::testDataPilot() // This time clear the cache to refresh the data from the source range. CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData()); - sal_uLong nErrId = pDPs->ClearCache(pDPObj2); + std::set<ScDPObject*> aRefs; + sal_uLong nErrId = pDPs->ReloadCache(pDPObj2, aRefs); CPPUNIT_ASSERT_MESSAGE("Cache removal failed.", nErrId == 0); pDPObj2->ClearSource(); pDPObj2->Output(aOutRange.aStart); diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 3999d55..3332ec9 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -2568,6 +2568,31 @@ void ScDPCollection::SheetCaches::updateReference( } } +void ScDPCollection::SheetCaches::updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs) +{ + RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange); + if (it == maRanges.end()) + { + // Not cached. Nothing to do. + rRefs.clear(); + return; + } + + size_t nIndex = std::distance(maRanges.begin(), it); + CachesType::iterator itCache = maCaches.find(nIndex); + if (itCache == maCaches.end()) + { + // Cache pool and index pool out-of-sync !!! + rRefs.clear(); + return; + } + + ScDPCache& rCache = *itCache->second; + rCache.InitFromDoc(mpDoc, rRange); + std::set<ScDPObject*> aRefs(rCache.GetAllReferences()); + rRefs.swap(aRefs); +} + void ScDPCollection::SheetCaches::removeCache(const ScRange& rRange) { RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange); @@ -2608,6 +2633,21 @@ const ScDPCache* ScDPCollection::NameCaches::getCache(const OUString& rName, con return p; } +void ScDPCollection::NameCaches::updateCache(const OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs) +{ + CachesType::iterator itr = maCaches.find(rName); + if (itr == maCaches.end()) + { + rRefs.clear(); + return; + } + + ScDPCache& rCache = *itr->second; + rCache.InitFromDoc(mpDoc, rRange); + std::set<ScDPObject*> aRefs(rCache.GetAllReferences()); + rRefs.swap(aRefs); +} + void ScDPCollection::NameCaches::removeCache(const OUString& rName) { CachesType::iterator itr = maCaches.find(rName); @@ -2633,68 +2673,117 @@ const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OU // already cached. return itr->second; - uno::Reference<sdbc::XRowSet> xRowSet ; + uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand); + if (!xRowSet.is()) + return NULL; + + SAL_WNODEPRECATED_DECLARATIONS_PUSH + ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc)); + SAL_WNODEPRECATED_DECLARATIONS_POP + SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge); + pCache->InitFromDataBase(xRowSet, *aFormat.GetNullDate()); + ::comphelper::disposeComponent(xRowSet); + const ScDPCache* p = pCache.get(); + maCaches.insert(aType, pCache); + return p; +} + +uno::Reference<sdbc::XRowSet> ScDPCollection::DBCaches::createRowSet( + sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand) +{ + uno::Reference<sdbc::XRowSet> xRowSet; try { xRowSet = uno::Reference<sdbc::XRowSet>( comphelper::getProcessServiceFactory()->createInstance( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_ROWSET )) ), - uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY ); + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_SERVICE_ROWSET))), + UNO_QUERY); + + uno::Reference<beans::XPropertySet> xRowProp(xRowSet, UNO_QUERY); OSL_ENSURE( xRowProp.is(), "can't get RowSet" ); - if ( xRowProp.is() ) + if (!xRowProp.is()) { - // - // set source parameters - // - uno::Any aAny; - aAny <<= rDBName; - xRowProp->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny ); - - aAny <<= rCommand; - xRowProp->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny ); - - aAny <<= nSdbType; - xRowProp->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny ); - - uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY ); - if ( xExecute.is() ) - { - uno::Reference<task::XInteractionHandler> xHandler( - comphelper::getProcessServiceFactory()->createInstance( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ), - uno::UNO_QUERY); - xExecute->executeWithCompletion( xHandler ); - } - else - xRowSet->execute(); + xRowSet.set(NULL); + return xRowSet; + } + + // + // set source parameters + // + uno::Any aAny; + aAny <<= rDBName; + xRowProp->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny ); + + aAny <<= rCommand; + xRowProp->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny ); + + aAny <<= nSdbType; + xRowProp->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny ); + + uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY ); + if ( xExecute.is() ) + { + uno::Reference<task::XInteractionHandler> xHandler( + comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ), + uno::UNO_QUERY); + xExecute->executeWithCompletion( xHandler ); } + else + xRowSet->execute(); + + return xRowSet; } catch ( const sdbc::SQLException& rError ) { //! store error message InfoBox aInfoBox( 0, String(rError.Message) ); aInfoBox.Execute(); - return NULL; } catch ( uno::Exception& ) { OSL_FAIL("Unexpected exception in database"); - return NULL; } - SAL_WNODEPRECATED_DECLARATIONS_PUSH - ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc)); - SAL_WNODEPRECATED_DECLARATIONS_POP + xRowSet.set(NULL); + return xRowSet; +} + +void ScDPCollection::DBCaches::updateCache( + sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand, std::set<ScDPObject*>& rRefs) +{ + DBType aType(nSdbType, rDBName, rCommand); + CachesType::iterator it = maCaches.find(aType); + if (it == maCaches.end()) + { + // not cached. + rRefs.clear(); + return; + } + + ScDPCache& rCache = *it->second; + + uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand); + if (!xRowSet.is()) + { + rRefs.clear(); + return; + } + SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge); - pCache->InitFromDataBase(xRowSet, *aFormat.GetNullDate()); - ::comphelper::disposeComponent(xRowSet); - const ScDPCache* p = pCache.get(); - maCaches.insert(aType, pCache); - return p; + if (!rCache.InitFromDataBase(xRowSet, *aFormat.GetNullDate())) + { + // initialization failed. + rRefs.clear(); + return; + } + + comphelper::disposeComponent(xRowSet); + std::set<ScDPObject*> aRefs(rCache.GetAllReferences()); + aRefs.swap(rRefs); } void ScDPCollection::DBCaches::removeCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) @@ -2745,7 +2834,7 @@ public: } -sal_uLong ScDPCollection::ClearCache(ScDPObject* pDPObj) +sal_uLong ScDPCollection::ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs) { if (pDPObj->IsSheetData()) { @@ -2762,13 +2851,13 @@ sal_uLong ScDPCollection::ClearCache(ScDPObject* pDPObj) { // cache by named range ScDPCollection::NameCaches& rCaches = GetNameCaches(); - rCaches.removeCache(pDesc->GetRangeName()); + rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs); } else { // cache by cell range ScDPCollection::SheetCaches& rCaches = GetSheetCaches(); - rCaches.removeCache(pDesc->GetSourceRange()); + rCaches.updateCache(pDesc->GetSourceRange(), rRefs); } } else if (pDPObj->IsImportData()) @@ -2779,7 +2868,8 @@ sal_uLong ScDPCollection::ClearCache(ScDPObject* pDPObj) return STR_ERR_DATAPILOTSOURCE; ScDPCollection::DBCaches& rCaches = GetDBCaches(); - rCaches.removeCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject); + rCaches.updateCache( + pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs); } return 0; } diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index 683a875..4ce5195 100644 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -995,6 +995,11 @@ void ScDPCache::RemoveReference(ScDPObject* pObj) const maRefObjects.erase(pObj); } +const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const +{ + return maRefObjects; +} + SCROW ScDPCache::GetIdByItemData(long nDim, const String& sItemData ) const { if ( nDim < mnColumnCount && nDim >=0 ) diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx index 5a5bed3..e67f1ab 100644 --- a/sc/source/ui/unoobj/dapiuno.cxx +++ b/sc/source/ui/unoobj/dapiuno.cxx @@ -1276,8 +1276,14 @@ void SAL_CALL ScDataPilotTableObj::refresh() throw(RuntimeException) if (pDPObj) { ScDBDocFunc aFunc(*GetDocShell()); - GetDocShell()->GetDocument()->GetDPCollection()->ClearCache(pDPObj); - aFunc.DataPilotUpdate( pDPObj, pDPObj, true, true ); + std::set<ScDPObject*> aRefs; + GetDocShell()->GetDocument()->GetDPCollection()->ReloadCache(pDPObj, aRefs); + std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end(); + for (; it != itEnd; ++it) + { + ScDPObject* pObj = *it; + aFunc.DataPilotUpdate(pObj, pObj, true, true); + } } } diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 0d4de94..b717742 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -707,7 +707,8 @@ void ScDBFunc::RecalcPivotTable() { // Remove existing data cache for the data that this datapilot uses, // to force re-build data cache. - sal_uLong nErrId = pDPs->ClearCache(pDPObj); + std::set<ScDPObject*> aRefs; + sal_uLong nErrId = pDPs->ReloadCache(pDPObj, aRefs); if (nErrId) { ErrorMessage(nErrId); @@ -715,7 +716,13 @@ void ScDBFunc::RecalcPivotTable() } ScDBDocFunc aFunc( *pDocSh ); - aFunc.DataPilotUpdate( pDPObj, pDPObj, true, false ); + std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end(); + for (; it != itEnd; ++it) + { + ScDPObject* pObj = *it; + aFunc.DataPilotUpdate(pObj, pObj, true, false); + } + CursorPosChanged(); // shells may be switched } else commit 29cfe42f6473fa2e7351f98d5f3480ffbd9904fe Author: Kohei Yoshida <kohei.yosh...@suse.com> Date: Thu Jan 12 14:09:32 2012 -0500 fdo#43077: Have cache instance keep track of who is referencing it. With this change, ScDPCacheTable should never clear pointer to the data cache instance; it should keep the same data cache instance that it is instantiated with. diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx index 62efc84..695586f 100644 --- a/sc/inc/dpcachetable.hxx +++ b/sc/inc/dpcachetable.hxx @@ -175,7 +175,6 @@ public: SCROW getOrder(long nDim, SCROW nIndex) const; void clear(); bool empty() const; - void setCache(const ScDPCache* p); bool hasCache() const; private: diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx index 87c3ccd..8be0cb9 100644 --- a/sc/inc/dpsdbtab.hxx +++ b/sc/inc/dpsdbtab.hxx @@ -38,6 +38,7 @@ class ScDPCacheTable; class ScDocument; +class ScDPCache; struct ScImportSourceDesc { @@ -69,8 +70,8 @@ private: const ScImportSourceDesc& mrImport; ScDPCacheTable aCacheTable; public: - ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport); - virtual ~ScDatabaseDPData(); + ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport, const ScDPCache* pCache); + virtual ~ScDatabaseDPData(); virtual long GetColumnCount(); virtual String getDimensionName(long nColumn); diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx index 950cc54..a67103d 100644 --- a/sc/inc/dptablecache.hxx +++ b/sc/inc/dptablecache.hxx @@ -53,11 +53,17 @@ public: private: typedef ::boost::ptr_vector<DataListType> DataGridType; typedef ::boost::ptr_vector< ::std::vector<SCROW> > RowGridType; + typedef std::set<ScDPObject*> ObjectSetType; ScDocument* mpDoc; long mnColumnCount; /** + * All pivot table objects that references this cache. + */ + mutable ObjectSetType maRefObjects; + + /** * This container stores only the unique instances of item data in each * column. Duplicates are not allowed. */ @@ -88,6 +94,9 @@ private: mutable ScDPItemDataPool maAdditionalData; public: + void AddReference(ScDPObject* pObj) const; + void RemoveReference(ScDPObject* pObj) const; + SCROW GetIdByItemData( long nDim, const String& sItemData ) const; SCROW GetIdByItemData( long nDim, const ScDPItemData& rData ) const; diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx index adc3cff..ae9ca76 100644 --- a/sc/source/core/data/dpcachetable.cxx +++ b/sc/source/core/data/dpcachetable.cxx @@ -414,24 +414,18 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const { - return mpCache ? getCache()->GetOrder(nDim, nIndex) : 0; + return mpCache->GetOrder(nDim, nIndex); } void ScDPCacheTable::clear() { maFieldEntries.clear(); maRowFlags.clear(); - mpCache = NULL; } bool ScDPCacheTable::empty() const { - return mpCache == NULL || maFieldEntries.empty(); -} - -void ScDPCacheTable::setCache(const ScDPCache* p) -{ - mpCache = p; + return maFieldEntries.empty(); } bool ScDPCacheTable::hasCache() const diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index a6f48db..3999d55 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -460,7 +460,12 @@ ScDPTableData* ScDPObject::GetTableData() if ( pImpDesc ) { // database data - pData.reset(new ScDatabaseDPData(pDoc, *pImpDesc)); + const ScDPCache* pCache = pImpDesc->CreateCache(); + if (pCache) + { + pCache->AddReference(this); + pData.reset(new ScDatabaseDPData(pDoc, *pImpDesc, pCache)); + } } else { @@ -478,7 +483,10 @@ ScDPTableData* ScDPObject::GetTableData() DisableGetPivotData aSwitch(*this, mbEnableGetPivotData); const ScDPCache* pCache = pSheetDesc->CreateCache(); if (pCache) + { + pCache->AddReference(this); pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, pCache)); + } } } @@ -572,6 +580,8 @@ void ScDPObject::ClearSource() } } xSource = NULL; + if (mpTableData) + mpTableData->GetCacheTable().getCache()->RemoveReference(this); mpTableData.reset(); } diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx index 0f410e1..1cfa2f8 100644 --- a/sc/source/core/data/dpsdbtab.cxx +++ b/sc/source/core/data/dpsdbtab.cxx @@ -77,10 +77,11 @@ const ScDPCache* ScImportSourceDesc::CreateCache() const return rCaches.getCache(nSdbType, aDBName, aObject); } -ScDatabaseDPData::ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport) : +ScDatabaseDPData::ScDatabaseDPData( + ScDocument* pDoc, const ScImportSourceDesc& rImport, const ScDPCache* pCache) : ScDPTableData(pDoc), mrImport(rImport), - aCacheTable(rImport.CreateCache()) + aCacheTable(pCache) { } @@ -139,12 +140,10 @@ void ScDatabaseDPData::CreateCacheTable() if (!aCacheTable.hasCache()) { - const ScDPCache* pCache = mrImport.CreateCache(); - if (!pCache) - // Cache creation failed. Perhaps invalid database connection. - return; - - aCacheTable.setCache(pCache); + fprintf(stdout, "ScDatabaseDPData::CreateCacheTable: NOT GOOD!\n"); + // This better not happen!! Cache table should be created with a live + // data cache instance at all times. + return; } aCacheTable.fillTable(); diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx index a04bb5a..14a6f7b 100644 --- a/sc/source/core/data/dpshttab.cxx +++ b/sc/source/core/data/dpshttab.cxx @@ -191,7 +191,12 @@ void ScSheetDPData::CreateCacheTable() return; if (!aCacheTable.hasCache()) - aCacheTable.setCache(mrDesc.CreateCache()); + { + fprintf(stdout, "ScSheetDPData::CreateCacheTable: NOT GOOD!!!\n"); + // This better not happen!! The cache table should be created with a + // live data cache at all times. + return; + } aCacheTable.fillTable(aQuery, bIgnoreEmptyRows, bRepeatIfEmpty); } diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index d0ca15c..683a875 100644 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -985,6 +985,16 @@ SCCOL ScDPCache::GetDimensionIndex(String sName) const return -1; } +void ScDPCache::AddReference(ScDPObject* pObj) const +{ + maRefObjects.insert(pObj); +} + +void ScDPCache::RemoveReference(ScDPObject* pObj) const +{ + maRefObjects.erase(pObj); +} + SCROW ScDPCache::GetIdByItemData(long nDim, const String& sItemData ) const { if ( nDim < mnColumnCount && nDim >=0 ) commit 659d0ebda52cb7252590d9b11ebe0ef461df89a9 Author: Kohei Yoshida <kohei.yosh...@suse.com> Date: Thu Jan 12 00:01:23 2012 -0500 fdo#43077: Copy pivot tables when a sheet is copied. diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index dc20944..769e0ac 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -341,7 +341,7 @@ public: void DeleteOnTab( SCTAB nTab ); void UpdateReference( UpdateRefMode eUpdateRefMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); - + void CopyToTab( SCTAB nOld, SCTAB nNew ); bool RefsEqual( const ScDPCollection& r ) const; void WriteRefsTo( ScDPCollection& r ) const; diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index aa99070..40a10ba 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -823,7 +823,8 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM { if (nNewPos >= static_cast<SCTAB>(maTabs.size())) { - maTabs.push_back( new ScTable(this, static_cast<SCTAB>(maTabs.size()), aName) ); + nNewPos = static_cast<SCTAB>(maTabs.size()); + maTabs.push_back(new ScTable(this, nNewPos, aName)); } else { @@ -904,6 +905,9 @@ bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM if (pDrawLayer) DrawCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) ); + if (pDPCollection) + pDPCollection->CopyToTab(nOldPos, nNewPos); + maTabs[nNewPos]->SetPageStyle( maTabs[nOldPos]->GetPageStyle() ); maTabs[nNewPos]->SetPendingRowHeights( maTabs[nOldPos]->IsPendingRowHeights() ); diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 063c02a..a6f48db 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -2790,6 +2790,30 @@ void ScDPCollection::UpdateReference( UpdateRefMode eUpdateRefMode, maSheetCaches.updateReference(eUpdateRefMode, r, nDx, nDy, nDz); } +void ScDPCollection::CopyToTab( SCTAB nOld, SCTAB nNew ) +{ + TablesType aAdded; + TablesType::const_iterator it = maTables.begin(), itEnd = maTables.end(); + for (; it != itEnd; ++it) + { + const ScDPObject& rObj = *it; + ScRange aOutRange = rObj.GetOutRange(); + if (aOutRange.aStart.Tab() != nOld) + continue; + + ScAddress& s = aOutRange.aStart; + ScAddress& e = aOutRange.aEnd; + s.SetTab(nNew); + e.SetTab(nNew); + std::auto_ptr<ScDPObject> pNew(new ScDPObject(rObj)); + pNew->SetOutRange(aOutRange); + pDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE); + aAdded.push_back(pNew); + } + + maTables.transfer(maTables.end(), aAdded.begin(), aAdded.end(), aAdded); +} + bool ScDPCollection::RefsEqual( const ScDPCollection& r ) const { if (maTables.size() != r.maTables.size()) _______________________________________________ Libreoffice-commits mailing list Libreoffice-commits@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits