Blame SOURCES/0002-fdo-72645-Allow-GETPIVOTDATA-to-get-result-from-leaf.patch

f0633d
From 83eb0b64980b405bc94ed19f3bcb60860f86e7d4 Mon Sep 17 00:00:00 2001
f0633d
From: Kohei Yoshida <kohei.yoshida@collabora.com>
f0633d
Date: Mon, 6 Jan 2014 23:45:46 -0500
f0633d
Subject: [PATCH 2/9] fdo#72645: Allow GETPIVOTDATA to get result from leaf
f0633d
 node of result tree.
f0633d
f0633d
Change-Id: I0fc1fd069440ed6fee378fc2dfd2ed761afbdeab
f0633d
Reviewed-on: https://gerrit.libreoffice.org/7284
f0633d
Reviewed-by: Eike Rathke <erack@redhat.com>
f0633d
Tested-by: Eike Rathke <erack@redhat.com>
f0633d
---
f0633d
 sc/inc/dpresfilter.hxx              | 12 ++++++++++
f0633d
 sc/source/core/data/dpobject.cxx    |  4 ++--
f0633d
 sc/source/core/data/dpresfilter.cxx | 44 +++++++++++++++++++++++++++++++++++++
f0633d
 sc/source/core/data/dptabsrc.cxx    | 28 +++++++++++++++++------
f0633d
 4 files changed, 79 insertions(+), 9 deletions(-)
f0633d
f0633d
diff --git a/sc/inc/dpresfilter.hxx b/sc/inc/dpresfilter.hxx
f0633d
index be84b8c..bc7ffc1 100644
f0633d
--- a/sc/inc/dpresfilter.hxx
f0633d
+++ b/sc/inc/dpresfilter.hxx
f0633d
@@ -15,6 +15,7 @@
f0633d
 #include <map>
f0633d
 #include <vector>
f0633d
 #include <boost/noncopyable.hpp>
f0633d
+#include <boost/unordered_map.hpp>
f0633d
 
f0633d
 
f0633d
 namespace com { namespace sun { namespace star { namespace sheet {
f0633d
@@ -85,6 +86,15 @@ private:
f0633d
 #endif
f0633d
     };
f0633d
 
f0633d
+    typedef std::pair<OUString, OUString> NamePairType;
f0633d
+
f0633d
+    struct NamePairHash
f0633d
+    {
f0633d
+        size_t operator() (const NamePairType& rPair) const;
f0633d
+    };
f0633d
+    typedef boost::unordered_map<NamePairType, double, NamePairHash> LeafValuesType;
f0633d
+    LeafValuesType maLeafValues;
f0633d
+
f0633d
     OUString maPrimaryDimName;
f0633d
     MemberNode* mpRoot;
f0633d
 
f0633d
@@ -115,6 +125,8 @@ public:
f0633d
         const com::sun::star::uno::Sequence<
f0633d
             com::sun::star::sheet::DataPilotFieldFilter>& rFilters) const;
f0633d
 
f0633d
+    double getLeafResult(const com::sun::star::sheet::DataPilotFieldFilter& rFilter) const;
f0633d
+
f0633d
 #if DEBUG_PIVOT_TABLE
f0633d
     void dump() const;
f0633d
 #endif
f0633d
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
f0633d
index 653bc0c..3d9f5af 100644
f0633d
--- a/sc/source/core/data/dpobject.cxx
f0633d
+++ b/sc/source/core/data/dpobject.cxx
f0633d
@@ -1328,8 +1328,8 @@ public:
f0633d
     {
f0633d
         // Layout name takes precedence.
f0633d
         const OUString* pLayoutName = pDim->GetLayoutName();
f0633d
-        if (pLayoutName)
f0633d
-            return *pLayoutName == maName;
f0633d
+        if (pLayoutName && *pLayoutName == maName)
f0633d
+            return true;
f0633d
 
f0633d
         sheet::GeneralFunction eGenFunc = static_cast<sheet::GeneralFunction>(pDim->GetFunction());
f0633d
         ScSubTotalFunc eFunc = ScDPUtil::toSubTotalFunc(eGenFunc);
f0633d
diff --git a/sc/source/core/data/dpresfilter.cxx b/sc/source/core/data/dpresfilter.cxx
f0633d
index 968be6b..41b2d7e 100644
f0633d
--- a/sc/source/core/data/dpresfilter.cxx
f0633d
+++ b/sc/source/core/data/dpresfilter.cxx
f0633d
@@ -10,6 +10,8 @@
f0633d
 #include "dpresfilter.hxx"
f0633d
 #include "global.hxx"
f0633d
 
f0633d
+#include <rtl/math.hxx>
f0633d
+
f0633d
 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
f0633d
 
f0633d
 using namespace com::sun::star;
f0633d
@@ -21,6 +23,12 @@ ScDPResultFilter::ScDPResultFilter(const OUString& rDimName, bool bDataLayout) :
f0633d
 ScDPResultFilterContext::ScDPResultFilterContext() :
f0633d
     mnCol(0), mnRow(0) {}
f0633d
 
f0633d
+size_t ScDPResultTree::NamePairHash::operator() (const NamePairType& rPair) const
f0633d
+{
f0633d
+    OUStringHash aHash;
f0633d
+    return aHash(rPair.first) + aHash(rPair.second);
f0633d
+}
f0633d
+
f0633d
 ScDPResultTree::DimensionNode::DimensionNode(const MemberNode* pParent) :
f0633d
     mpParent(pParent) {}
f0633d
 
f0633d
@@ -89,6 +97,8 @@ void ScDPResultTree::add(
f0633d
 {
f0633d
     // TODO: I'll work on the col / row to value node mapping later.
f0633d
 
f0633d
+    const OUString* pDimName = NULL;
f0633d
+    const OUString* pMemName = NULL;
f0633d
     MemberNode* pMemNode = mpRoot;
f0633d
 
f0633d
     std::vector<ScDPResultFilter>::const_iterator itFilter = rFilters.begin(), itFilterEnd = rFilters.end();
f0633d
@@ -117,6 +127,8 @@ void ScDPResultTree::add(
f0633d
             itDim = r.first;
f0633d
         }
f0633d
 
f0633d
+        pDimName = &itDim->first;
f0633d
+
f0633d
         // Now, see if this dimension member exists.
f0633d
         DimensionNode* pDim = itDim->second;
f0633d
         MembersType& rMembers = pDim->maChildMembers;
f0633d
@@ -135,9 +147,26 @@ void ScDPResultTree::add(
f0633d
             itMem = r.first;
f0633d
         }
f0633d
 
f0633d
+        pMemName = &itMem->first;
f0633d
         pMemNode = itMem->second;
f0633d
     }
f0633d
 
f0633d
+    if (pDimName && pMemName)
f0633d
+    {
f0633d
+        NamePairType aNames(*pDimName, *pMemName);
f0633d
+        LeafValuesType::iterator it = maLeafValues.find(aNames);
f0633d
+        if (it == maLeafValues.end())
f0633d
+        {
f0633d
+            // This name pair doesn't exist.  Associate a new value for it.
f0633d
+            maLeafValues.insert(LeafValuesType::value_type(aNames, fVal));
f0633d
+        }
f0633d
+        else
f0633d
+        {
f0633d
+            // This name pair already exists. Set the value to NaN.
f0633d
+            rtl::math::setNan(&it->second);
f0633d
+        }
f0633d
+    }
f0633d
+
f0633d
     pMemNode->maValues.push_back(fVal);
f0633d
 }
f0633d
 
f0633d
@@ -145,6 +174,7 @@ void ScDPResultTree::swap(ScDPResultTree& rOther)
f0633d
 {
f0633d
     std::swap(maPrimaryDimName, rOther.maPrimaryDimName);
f0633d
     std::swap(mpRoot, rOther.mpRoot);
f0633d
+    maLeafValues.swap(rOther.maLeafValues);
f0633d
 }
f0633d
 
f0633d
 bool ScDPResultTree::empty() const
f0633d
@@ -184,6 +214,20 @@ const ScDPResultTree::ValuesType* ScDPResultTree::getResults(
f0633d
     return &pMember->maValues;
f0633d
 }
f0633d
 
f0633d
+double ScDPResultTree::getLeafResult(const com::sun::star::sheet::DataPilotFieldFilter& rFilter) const
f0633d
+{
f0633d
+    NamePairType aPair(rFilter.FieldName, rFilter.MatchValue);
f0633d
+    LeafValuesType::const_iterator it = maLeafValues.find(aPair);
f0633d
+    if (it != maLeafValues.end())
f0633d
+        // Found!
f0633d
+        return it->second;
f0633d
+
f0633d
+    // Not found.  Return an NaN.
f0633d
+    double fNan;
f0633d
+    rtl::math::setNan(&fNan);
f0633d
+    return fNan;
f0633d
+}
f0633d
+
f0633d
 #if DEBUG_PIVOT_TABLE
f0633d
 void ScDPResultTree::dump() const
f0633d
 {
f0633d
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
f0633d
index 96fe330..08df85d 100644
f0633d
--- a/sc/source/core/data/dptabsrc.cxx
f0633d
+++ b/sc/source/core/data/dptabsrc.cxx
f0633d
@@ -423,15 +423,29 @@ uno::Sequence<double> ScDPSource::getFilteredResults(
f0633d
 
f0633d
     // Get result values from the tree.
f0633d
     const ScDPResultTree::ValuesType* pVals = maResFilterSet.getResults(aFilters);
f0633d
-    if (!pVals)
f0633d
-        return uno::Sequence<double>();
f0633d
+    if (pVals)
f0633d
+    {
f0633d
+        size_t n = pVals->size();
f0633d
+        uno::Sequence<double> aRet(n);
f0633d
+        for (size_t i = 0; i < n; ++i)
f0633d
+            aRet[i] = (*pVals)[i];
f0633d
 
f0633d
-    size_t n = pVals->size();
f0633d
-    uno::Sequence<double> aRet(n);
f0633d
-    for (size_t i = 0; i < n; ++i)
f0633d
-        aRet[i] = (*pVals)[i];
f0633d
+        return aRet;
f0633d
+    }
f0633d
 
f0633d
-    return aRet;
f0633d
+    if (aFilters.getLength() == 1)
f0633d
+    {
f0633d
+        // Try to get result from the leaf nodes.
f0633d
+        double fVal = maResFilterSet.getLeafResult(aFilters[0]);
f0633d
+        if (!rtl::math::isNan(fVal))
f0633d
+        {
f0633d
+            uno::Sequence<double> aRet(1);
f0633d
+            aRet[0] = fVal;
f0633d
+            return aRet;
f0633d
+        }
f0633d
+    }
f0633d
+
f0633d
+    return uno::Sequence<double>();
f0633d
 }
f0633d
 
f0633d
 void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException)
f0633d
-- 
f0633d
1.8.4.2
f0633d