[Libreoffice-commits] .: 5 commits - sc/inc sc/qa sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Thu Jan 12 18:56:54 PST 2012


 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 44cd9971649b9611c59bb3e423133b9a4d82a2fa
Author: Kohei Yoshida <kohei.yoshida at 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 88abad3..ad412ef 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 2ab84dcaa32cb117b0ba30f3dcbdf6911dc4f0f4
Author: Kohei Yoshida <kohei.yoshida at 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 a10cee9..88abad3 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 2232b0c303ca4776a9df762d802b8f74b9d78c93
Author: Kohei Yoshida <kohei.yoshida at 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 b9e3013..a10cee9 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 c9ff82a..6da91c2 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 2b21a16..086b4ff 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 33024ee9d07f4448b2ecdd6f27e0344072b2c0ea
Author: Kohei Yoshida <kohei.yoshida at 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 046c159..60db27b 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 0f2a0fc99deb7b9233dbc39e74e0bfdaf9d6efeb
Author: Kohei Yoshida <kohei.yoshida at 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 8f2828b..5917db0 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -822,7 +822,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
         {
@@ -903,6 +904,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())


More information about the Libreoffice-commits mailing list