[Libreoffice-commits] .: sc/inc sc/Library_sc.mk sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Fri Mar 9 12:04:02 PST 2012


 sc/Library_sc.mk                     |    2 
 sc/inc/dpcache.hxx                   |  177 +++++
 sc/inc/dptabdat.hxx                  |    2 
 sc/inc/dptablecache.hxx              |  177 -----
 sc/source/core/data/documen3.cxx     |    2 
 sc/source/core/data/dpcache.cxx      | 1123 +++++++++++++++++++++++++++++++++++
 sc/source/core/data/dptablecache.cxx | 1123 -----------------------------------
 7 files changed, 1303 insertions(+), 1303 deletions(-)

New commits:
commit bded4b782a1dcd22ccd7187262d1aea3b0d50e6a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Fri Mar 9 15:03:43 2012 -0500

    dptablecache.* to dpcache.*

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index a991cd9..917d8f0 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -114,7 +114,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/data/dpsdbtab \
 	sc/source/core/data/dpshttab \
 	sc/source/core/data/dptabdat \
-	sc/source/core/data/dptablecache \
+	sc/source/core/data/dpcache \
 	sc/source/core/data/dptabres \
 	sc/source/core/data/dptabsrc \
 	sc/source/core/data/dputil \
diff --git a/sc/inc/dpcache.hxx b/sc/inc/dpcache.hxx
new file mode 100644
index 0000000..661c5cd
--- /dev/null
+++ b/sc/inc/dpcache.hxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright IBM Corporation 2009.
+ * Copyright 2009 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SC_DPTABLECACHE_HXX
+#define SC_DPTABLECACHE_HXX
+
+#include "global.hxx"
+#include "dpnumgroupinfo.hxx"
+
+#include <svl/zforlist.hxx>
+
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+#include <vector>
+
+struct ScQueryParam;
+class ScDPObject;
+class ScDPItemData;
+struct ScDPNumGroupInfo;
+
+/**
+ * This class represents the cached data part of the datapilot cache table
+ * implementation.
+ */
+class SC_DLLPUBLIC ScDPCache : boost::noncopyable
+{
+public:
+    typedef boost::ptr_vector<ScDPItemData> DataListType;
+    typedef std::set<ScDPObject*> ObjectSetType;
+    typedef std::vector<rtl::OUString> LabelsType;
+    typedef std::vector<SCROW> IndexArrayType;
+
+    struct GroupItems : boost::noncopyable
+    {
+        DataListType maItems;
+        ScDPNumGroupInfo maInfo;
+
+        GroupItems();
+        GroupItems(const ScDPNumGroupInfo& rInfo);
+    };
+
+    struct Field : boost::noncopyable
+    {
+        /**
+         * Optional items for grouped field.
+         */
+        boost::scoped_ptr<GroupItems> mpGroup;
+
+        DataListType maItems; /// Unique values in the field.
+
+        /**
+         * Original source data represented as indices to the unique value
+         * list.  The order of the data is as they appear in the original
+         * data source.
+         */
+        IndexArrayType maData;
+
+        /**
+         * Ascending order of field items.
+         */
+        IndexArrayType maGlobalOrder;
+
+        /**
+         * Ranks of each unique data represented by their index.  It's a
+         * reverse mapping of item index to global order index.
+         */
+        mutable IndexArrayType maIndexOrder;
+
+        std::vector<sal_uLong> maNumFormats;
+
+        Field();
+    };
+
+private:
+
+    ScDocument* mpDoc;
+    long mnColumnCount;
+
+    /**
+     * All pivot table objects that references this cache.
+     */
+    mutable ObjectSetType maRefObjects;
+
+    typedef boost::ptr_vector<Field> FieldsType;
+    typedef boost::ptr_vector<GroupItems> GroupFieldsType;
+
+    FieldsType maFields;
+    GroupFieldsType maGroupFields;
+
+    LabelsType maLabelNames;    // Stores dimension names.
+    std::vector<bool> maEmptyRows; // Keeps track of empty rows.
+
+    bool mbDisposing;
+
+public:
+    void AddReference(ScDPObject* pObj) const;
+    void RemoveReference(ScDPObject* pObj) const;
+    const ObjectSetType& GetAllReferences() const;
+
+    SCROW GetIdByItemData(long nDim, const ScDPItemData& rItem) const;
+    rtl::OUString GetFormattedString(long nDim, const ScDPItemData& rItem) const;
+    long AppendGroupField();
+    void ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo);
+    SCROW SetGroupItem(long nDim, const ScDPItemData& rData);
+    const DataListType* GetGroupDimMemberValues(long nDim) const;
+    void GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const;
+    void ClearGroupFields();
+
+    SCCOL GetDimensionIndex(const rtl::OUString& sName) const;
+    sal_uLong GetNumberFormat( long nDim ) const;
+    bool  IsDateDimension( long nDim ) const ;
+    SCROW GetDimMemberCount( SCCOL nDim ) const;
+    SCROW GetOrder( long nDim, SCROW nIndex ) const;
+
+    const DataListType& GetDimMemberValues( SCCOL nDim ) const;
+    bool InitFromDoc(ScDocument* pDoc, const ScRange& rRange);
+    bool InitFromDataBase(const  ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& xRowSet, const Date& rNullDate);
+
+    SCROW  GetRowCount() const;
+    SCROW  GetItemDataId( sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty ) const;
+    rtl::OUString GetDimensionName(LabelsType::size_type nDim) const;
+    bool IsRowEmpty( SCROW nRow ) const;
+    bool IsValid() const;
+    bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam) const;
+
+    ScDocument* GetDoc() const;
+    long GetColumnCount() const;
+    long GetGroupFieldCount() const;
+
+    const ScDPItemData* GetItemDataById( long nDim, SCROW nId ) const;
+
+    bool operator== ( const ScDPCache& r ) const;
+
+    ScDPCache(ScDocument* pDoc);
+    ~ScDPCache();
+
+private:
+    void Clear();
+    void AddLabel(const rtl::OUString& rLabel);
+    bool AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat);
+    const GroupItems* GetGroupItems(long nDim) const;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/dptabdat.hxx b/sc/inc/dptabdat.hxx
index de323e6..0fbad22 100644
--- a/sc/inc/dptabdat.hxx
+++ b/sc/inc/dptabdat.hxx
@@ -32,7 +32,7 @@
 #include "address.hxx"
 #include "dpoutput.hxx"
 #include "dpcachetable.hxx"
-#include "dptablecache.hxx"
+#include "dpcache.hxx"
 #include <tools/string.hxx>
 
 #include <vector>
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
deleted file mode 100644
index 661c5cd..0000000
--- a/sc/inc/dptablecache.hxx
+++ /dev/null
@@ -1,177 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright IBM Corporation 2009.
- * Copyright 2009 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org.  If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-#ifndef SC_DPTABLECACHE_HXX
-#define SC_DPTABLECACHE_HXX
-
-#include "global.hxx"
-#include "dpnumgroupinfo.hxx"
-
-#include <svl/zforlist.hxx>
-
-#include <com/sun/star/sdbc/DataType.hpp>
-#include <com/sun/star/sdbc/XRow.hpp>
-#include <com/sun/star/sdbc/XRowSet.hpp>
-
-#include <boost/noncopyable.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-
-#include <vector>
-
-struct ScQueryParam;
-class ScDPObject;
-class ScDPItemData;
-struct ScDPNumGroupInfo;
-
-/**
- * This class represents the cached data part of the datapilot cache table
- * implementation.
- */
-class SC_DLLPUBLIC ScDPCache : boost::noncopyable
-{
-public:
-    typedef boost::ptr_vector<ScDPItemData> DataListType;
-    typedef std::set<ScDPObject*> ObjectSetType;
-    typedef std::vector<rtl::OUString> LabelsType;
-    typedef std::vector<SCROW> IndexArrayType;
-
-    struct GroupItems : boost::noncopyable
-    {
-        DataListType maItems;
-        ScDPNumGroupInfo maInfo;
-
-        GroupItems();
-        GroupItems(const ScDPNumGroupInfo& rInfo);
-    };
-
-    struct Field : boost::noncopyable
-    {
-        /**
-         * Optional items for grouped field.
-         */
-        boost::scoped_ptr<GroupItems> mpGroup;
-
-        DataListType maItems; /// Unique values in the field.
-
-        /**
-         * Original source data represented as indices to the unique value
-         * list.  The order of the data is as they appear in the original
-         * data source.
-         */
-        IndexArrayType maData;
-
-        /**
-         * Ascending order of field items.
-         */
-        IndexArrayType maGlobalOrder;
-
-        /**
-         * Ranks of each unique data represented by their index.  It's a
-         * reverse mapping of item index to global order index.
-         */
-        mutable IndexArrayType maIndexOrder;
-
-        std::vector<sal_uLong> maNumFormats;
-
-        Field();
-    };
-
-private:
-
-    ScDocument* mpDoc;
-    long mnColumnCount;
-
-    /**
-     * All pivot table objects that references this cache.
-     */
-    mutable ObjectSetType maRefObjects;
-
-    typedef boost::ptr_vector<Field> FieldsType;
-    typedef boost::ptr_vector<GroupItems> GroupFieldsType;
-
-    FieldsType maFields;
-    GroupFieldsType maGroupFields;
-
-    LabelsType maLabelNames;    // Stores dimension names.
-    std::vector<bool> maEmptyRows; // Keeps track of empty rows.
-
-    bool mbDisposing;
-
-public:
-    void AddReference(ScDPObject* pObj) const;
-    void RemoveReference(ScDPObject* pObj) const;
-    const ObjectSetType& GetAllReferences() const;
-
-    SCROW GetIdByItemData(long nDim, const ScDPItemData& rItem) const;
-    rtl::OUString GetFormattedString(long nDim, const ScDPItemData& rItem) const;
-    long AppendGroupField();
-    void ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo);
-    SCROW SetGroupItem(long nDim, const ScDPItemData& rData);
-    const DataListType* GetGroupDimMemberValues(long nDim) const;
-    void GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const;
-    void ClearGroupFields();
-
-    SCCOL GetDimensionIndex(const rtl::OUString& sName) const;
-    sal_uLong GetNumberFormat( long nDim ) const;
-    bool  IsDateDimension( long nDim ) const ;
-    SCROW GetDimMemberCount( SCCOL nDim ) const;
-    SCROW GetOrder( long nDim, SCROW nIndex ) const;
-
-    const DataListType& GetDimMemberValues( SCCOL nDim ) const;
-    bool InitFromDoc(ScDocument* pDoc, const ScRange& rRange);
-    bool InitFromDataBase(const  ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& xRowSet, const Date& rNullDate);
-
-    SCROW  GetRowCount() const;
-    SCROW  GetItemDataId( sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty ) const;
-    rtl::OUString GetDimensionName(LabelsType::size_type nDim) const;
-    bool IsRowEmpty( SCROW nRow ) const;
-    bool IsValid() const;
-    bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam) const;
-
-    ScDocument* GetDoc() const;
-    long GetColumnCount() const;
-    long GetGroupFieldCount() const;
-
-    const ScDPItemData* GetItemDataById( long nDim, SCROW nId ) const;
-
-    bool operator== ( const ScDPCache& r ) const;
-
-    ScDPCache(ScDocument* pDoc);
-    ~ScDPCache();
-
-private:
-    void Clear();
-    void AddLabel(const rtl::OUString& rLabel);
-    bool AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat);
-    const GroupItems* GetGroupItems(long nDim) const;
-};
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index ddacf92..e0d57a6 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -74,7 +74,7 @@
 #include "unoreflist.hxx"
 #include "listenercalls.hxx"
 #include "dpshttab.hxx"
-#include "dptablecache.hxx"
+#include "dpcache.hxx"
 #include "tabprotection.hxx"
 #include "formulaparserpool.hxx"
 #include "clipparam.hxx"
diff --git a/sc/source/core/data/dpcache.cxx b/sc/source/core/data/dpcache.cxx
new file mode 100644
index 0000000..33a0a25
--- /dev/null
+++ b/sc/source/core/data/dpcache.cxx
@@ -0,0 +1,1123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright IBM Corporation 2009.
+ * Copyright 2009 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "dpcache.hxx"
+
+#include "document.hxx"
+#include "queryentry.hxx"
+#include "queryparam.hxx"
+#include "dpglobal.hxx"
+#include "dpobject.hxx"
+#include "globstr.hrc"
+#include "docoptio.hxx"
+#include "dpitemdata.hxx"
+#include "dputil.hxx"
+#include "dpnumgroupinfo.hxx"
+
+#include <rtl/math.hxx>
+#include <unotools/textsearch.hxx>
+#include <unotools/localedatawrapper.hxx>
+
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+
+#include <memory>
+
+const double D_TIMEFACTOR = 86400.0;
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::std::vector;
+using ::std::auto_ptr;
+
+namespace {
+
+/**
+ * Search for an item in the data array.  If it's in the array, return its
+ * index to the caller.
+ *
+ * @param rArray dimension array
+ * @param rOrder global order (what's this?)
+ * @param item item to search for
+ * @param rIndex the index of the found item in the global order.
+ *
+ * @return true if the item is found, or false otherwise.
+ */
+bool hasItemInDimension(const ScDPCache::DataListType& rArray, const ScDPCache::IndexArrayType& rOrder, const ScDPItemData& item, SCROW& rIndex)
+{
+    rIndex = rArray.size();
+    bool bFound = false;
+    SCROW nLo = 0;
+    SCROW nHi = rArray.size() - 1;
+    long nCompare;
+    while (nLo <= nHi)
+    {
+        SCROW nIndex = (nLo + nHi) / 2;
+        nCompare = ScDPItemData::Compare( rArray[rOrder[nIndex]], item );
+        if (nCompare < 0)
+            nLo = nIndex + 1;
+        else
+        {
+            nHi = nIndex - 1;
+            if (nCompare == 0)
+            {
+                bFound = true;
+                nLo = nIndex;
+            }
+        }
+    }
+    rIndex = nLo;
+    return bFound;
+}
+
+ScDPItemData* lcl_GetItemValue(
+    const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol, const Date& rNullDate, short& rNumType)
+{
+    rNumType = NUMBERFORMAT_NUMBER;
+    try
+    {
+        double fValue = 0.0;
+        switch (nType)
+        {
+            case sdbc::DataType::BIT:
+            case sdbc::DataType::BOOLEAN:
+            {
+                rNumType = NUMBERFORMAT_LOGICAL;
+                fValue  = xRow->getBoolean(nCol) ? 1 : 0;
+                return new ScDPItemData(fValue);
+            }
+            case sdbc::DataType::TINYINT:
+            case sdbc::DataType::SMALLINT:
+            case sdbc::DataType::INTEGER:
+            case sdbc::DataType::BIGINT:
+            case sdbc::DataType::FLOAT:
+            case sdbc::DataType::REAL:
+            case sdbc::DataType::DOUBLE:
+            case sdbc::DataType::NUMERIC:
+            case sdbc::DataType::DECIMAL:
+            {
+                //! do the conversion here?
+                fValue = xRow->getDouble(nCol);
+                return new ScDPItemData(fValue);
+            }
+            case sdbc::DataType::DATE:
+            {
+                rNumType = NUMBERFORMAT_DATE;
+
+                util::Date aDate = xRow->getDate(nCol);
+                fValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate;
+                return new ScDPItemData(fValue);
+            }
+            case sdbc::DataType::TIME:
+            {
+                rNumType = NUMBERFORMAT_TIME;
+
+                util::Time aTime = xRow->getTime(nCol);
+                fValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 +
+                           aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR;
+                return new ScDPItemData(fValue);
+            }
+            case sdbc::DataType::TIMESTAMP:
+            {
+                rNumType = NUMBERFORMAT_DATETIME;
+
+                util::DateTime aStamp = xRow->getTimestamp(nCol);
+                fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - rNullDate ) +
+                         ( aStamp.Hours * 3600 + aStamp.Minutes * 60 +
+                           aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR;
+                return new ScDPItemData(fValue);
+            }
+            case sdbc::DataType::CHAR:
+            case sdbc::DataType::VARCHAR:
+            case sdbc::DataType::LONGVARCHAR:
+            case sdbc::DataType::SQLNULL:
+            case sdbc::DataType::BINARY:
+            case sdbc::DataType::VARBINARY:
+            case sdbc::DataType::LONGVARBINARY:
+            default:
+                return new ScDPItemData(xRow->getString(nCol));
+        }
+    }
+    catch (uno::Exception&)
+    {
+    }
+
+    return NULL;
+}
+
+}
+
+ScDPCache::GroupItems::GroupItems() {}
+
+ScDPCache::GroupItems::GroupItems(const ScDPNumGroupInfo& rInfo) :
+    maInfo(rInfo) {}
+
+bool ScDPCache::operator== ( const ScDPCache& r ) const
+{
+    if ( GetColumnCount() == r.GetColumnCount() )
+    {
+        for ( SCCOL i = 0 ; i < GetColumnCount(); i++ )
+        {   //check dim names
+            if ( GetDimensionName( i ) != r.GetDimensionName( i ) )
+                return false;
+            //check rows count
+            if ( GetRowCount() != r.GetRowCount() )
+                return false;
+            //check dim member values
+            size_t nMembersCount = GetDimMemberValues( i ).size();
+            if ( GetDimMemberValues( i ).size() == r. GetDimMemberValues( i ).size() )
+            {
+                for ( size_t j = 0; j < nMembersCount; j++ )
+                {
+                    if ( GetDimMemberValues(i)[j] == r.GetDimMemberValues(i)[j] )
+                        continue;
+                    else
+                        return false;
+                }
+            }
+            else
+                return false;
+            //check source table index
+            for ( SCROW k=0 ; k < GetRowCount(); k ++ )
+            {
+                if ( GetItemDataId( i, k, false ) == r.GetItemDataId( i,k,false) )
+                    continue;
+                else
+                    return false;
+            }
+        }
+    }
+    return true;
+}
+
+ScDPCache::Field::Field() {}
+
+ScDPCache::ScDPCache(ScDocument* pDoc) :
+    mpDoc( pDoc ),
+    mnColumnCount ( 0 ),
+    mbDisposing(false)
+{
+}
+
+namespace {
+
+struct ClearObjectSource : std::unary_function<ScDPObject*, void>
+{
+    void operator() (ScDPObject* p) const
+    {
+        p->ClearSource();
+    }
+};
+
+}
+
+ScDPCache::~ScDPCache()
+{
+    // Make sure no live ScDPObject instances hold reference to this cache any
+    // more.
+    mbDisposing = true;
+    std::for_each(maRefObjects.begin(), maRefObjects.end(), ClearObjectSource());
+}
+
+bool ScDPCache::IsValid() const
+{
+    return !maFields.empty() && mnColumnCount > 0;
+}
+
+namespace {
+
+/**
+ * While the macro interpret level is incremented, the formula cells are
+ * (semi-)guaranteed to be interpreted.
+ */
+class MacroInterpretIncrementer
+{
+public:
+    MacroInterpretIncrementer(ScDocument* pDoc) :
+        mpDoc(pDoc)
+    {
+        mpDoc->IncMacroInterpretLevel();
+    }
+    ~MacroInterpretIncrementer()
+    {
+        mpDoc->DecMacroInterpretLevel();
+    }
+private:
+    ScDocument* mpDoc;
+};
+
+rtl::OUString createLabelString(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
+{
+    rtl::OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
+    if (aDocStr.isEmpty())
+    {
+        // Replace an empty label string with column name.
+        rtl::OUStringBuffer aBuf;
+        aBuf.append(ScGlobal::GetRscString(STR_COLUMN));
+        aBuf.append(sal_Unicode(' '));
+
+        ScAddress aColAddr(nCol, 0, 0);
+        rtl::OUString aColStr;
+        aColAddr.Format(aColStr, SCA_VALID_COL, NULL);
+        aBuf.append(aColStr);
+        aDocStr = aBuf.makeStringAndClear();
+    }
+    return aDocStr;
+}
+
+void initFromCell(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, ScDPItemData& rData, sal_uLong& rNumFormat)
+{
+    rtl::OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
+    rNumFormat = 0;
+
+    ScAddress aPos(nCol, nRow, nTab);
+
+    if (pDoc->GetErrCode(aPos))
+    {
+        rData.SetErrorString(aDocStr);
+    }
+    else if (pDoc->HasValueData(nCol, nRow, nTab))
+    {
+        double fVal = pDoc->GetValue(aPos);
+        rNumFormat = pDoc->GetNumberFormat(aPos);
+        rData.SetValue(fVal);
+    }
+    else if (pDoc->HasData(nCol, nRow, nTab))
+    {
+        rData.SetString(aDocStr);
+    }
+}
+
+}
+
+bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
+{
+    Clear();
+    // Make sure the formula cells within the data range are interpreted
+    // during this call, for this method may be called from the interpretation
+    // of GETPIVOTDATA, which disables nested formula interpretation without
+    // increasing the macro level.
+    MacroInterpretIncrementer aMacroInc(pDoc);
+
+    SCROW nStartRow = rRange.aStart.Row();  // start of data
+    SCROW nEndRow = rRange.aEnd.Row();
+    sal_uInt16 nStartCol = rRange.aStart.Col();
+    sal_uInt16 nEndCol = rRange.aEnd.Col();
+    sal_uInt16 nDocTab = rRange.aStart.Tab();
+
+    mnColumnCount = nEndCol - nStartCol + 1;
+
+    maFields.reserve(mnColumnCount);
+    for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
+        maFields.push_back(new Field);
+
+    maLabelNames.reserve(mnColumnCount+1);
+
+    for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
+    {
+        AddLabel(createLabelString(pDoc, nCol, nStartRow, nDocTab));
+        for (SCROW nRow = nStartRow + 1; nRow <= nEndRow; ++nRow)
+        {
+            std::auto_ptr<ScDPItemData> pData(new ScDPItemData);
+            sal_uLong nNumFormat = 0;
+            initFromCell(pDoc, nCol, nRow, nDocTab, *pData, nNumFormat);
+            AddData(nCol - nStartCol, pData.release(), nNumFormat);
+        }
+    }
+    return true;
+}
+
+bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate)
+{
+    Clear();
+    if (!xRowSet.is())
+        // Don't even waste time to go any further.
+        return false;
+    try
+    {
+        Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW);
+        Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData();
+        if (!xMeta.is())
+            return false;
+
+        mnColumnCount = xMeta->getColumnCount();
+        maFields.clear();
+        maFields.reserve(mnColumnCount);
+        for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
+            maFields.push_back(new Field);
+
+        // Get column titles and types.
+        maLabelNames.clear();
+        maLabelNames.reserve(mnColumnCount+1);
+
+        std::vector<sal_Int32> aColTypes(mnColumnCount);
+
+        for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol)
+        {
+            rtl::OUString aColTitle = xMeta->getColumnLabel(nCol+1);
+            aColTypes[nCol]  = xMeta->getColumnType(nCol+1);
+            AddLabel(aColTitle);
+        }
+
+        // Now get the data rows.
+        Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW);
+        xRowSet->first();
+        do
+        {
+            for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol)
+            {
+                short nFormatType = NUMBERFORMAT_UNDEFINED;
+                ScDPItemData* pNew = lcl_GetItemValue(
+                    xRow, aColTypes[nCol], nCol+1, rNullDate, nFormatType);
+                if (pNew)
+                {
+                    SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
+                    sal_uLong nNumFormat = pFormatter ? pFormatter->GetStandardFormat(nFormatType) : 0;
+                    AddData(nCol, pNew, nNumFormat);
+                }
+            }
+        }
+        while (xRowSet->next());
+
+        xRowSet->beforeFirst();
+
+        return true;
+    }
+    catch (const Exception&)
+    {
+        return false;
+    }
+}
+
+bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const
+{
+    if (!rParam.GetEntry(0).bDoQuery)
+        return true;
+    bool bMatchWholeCell = mpDoc->GetDocOptions().IsMatchWholeCell();
+
+    SCSIZE nEntryCount = rParam.GetEntryCount();
+    std::vector<bool> aPassed(nEntryCount, false);
+
+    long nPos = -1;
+    CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
+                                  ScGlobal::GetCollator() );
+    ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
+                                                       ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
+
+    for (size_t i = 0; i < nEntryCount && rParam.GetEntry(i).bDoQuery; ++i)
+    {
+        const ScQueryEntry& rEntry = rParam.GetEntry(i);
+        const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
+        // we can only handle one single direct query
+        // #i115431# nField in QueryParam is the sheet column, not the field within the source range
+        SCCOL nQueryCol = (SCCOL)rEntry.nField;
+        if ( nQueryCol < rParam.nCol1 )
+            nQueryCol = rParam.nCol1;
+        if ( nQueryCol > rParam.nCol2 )
+            nQueryCol = rParam.nCol2;
+        SCCOL nSourceField = nQueryCol - rParam.nCol1;
+        SCROW nId = GetItemDataId( nSourceField, nRow, false );
+        const ScDPItemData* pCellData = GetItemDataById( nSourceField, nId );
+
+        bool bOk = false;
+
+        if (rEntry.GetQueryItem().meType == ScQueryEntry::ByEmpty)
+        {
+            if (rEntry.IsQueryByEmpty())
+                bOk = pCellData->IsEmpty();
+            else
+            {
+                OSL_ASSERT(rEntry.IsQueryByNonEmpty());
+                bOk = !pCellData->IsEmpty();
+            }
+        }
+        else if (rEntry.GetQueryItem().meType != ScQueryEntry::ByString && pCellData->IsValue())
+        {   // by Value
+            double nCellVal = pCellData->GetValue();
+
+            switch (rEntry.eOp)
+            {
+                case SC_EQUAL :
+                    bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                    break;
+                case SC_LESS :
+                    bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                    break;
+                case SC_GREATER :
+                    bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                    break;
+                case SC_LESS_EQUAL :
+                    bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                    break;
+                case SC_GREATER_EQUAL :
+                    bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                    break;
+                case SC_NOT_EQUAL :
+                    bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                    break;
+                default:
+                    bOk= false;
+                    break;
+            }
+        }
+        else if ((rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+                 || (rEntry.GetQueryItem().meType == ScQueryEntry::ByString
+                     && pCellData->HasStringData() )
+                )
+        {   // by String
+            String  aCellStr = pCellData->GetString();
+
+            bool bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
+                                                   || (rEntry.eOp == SC_NOT_EQUAL)));
+            bool bTestRegExp = false;
+            if (bRealRegExp || bTestRegExp)
+            {
+                xub_StrLen nStart = 0;
+                xub_StrLen nEnd   = aCellStr.Len();
+                bool bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+                              ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+                // from 614 on, nEnd is behind the found text
+                if (bMatch && bMatchWholeCell
+                    && (nStart != 0 || nEnd != aCellStr.Len()))
+                    bMatch = false;    // RegExp must match entire cell string
+                if (bRealRegExp)
+                    bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
+            }
+            if (!bRealRegExp)
+            {
+                if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+                {
+                    if (bMatchWholeCell)
+                    {
+                        String aStr = rEntry.GetQueryItem().maString;
+                        bOk = pTransliteration->isEqual(aCellStr, aStr);
+                        bool bHasStar = false;
+                        xub_StrLen nIndex;
+                        if (( nIndex = aStr.Search('*') ) != STRING_NOTFOUND)
+                            bHasStar = sal_True;
+                        if (bHasStar && (nIndex>0))
+                        {
+                            for (i=0;(i<nIndex) && (i< aCellStr.Len()) ; i++)
+                            {
+                                if (aCellStr.GetChar( (sal_uInt16)i ) == aStr.GetChar((sal_uInt16) i ))
+                                {
+                                    bOk=1;
+                                }
+                                else
+                                {
+                                    bOk=0;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        const rtl::OUString& rQueryStr = rEntry.GetQueryItem().maString;
+                        ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
+                        String aCell = pTransliteration->transliterate(
+                            aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), &xOff);
+                        String aQuer = pTransliteration->transliterate(
+                            rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(), &xOff);
+                        bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
+                    }
+                    if (rEntry.eOp == SC_NOT_EQUAL)
+                        bOk = !bOk;
+                }
+                else
+                {   // use collator here because data was probably sorted
+                    sal_Int32 nCompare = pCollator->compareString(
+                        aCellStr, rEntry.GetQueryItem().maString);
+                    switch (rEntry.eOp)
+                    {
+                        case SC_LESS :
+                            bOk = (nCompare < 0);
+                            break;
+                        case SC_GREATER :
+                            bOk = (nCompare > 0);
+                            break;
+                        case SC_LESS_EQUAL :
+                            bOk = (nCompare <= 0);
+                            break;
+                        case SC_GREATER_EQUAL :
+                            bOk = (nCompare >= 0);
+                            break;
+                        case SC_NOT_EQUAL:
+                            OSL_FAIL("SC_NOT_EQUAL");
+                            break;
+                        case SC_TOPVAL:
+                        case SC_BOTVAL:
+                        case SC_TOPPERC:
+                        case SC_BOTPERC:
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+
+        if (nPos == -1)
+        {
+            nPos++;
+            aPassed[nPos] = bOk;
+        }
+        else
+        {
+            if (rEntry.eConnect == SC_AND)
+            {
+                aPassed[nPos] = aPassed[nPos] && bOk;
+            }
+            else
+            {
+                nPos++;
+                aPassed[nPos] = bOk;
+            }
+        }
+    }
+
+    for (long j=1; j <= nPos; j++)
+        aPassed[0] = aPassed[0] || aPassed[j];
+
+    bool bRet = aPassed[0];
+    return bRet;
+}
+
+bool ScDPCache::IsRowEmpty( SCROW nRow ) const
+{
+    return maEmptyRows[nRow];
+}
+
+bool ScDPCache::AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat)
+{
+    OSL_ENSURE( IsValid(), "  IsValid() == false " );
+    OSL_ENSURE( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" );
+
+    // Wrap this instance with scoped pointer to ensure proper deletion.
+    SAL_WNODEPRECATED_DECLARATIONS_PUSH
+    auto_ptr<ScDPItemData> p(pData);
+    SAL_WNODEPRECATED_DECLARATIONS_POP
+
+    SCROW nIndex = 0;
+    Field& rField = maFields[nDim];
+    if (!hasItemInDimension(rField.maItems, rField.maGlobalOrder, *pData, nIndex))
+    {
+        // This item doesn't exist in the dimension array yet.
+        rField.maItems.push_back(p);
+        rField.maGlobalOrder.insert(
+            rField.maGlobalOrder.begin()+nIndex, rField.maItems.size()-1);
+        OSL_ENSURE(rField.maGlobalOrder[nIndex] == sal::static_int_cast<SCROW>(rField.maItems.size())-1, "ScDPTableDataCache::AddData ");
+        rField.maData.push_back(rField.maItems.size()-1);
+        rField.maNumFormats.push_back(nNumFormat);
+    }
+    else
+        rField.maData.push_back(rField.maGlobalOrder[nIndex]);
+
+//init empty row tag
+    size_t nCurRow = maFields[nDim].maData.size() - 1;
+
+    while (maEmptyRows.size() <= nCurRow)
+        maEmptyRows.push_back(true);
+
+    if (!pData->IsEmpty())
+        maEmptyRows[nCurRow] = false;
+
+    return true;
+}
+
+const ScDPCache::GroupItems* ScDPCache::GetGroupItems(long nDim) const
+{
+    if (nDim < 0)
+        return NULL;
+
+    long nSourceCount = static_cast<long>(maFields.size());
+    if (nDim < nSourceCount)
+        return maFields[nDim].mpGroup.get();
+
+    nDim -= nSourceCount;
+    if (nDim < static_cast<long>(maGroupFields.size()))
+        return &maGroupFields[nDim];
+
+    return NULL;
+}
+
+rtl::OUString ScDPCache::GetDimensionName(LabelsType::size_type nDim) const
+{
+    OSL_ENSURE(nDim < maLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName");
+    OSL_ENSURE(maLabelNames.size() == static_cast <sal_uInt16> (mnColumnCount+1), "ScDPTableDataCache::GetDimensionName");
+
+    if ( nDim+1 < maLabelNames.size() )
+    {
+        return maLabelNames[nDim+1];
+    }
+    else
+        return rtl::OUString();
+}
+
+namespace {
+
+typedef boost::unordered_set<rtl::OUString, rtl::OUStringHash> LabelSet;
+
+class InsertLabel : public std::unary_function<rtl::OUString, void>
+{
+    LabelSet& mrNames;
+public:
+    InsertLabel(LabelSet& rNames) : mrNames(rNames) {}
+    void operator() (const rtl::OUString& r)
+    {
+        mrNames.insert(r);
+    }
+};
+
+}
+
+void ScDPCache::Clear()
+{
+    maFields.clear();
+    maLabelNames.clear();
+    maGroupFields.clear();
+    maEmptyRows.clear();
+}
+
+void ScDPCache::AddLabel(const rtl::OUString& rLabel)
+{
+    OSL_ENSURE( IsValid(), "  IsValid() == false " );
+
+    if ( maLabelNames.empty() )
+        maLabelNames.push_back(ScGlobal::GetRscString(STR_PIVOT_DATA));
+
+    //reset name if needed
+    LabelSet aExistingNames;
+    std::for_each(maLabelNames.begin(), maLabelNames.end(), InsertLabel(aExistingNames));
+    sal_Int32 nSuffix = 1;
+    rtl::OUString aNewName = rLabel;
+    while (true)
+    {
+        if (!aExistingNames.count(aNewName))
+        {
+            // unique name found!
+            maLabelNames.push_back(aNewName);
+            return;
+        }
+
+        // Name already exists.
+        rtl::OUStringBuffer aBuf(rLabel);
+        aBuf.append(++nSuffix);
+        aNewName = aBuf.makeStringAndClear();
+    }
+}
+
+SCROW ScDPCache::GetItemDataId(sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty) const
+{
+    OSL_ENSURE( IsValid(), "  IsValid() == false " );
+    OSL_ENSURE(nDim < mnColumnCount, "ScDPTableDataCache::GetItemDataId ");
+
+    const Field& rField = maFields[nDim];
+    if (bRepeatIfEmpty)
+    {
+        while (nRow > 0 && rField.maItems[rField.maData[nRow]].IsEmpty())
+            --nRow;
+    }
+
+    return rField.maData[nRow];
+}
+
+const ScDPItemData* ScDPCache::GetItemDataById(long nDim, SCROW nId) const
+{
+    if (nDim < 0 || nId < 0)
+        return NULL;
+
+    size_t nSourceCount = maFields.size();
+    size_t nDimPos = static_cast<size_t>(nDim);
+    size_t nItemId = static_cast<size_t>(nId);
+    if (nDimPos < nSourceCount)
+    {
+        // source field.
+        const Field& rField = maFields[nDimPos];
+        if (nItemId < rField.maItems.size())
+            return &rField.maItems[nItemId];
+
+        if (!rField.mpGroup)
+            return NULL;
+
+        nItemId -= rField.maItems.size();
+        const DataListType& rGI = rField.mpGroup->maItems;
+        if (nItemId >= rGI.size())
+            return NULL;
+
+        return &rGI[nItemId];
+    }
+
+    // Try group fields.
+    nDimPos -= nSourceCount;
+    if (nDimPos >= maGroupFields.size())
+        return NULL;
+
+    const DataListType& rGI = maGroupFields[nDimPos].maItems;
+    if (nItemId >= rGI.size())
+        return NULL;
+
+    return &rGI[nItemId];
+}
+
+SCROW ScDPCache::GetRowCount() const
+{
+    if (maFields.empty() || maFields[0].maData.empty())
+        return 0;
+
+    return maFields[0].maData.size();
+}
+
+const ScDPCache::DataListType& ScDPCache::GetDimMemberValues(SCCOL nDim) const
+{
+    OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," nDim < mnColumnCount ");
+    return maFields[nDim].maItems;
+}
+
+sal_uLong ScDPCache::GetNumberFormat( long nDim ) const
+{
+    if ( nDim >= mnColumnCount )
+        return 0;
+
+    const std::vector<sal_uLong>& rNumFormats = maFields[nDim].maNumFormats;
+    if (rNumFormats.empty())
+        return 0;
+
+    // TODO: Find a way to determine the dominant number format in presence of
+    // multiple number formats in the same field.
+    return *rNumFormats.begin();
+}
+
+bool ScDPCache::IsDateDimension( long nDim ) const
+{
+    if (nDim >= mnColumnCount)
+        return false;
+
+    SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
+    if (!pFormatter)
+        return false;
+
+    const std::vector<sal_uLong>& rNumFormats = maFields[nDim].maNumFormats;
+    if (rNumFormats.empty())
+        return false;
+
+    short eType = pFormatter->GetType(rNumFormats[0]);
+    return (eType == NUMBERFORMAT_DATE) || (eType == NUMBERFORMAT_DATETIME);
+}
+
+SCROW ScDPCache::GetDimMemberCount( SCCOL nDim ) const
+{
+    OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," ScDPTableDataCache::GetDimMemberCount : out of bound ");
+    return maFields[nDim].maItems.size();
+}
+
+SCCOL ScDPCache::GetDimensionIndex(const rtl::OUString& sName) const
+{
+    for (size_t i = 1; i < maLabelNames.size(); ++i)
+    {
+        if (maLabelNames[i].equals(sName))
+            return static_cast<SCCOL>(i-1);
+    }
+    return -1;
+}
+
+void ScDPCache::AddReference(ScDPObject* pObj) const
+{
+    maRefObjects.insert(pObj);
+}
+
+void ScDPCache::RemoveReference(ScDPObject* pObj) const
+{
+    if (mbDisposing)
+        // Object being deleted.
+        return;
+
+    maRefObjects.erase(pObj);
+    if (maRefObjects.empty())
+        mpDoc->GetDPCollection()->RemoveCache(this);
+}
+
+const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const
+{
+    return maRefObjects;
+}
+
+SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
+{
+    if (nDim < 0)
+        return -1;
+
+    if (nDim < mnColumnCount)
+    {
+        // source field.
+        const DataListType& rItems = maFields[nDim].maItems;
+        for (size_t i = 0, n = rItems.size(); i < n; ++i)
+        {
+            if (rItems[i] == rItem)
+                return i;
+        }
+
+        if (!maFields[nDim].mpGroup)
+            return -1;
+
+        // grouped source field.
+        const DataListType& rGI = maFields[nDim].mpGroup->maItems;
+        for (size_t i = 0, n = rGI.size(); i < n; ++i)
+        {
+            if (rGI[i] == rItem)
+                return rItems.size() + i;
+        }
+        return -1;
+    }
+
+    // group field.
+    nDim -= mnColumnCount;
+    if (static_cast<size_t>(nDim) < maGroupFields.size())
+    {
+        const DataListType& rGI = maGroupFields[nDim].maItems;
+        for (size_t i = 0, n = rGI.size(); i < n; ++i)
+        {
+            if (rGI[i] == rItem)
+                return i;
+        }
+    }
+
+    return -1;
+}
+
+rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem) const
+{
+    if (nDim < 0)
+        return rItem.GetString();
+
+    ScDPItemData::Type eType = rItem.GetType();
+    if (eType == ScDPItemData::Value)
+    {
+        // Format value using the stored number format.
+        sal_uLong nNumFormat = GetNumberFormat(nDim);
+        SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
+        if (pFormatter)
+        {
+            Color* pColor = NULL;
+            String aStr;
+            pFormatter->GetOutputString(rItem.GetValue(), nNumFormat, aStr, &pColor);
+            return aStr;
+        }
+    }
+
+    if (eType == ScDPItemData::GroupValue)
+    {
+        ScDPItemData::GroupValueAttr aAttr = rItem.GetGroupValue();
+        double fStart = 0.0, fEnd = 0.0;
+        const GroupItems* p = GetGroupItems(nDim);
+        if (p)
+        {
+            fStart = p->maInfo.mfStart;
+            fEnd = p->maInfo.mfEnd;
+        }
+        return ScDPUtil::getDateGroupName(
+            aAttr.mnGroupType, aAttr.mnValue, mpDoc->GetFormatTable(), fStart, fEnd);
+    }
+
+    if (eType == ScDPItemData::RangeStart)
+    {
+        double fVal = rItem.GetValue();
+        const GroupItems* p = GetGroupItems(nDim);
+        if (!p)
+            return rItem.GetString();
+
+        sal_Unicode cDecSep = ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0);
+        return ScDPUtil::getNumGroupName(fVal, p->maInfo, cDecSep, mpDoc->GetFormatTable());
+    }
+
+    return rItem.GetString();
+}
+
+long ScDPCache::AppendGroupField()
+{
+    maGroupFields.push_back(new GroupItems);
+    return static_cast<long>(maFields.size() + maGroupFields.size() - 1);
+}
+
+void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo)
+{
+    if (nDim < 0)
+        return;
+
+    long nSourceCount = static_cast<long>(maFields.size());
+    if (nDim < nSourceCount)
+    {
+        maFields.at(nDim).mpGroup.reset(new GroupItems(rNumInfo));
+        return;
+    }
+
+    nDim -= nSourceCount;
+    if (nDim < static_cast<long>(maGroupFields.size()))
+    {
+        GroupItems& rGI = maGroupFields[nDim];
+        rGI.maItems.clear();
+        rGI.maInfo = rNumInfo;
+    }
+}
+
+SCROW ScDPCache::SetGroupItem(long nDim, const ScDPItemData& rData)
+{
+    if (nDim < 0)
+        return -1;
+
+    long nSourceCount = static_cast<long>(maFields.size());
+    if (nDim < nSourceCount)
+    {
+        GroupItems& rGI = *maFields.at(nDim).mpGroup;
+        rGI.maItems.push_back(new ScDPItemData(rData));
+        SCROW nId = maFields[nDim].maItems.size() + rGI.maItems.size() - 1;
+        return nId;
+    }
+
+    nDim -= nSourceCount;
+    if (nDim < static_cast<long>(maGroupFields.size()))
+    {
+        DataListType& rItems = maGroupFields.at(nDim).maItems;
+        rItems.push_back(new ScDPItemData(rData));
+        return rItems.size()-1;
+    }
+
+    return -1;
+}
+
+const ScDPCache::DataListType* ScDPCache::GetGroupDimMemberValues(long nDim) const
+{
+    if (nDim < 0)
+        return NULL;
+
+    long nSourceCount = static_cast<long>(maFields.size());
+    if (nDim < nSourceCount)
+    {
+        if (!maFields.at(nDim).mpGroup)
+            return NULL;
+
+        return &maFields[nDim].mpGroup->maItems;
+    }
+
+    nDim -= nSourceCount;
+    if (nDim < static_cast<long>(maGroupFields.size()))
+        return &maGroupFields.at(nDim).maItems;
+
+    return NULL;
+}
+
+void ScDPCache::GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const
+{
+    if (nDim < 0)
+        return;
+
+    long nSourceCount = static_cast<long>(maFields.size());
+    if (nDim < nSourceCount)
+    {
+        if (!maFields.at(nDim).mpGroup)
+            return;
+
+        size_t nOffset = maFields[nDim].maItems.size();
+        const DataListType& rGI = maFields[nDim].mpGroup->maItems;
+        for (size_t i = 0, n = rGI.size(); i < n; ++i)
+            rIds.push_back(static_cast<SCROW>(i + nOffset));
+
+        return;
+    }
+
+    nDim -= nSourceCount;
+    if (nDim < static_cast<long>(maGroupFields.size()))
+    {
+        const DataListType& rGI = maGroupFields.at(nDim).maItems;
+        for (size_t i = 0, n = rGI.size(); i < n; ++i)
+            rIds.push_back(static_cast<SCROW>(i));
+    }
+}
+
+namespace {
+
+struct ClearGroupItems : std::unary_function<ScDPCache::Field, void>
+{
+    void operator() (ScDPCache::Field& r) const
+    {
+        r.mpGroup.reset();
+    }
+};
+
+}
+
+void ScDPCache::ClearGroupFields()
+{
+    maGroupFields.clear();
+    std::for_each(maFields.begin(), maFields.end(), ClearGroupItems());
+}
+
+SCROW ScDPCache::GetOrder(long nDim, SCROW nIndex) const
+{
+    OSL_ENSURE( IsValid(), "  IsValid() == false " );
+    OSL_ENSURE( nDim >=0 && nDim < mnColumnCount, "ScDPTableDataCache::GetOrder : out of bound" );
+
+    const Field& rField = maFields[nDim];
+    if (rField.maIndexOrder.size() !=  rField.maGlobalOrder.size())
+    { //not inited
+        SCROW nRow  = 0;
+        rField.maIndexOrder.resize(rField.maGlobalOrder.size(), 0);
+        for (size_t i = 0, n = rField.maGlobalOrder.size(); i < n; ++i)
+        {
+            nRow = rField.maGlobalOrder[i];
+            rField.maIndexOrder[nRow] = i;
+        }
+    }
+
+    OSL_ENSURE(nIndex >= 0 && sal::static_int_cast<sal_uInt32>(nIndex) < rField.maIndexOrder.size() , "ScDPTableDataCache::GetOrder");
+    return rField.maIndexOrder[nIndex];
+}
+
+ScDocument* ScDPCache::GetDoc() const
+{
+    return mpDoc;
+};
+
+long ScDPCache::GetColumnCount() const
+{
+    return mnColumnCount;
+}
+
+long ScDPCache::GetGroupFieldCount() const
+{
+    return maGroupFields.size();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
deleted file mode 100644
index c01e132..0000000
--- a/sc/source/core/data/dptablecache.cxx
+++ /dev/null
@@ -1,1123 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright IBM Corporation 2009.
- * Copyright 2009 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org.  If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-#include "dptablecache.hxx"
-
-#include "document.hxx"
-#include "queryentry.hxx"
-#include "queryparam.hxx"
-#include "dpglobal.hxx"
-#include "dpobject.hxx"
-#include "globstr.hrc"
-#include "docoptio.hxx"
-#include "dpitemdata.hxx"
-#include "dputil.hxx"
-#include "dpnumgroupinfo.hxx"
-
-#include <rtl/math.hxx>
-#include <unotools/textsearch.hxx>
-#include <unotools/localedatawrapper.hxx>
-
-#include <com/sun/star/sdbc/DataType.hpp>
-#include <com/sun/star/sdbc/XRow.hpp>
-#include <com/sun/star/sdbc/XRowSet.hpp>
-#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
-#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
-
-#include <memory>
-
-const double D_TIMEFACTOR = 86400.0;
-
-using namespace ::com::sun::star;
-
-using ::com::sun::star::uno::Exception;
-using ::com::sun::star::uno::Reference;
-using ::com::sun::star::uno::UNO_QUERY;
-using ::com::sun::star::uno::UNO_QUERY_THROW;
-using ::std::vector;
-using ::std::auto_ptr;
-
-namespace {
-
-/**
- * Search for an item in the data array.  If it's in the array, return its
- * index to the caller.
- *
- * @param rArray dimension array
- * @param rOrder global order (what's this?)
- * @param item item to search for
- * @param rIndex the index of the found item in the global order.
- *
- * @return true if the item is found, or false otherwise.
- */
-bool hasItemInDimension(const ScDPCache::DataListType& rArray, const ScDPCache::IndexArrayType& rOrder, const ScDPItemData& item, SCROW& rIndex)
-{
-    rIndex = rArray.size();
-    bool bFound = false;
-    SCROW nLo = 0;
-    SCROW nHi = rArray.size() - 1;
-    long nCompare;
-    while (nLo <= nHi)
-    {
-        SCROW nIndex = (nLo + nHi) / 2;
-        nCompare = ScDPItemData::Compare( rArray[rOrder[nIndex]], item );
-        if (nCompare < 0)
-            nLo = nIndex + 1;
-        else
-        {
-            nHi = nIndex - 1;
-            if (nCompare == 0)
-            {
-                bFound = true;
-                nLo = nIndex;
-            }
-        }
-    }
-    rIndex = nLo;
-    return bFound;
-}
-
-ScDPItemData* lcl_GetItemValue(
-    const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol, const Date& rNullDate, short& rNumType)
-{
-    rNumType = NUMBERFORMAT_NUMBER;
-    try
-    {
-        double fValue = 0.0;
-        switch (nType)
-        {
-            case sdbc::DataType::BIT:
-            case sdbc::DataType::BOOLEAN:
-            {
-                rNumType = NUMBERFORMAT_LOGICAL;
-                fValue  = xRow->getBoolean(nCol) ? 1 : 0;
-                return new ScDPItemData(fValue);
-            }
-            case sdbc::DataType::TINYINT:
-            case sdbc::DataType::SMALLINT:
-            case sdbc::DataType::INTEGER:
-            case sdbc::DataType::BIGINT:
-            case sdbc::DataType::FLOAT:
-            case sdbc::DataType::REAL:
-            case sdbc::DataType::DOUBLE:
-            case sdbc::DataType::NUMERIC:
-            case sdbc::DataType::DECIMAL:
-            {
-                //! do the conversion here?
-                fValue = xRow->getDouble(nCol);
-                return new ScDPItemData(fValue);
-            }
-            case sdbc::DataType::DATE:
-            {
-                rNumType = NUMBERFORMAT_DATE;
-
-                util::Date aDate = xRow->getDate(nCol);
-                fValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate;
-                return new ScDPItemData(fValue);
-            }
-            case sdbc::DataType::TIME:
-            {
-                rNumType = NUMBERFORMAT_TIME;
-
-                util::Time aTime = xRow->getTime(nCol);
-                fValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 +
-                           aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR;
-                return new ScDPItemData(fValue);
-            }
-            case sdbc::DataType::TIMESTAMP:
-            {
-                rNumType = NUMBERFORMAT_DATETIME;
-
-                util::DateTime aStamp = xRow->getTimestamp(nCol);
-                fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - rNullDate ) +
-                         ( aStamp.Hours * 3600 + aStamp.Minutes * 60 +
-                           aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR;
-                return new ScDPItemData(fValue);
-            }
-            case sdbc::DataType::CHAR:
-            case sdbc::DataType::VARCHAR:
-            case sdbc::DataType::LONGVARCHAR:
-            case sdbc::DataType::SQLNULL:
-            case sdbc::DataType::BINARY:
-            case sdbc::DataType::VARBINARY:
-            case sdbc::DataType::LONGVARBINARY:
-            default:
-                return new ScDPItemData(xRow->getString(nCol));
-        }
-    }
-    catch (uno::Exception&)
-    {
-    }
-
-    return NULL;
-}
-
-}
-
-ScDPCache::GroupItems::GroupItems() {}
-
-ScDPCache::GroupItems::GroupItems(const ScDPNumGroupInfo& rInfo) :
-    maInfo(rInfo) {}
-
-bool ScDPCache::operator== ( const ScDPCache& r ) const
-{
-    if ( GetColumnCount() == r.GetColumnCount() )
-    {
-        for ( SCCOL i = 0 ; i < GetColumnCount(); i++ )
-        {   //check dim names
-            if ( GetDimensionName( i ) != r.GetDimensionName( i ) )
-                return false;
-            //check rows count
-            if ( GetRowCount() != r.GetRowCount() )
-                return false;
-            //check dim member values
-            size_t nMembersCount = GetDimMemberValues( i ).size();
-            if ( GetDimMemberValues( i ).size() == r. GetDimMemberValues( i ).size() )
-            {
-                for ( size_t j = 0; j < nMembersCount; j++ )
-                {
-                    if ( GetDimMemberValues(i)[j] == r.GetDimMemberValues(i)[j] )
-                        continue;
-                    else
-                        return false;
-                }
-            }
-            else
-                return false;
-            //check source table index
-            for ( SCROW k=0 ; k < GetRowCount(); k ++ )
-            {
-                if ( GetItemDataId( i, k, false ) == r.GetItemDataId( i,k,false) )
-                    continue;
-                else
-                    return false;
-            }
-        }
-    }
-    return true;
-}
-
-ScDPCache::Field::Field() {}
-
-ScDPCache::ScDPCache(ScDocument* pDoc) :
-    mpDoc( pDoc ),
-    mnColumnCount ( 0 ),
-    mbDisposing(false)
-{
-}
-
-namespace {
-
-struct ClearObjectSource : std::unary_function<ScDPObject*, void>
-{
-    void operator() (ScDPObject* p) const
-    {
-        p->ClearSource();
-    }
-};
-
-}
-
-ScDPCache::~ScDPCache()
-{
-    // Make sure no live ScDPObject instances hold reference to this cache any
-    // more.
-    mbDisposing = true;
-    std::for_each(maRefObjects.begin(), maRefObjects.end(), ClearObjectSource());
-}
-
-bool ScDPCache::IsValid() const
-{
-    return !maFields.empty() && mnColumnCount > 0;
-}
-
-namespace {
-
-/**
- * While the macro interpret level is incremented, the formula cells are
- * (semi-)guaranteed to be interpreted.
- */
-class MacroInterpretIncrementer
-{
-public:
-    MacroInterpretIncrementer(ScDocument* pDoc) :
-        mpDoc(pDoc)
-    {
-        mpDoc->IncMacroInterpretLevel();
-    }
-    ~MacroInterpretIncrementer()
-    {
-        mpDoc->DecMacroInterpretLevel();
-    }
-private:
-    ScDocument* mpDoc;
-};
-
-rtl::OUString createLabelString(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
-{
-    rtl::OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
-    if (aDocStr.isEmpty())
-    {
-        // Replace an empty label string with column name.
-        rtl::OUStringBuffer aBuf;
-        aBuf.append(ScGlobal::GetRscString(STR_COLUMN));
-        aBuf.append(sal_Unicode(' '));
-
-        ScAddress aColAddr(nCol, 0, 0);
-        rtl::OUString aColStr;
-        aColAddr.Format(aColStr, SCA_VALID_COL, NULL);
-        aBuf.append(aColStr);
-        aDocStr = aBuf.makeStringAndClear();
-    }
-    return aDocStr;
-}
-
-void initFromCell(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, ScDPItemData& rData, sal_uLong& rNumFormat)
-{
-    rtl::OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
-    rNumFormat = 0;
-
-    ScAddress aPos(nCol, nRow, nTab);
-
-    if (pDoc->GetErrCode(aPos))
-    {
-        rData.SetErrorString(aDocStr);
-    }
-    else if (pDoc->HasValueData(nCol, nRow, nTab))
-    {
-        double fVal = pDoc->GetValue(aPos);
-        rNumFormat = pDoc->GetNumberFormat(aPos);
-        rData.SetValue(fVal);
-    }
-    else if (pDoc->HasData(nCol, nRow, nTab))
-    {
-        rData.SetString(aDocStr);
-    }
-}
-
-}
-
-bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
-{
-    Clear();
-    // Make sure the formula cells within the data range are interpreted
-    // during this call, for this method may be called from the interpretation
-    // of GETPIVOTDATA, which disables nested formula interpretation without
-    // increasing the macro level.
-    MacroInterpretIncrementer aMacroInc(pDoc);
-
-    SCROW nStartRow = rRange.aStart.Row();  // start of data
-    SCROW nEndRow = rRange.aEnd.Row();
-    sal_uInt16 nStartCol = rRange.aStart.Col();
-    sal_uInt16 nEndCol = rRange.aEnd.Col();
-    sal_uInt16 nDocTab = rRange.aStart.Tab();
-
-    mnColumnCount = nEndCol - nStartCol + 1;
-
-    maFields.reserve(mnColumnCount);
-    for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
-        maFields.push_back(new Field);
-
-    maLabelNames.reserve(mnColumnCount+1);
-
-    for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
-    {
-        AddLabel(createLabelString(pDoc, nCol, nStartRow, nDocTab));
-        for (SCROW nRow = nStartRow + 1; nRow <= nEndRow; ++nRow)
-        {
-            std::auto_ptr<ScDPItemData> pData(new ScDPItemData);
-            sal_uLong nNumFormat = 0;
-            initFromCell(pDoc, nCol, nRow, nDocTab, *pData, nNumFormat);
-            AddData(nCol - nStartCol, pData.release(), nNumFormat);
-        }
-    }
-    return true;
-}
-
-bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate)
-{
-    Clear();
-    if (!xRowSet.is())
-        // Don't even waste time to go any further.
-        return false;
-    try
-    {
-        Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW);
-        Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData();
-        if (!xMeta.is())
-            return false;
-
-        mnColumnCount = xMeta->getColumnCount();
-        maFields.clear();
-        maFields.reserve(mnColumnCount);
-        for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i)
-            maFields.push_back(new Field);
-
-        // Get column titles and types.
-        maLabelNames.clear();
-        maLabelNames.reserve(mnColumnCount+1);
-
-        std::vector<sal_Int32> aColTypes(mnColumnCount);
-
-        for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol)
-        {
-            rtl::OUString aColTitle = xMeta->getColumnLabel(nCol+1);
-            aColTypes[nCol]  = xMeta->getColumnType(nCol+1);
-            AddLabel(aColTitle);
-        }
-
-        // Now get the data rows.
-        Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW);
-        xRowSet->first();
-        do
-        {
-            for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol)
-            {
-                short nFormatType = NUMBERFORMAT_UNDEFINED;
-                ScDPItemData* pNew = lcl_GetItemValue(
-                    xRow, aColTypes[nCol], nCol+1, rNullDate, nFormatType);
-                if (pNew)
-                {
-                    SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
-                    sal_uLong nNumFormat = pFormatter ? pFormatter->GetStandardFormat(nFormatType) : 0;
-                    AddData(nCol, pNew, nNumFormat);
-                }
-            }
-        }
-        while (xRowSet->next());
-
-        xRowSet->beforeFirst();
-
-        return true;
-    }
-    catch (const Exception&)
-    {
-        return false;
-    }
-}
-
-bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const
-{
-    if (!rParam.GetEntry(0).bDoQuery)
-        return true;
-    bool bMatchWholeCell = mpDoc->GetDocOptions().IsMatchWholeCell();
-
-    SCSIZE nEntryCount = rParam.GetEntryCount();
-    std::vector<bool> aPassed(nEntryCount, false);
-
-    long nPos = -1;
-    CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
-                                  ScGlobal::GetCollator() );
-    ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
-                                                       ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
-
-    for (size_t i = 0; i < nEntryCount && rParam.GetEntry(i).bDoQuery; ++i)
-    {
-        const ScQueryEntry& rEntry = rParam.GetEntry(i);
-        const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
-        // we can only handle one single direct query
-        // #i115431# nField in QueryParam is the sheet column, not the field within the source range
-        SCCOL nQueryCol = (SCCOL)rEntry.nField;
-        if ( nQueryCol < rParam.nCol1 )
-            nQueryCol = rParam.nCol1;
-        if ( nQueryCol > rParam.nCol2 )
-            nQueryCol = rParam.nCol2;
-        SCCOL nSourceField = nQueryCol - rParam.nCol1;
-        SCROW nId = GetItemDataId( nSourceField, nRow, false );
-        const ScDPItemData* pCellData = GetItemDataById( nSourceField, nId );
-
-        bool bOk = false;
-
-        if (rEntry.GetQueryItem().meType == ScQueryEntry::ByEmpty)
-        {
-            if (rEntry.IsQueryByEmpty())
-                bOk = pCellData->IsEmpty();
-            else
-            {
-                OSL_ASSERT(rEntry.IsQueryByNonEmpty());
-                bOk = !pCellData->IsEmpty();
-            }
-        }
-        else if (rEntry.GetQueryItem().meType != ScQueryEntry::ByString && pCellData->IsValue())
-        {   // by Value
-            double nCellVal = pCellData->GetValue();
-
-            switch (rEntry.eOp)
-            {
-                case SC_EQUAL :
-                    bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_LESS :
-                    bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_GREATER :
-                    bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_LESS_EQUAL :
-                    bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_GREATER_EQUAL :
-                    bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_NOT_EQUAL :
-                    bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                default:
-                    bOk= false;
-                    break;
-            }
-        }
-        else if ((rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
-                 || (rEntry.GetQueryItem().meType == ScQueryEntry::ByString
-                     && pCellData->HasStringData() )
-                )
-        {   // by String
-            String  aCellStr = pCellData->GetString();
-
-            bool bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
-                                                   || (rEntry.eOp == SC_NOT_EQUAL)));
-            bool bTestRegExp = false;
-            if (bRealRegExp || bTestRegExp)
-            {
-                xub_StrLen nStart = 0;
-                xub_StrLen nEnd   = aCellStr.Len();
-                bool bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
-                              ->SearchFrwrd( aCellStr, &nStart, &nEnd );
-                // from 614 on, nEnd is behind the found text
-                if (bMatch && bMatchWholeCell
-                    && (nStart != 0 || nEnd != aCellStr.Len()))
-                    bMatch = false;    // RegExp must match entire cell string
-                if (bRealRegExp)
-                    bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch);
-            }
-            if (!bRealRegExp)
-            {
-                if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
-                {
-                    if (bMatchWholeCell)
-                    {
-                        String aStr = rEntry.GetQueryItem().maString;
-                        bOk = pTransliteration->isEqual(aCellStr, aStr);
-                        bool bHasStar = false;
-                        xub_StrLen nIndex;
-                        if (( nIndex = aStr.Search('*') ) != STRING_NOTFOUND)
-                            bHasStar = sal_True;
-                        if (bHasStar && (nIndex>0))
-                        {
-                            for (i=0;(i<nIndex) && (i< aCellStr.Len()) ; i++)
-                            {
-                                if (aCellStr.GetChar( (sal_uInt16)i ) == aStr.GetChar((sal_uInt16) i ))
-                                {
-                                    bOk=1;
-                                }
-                                else
-                                {
-                                    bOk=0;
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    else
-                    {
-                        const rtl::OUString& rQueryStr = rEntry.GetQueryItem().maString;
-                        ::com::sun::star::uno::Sequence< sal_Int32 > xOff;
-                        String aCell = pTransliteration->transliterate(
-                            aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), &xOff);
-                        String aQuer = pTransliteration->transliterate(
-                            rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(), &xOff);
-                        bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND);
-                    }
-                    if (rEntry.eOp == SC_NOT_EQUAL)
-                        bOk = !bOk;
-                }
-                else
-                {   // use collator here because data was probably sorted
-                    sal_Int32 nCompare = pCollator->compareString(
-                        aCellStr, rEntry.GetQueryItem().maString);
-                    switch (rEntry.eOp)
-                    {
-                        case SC_LESS :
-                            bOk = (nCompare < 0);
-                            break;
-                        case SC_GREATER :
-                            bOk = (nCompare > 0);
-                            break;
-                        case SC_LESS_EQUAL :
-                            bOk = (nCompare <= 0);
-                            break;
-                        case SC_GREATER_EQUAL :
-                            bOk = (nCompare >= 0);
-                            break;
-                        case SC_NOT_EQUAL:
-                            OSL_FAIL("SC_NOT_EQUAL");
-                            break;
-                        case SC_TOPVAL:
-                        case SC_BOTVAL:
-                        case SC_TOPPERC:
-                        case SC_BOTPERC:
-                        default:
-                            break;
-                    }
-                }
-            }
-        }
-
-        if (nPos == -1)
-        {
-            nPos++;
-            aPassed[nPos] = bOk;
-        }
-        else
-        {
-            if (rEntry.eConnect == SC_AND)
-            {
-                aPassed[nPos] = aPassed[nPos] && bOk;
-            }
-            else
-            {
-                nPos++;
-                aPassed[nPos] = bOk;
-            }
-        }
-    }
-
-    for (long j=1; j <= nPos; j++)
-        aPassed[0] = aPassed[0] || aPassed[j];
-
-    bool bRet = aPassed[0];
-    return bRet;
-}
-
-bool ScDPCache::IsRowEmpty( SCROW nRow ) const
-{
-    return maEmptyRows[nRow];
-}
-
-bool ScDPCache::AddData(long nDim, ScDPItemData* pData, sal_uLong nNumFormat)
-{
-    OSL_ENSURE( IsValid(), "  IsValid() == false " );
-    OSL_ENSURE( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" );
-
-    // Wrap this instance with scoped pointer to ensure proper deletion.
-    SAL_WNODEPRECATED_DECLARATIONS_PUSH
-    auto_ptr<ScDPItemData> p(pData);
-    SAL_WNODEPRECATED_DECLARATIONS_POP
-
-    SCROW nIndex = 0;
-    Field& rField = maFields[nDim];
-    if (!hasItemInDimension(rField.maItems, rField.maGlobalOrder, *pData, nIndex))
-    {
-        // This item doesn't exist in the dimension array yet.
-        rField.maItems.push_back(p);
-        rField.maGlobalOrder.insert(
-            rField.maGlobalOrder.begin()+nIndex, rField.maItems.size()-1);
-        OSL_ENSURE(rField.maGlobalOrder[nIndex] == sal::static_int_cast<SCROW>(rField.maItems.size())-1, "ScDPTableDataCache::AddData ");
-        rField.maData.push_back(rField.maItems.size()-1);
-        rField.maNumFormats.push_back(nNumFormat);
-    }
-    else
-        rField.maData.push_back(rField.maGlobalOrder[nIndex]);
-
-//init empty row tag
-    size_t nCurRow = maFields[nDim].maData.size() - 1;
-
-    while (maEmptyRows.size() <= nCurRow)
-        maEmptyRows.push_back(true);
-
-    if (!pData->IsEmpty())
-        maEmptyRows[nCurRow] = false;
-
-    return true;
-}
-
-const ScDPCache::GroupItems* ScDPCache::GetGroupItems(long nDim) const
-{
-    if (nDim < 0)
-        return NULL;
-
-    long nSourceCount = static_cast<long>(maFields.size());
-    if (nDim < nSourceCount)
-        return maFields[nDim].mpGroup.get();
-
-    nDim -= nSourceCount;
-    if (nDim < static_cast<long>(maGroupFields.size()))
-        return &maGroupFields[nDim];
-
-    return NULL;
-}
-
-rtl::OUString ScDPCache::GetDimensionName(LabelsType::size_type nDim) const
-{
-    OSL_ENSURE(nDim < maLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName");
-    OSL_ENSURE(maLabelNames.size() == static_cast <sal_uInt16> (mnColumnCount+1), "ScDPTableDataCache::GetDimensionName");
-
-    if ( nDim+1 < maLabelNames.size() )
-    {
-        return maLabelNames[nDim+1];
-    }
-    else
-        return rtl::OUString();
-}
-
-namespace {
-
-typedef boost::unordered_set<rtl::OUString, rtl::OUStringHash> LabelSet;
-
-class InsertLabel : public std::unary_function<rtl::OUString, void>
-{
-    LabelSet& mrNames;
-public:
-    InsertLabel(LabelSet& rNames) : mrNames(rNames) {}
-    void operator() (const rtl::OUString& r)
-    {
-        mrNames.insert(r);
-    }
-};
-
-}
-
-void ScDPCache::Clear()
-{
-    maFields.clear();
-    maLabelNames.clear();
-    maGroupFields.clear();
-    maEmptyRows.clear();
-}
-
-void ScDPCache::AddLabel(const rtl::OUString& rLabel)
-{
-    OSL_ENSURE( IsValid(), "  IsValid() == false " );
-
-    if ( maLabelNames.empty() )
-        maLabelNames.push_back(ScGlobal::GetRscString(STR_PIVOT_DATA));
-
-    //reset name if needed
-    LabelSet aExistingNames;
-    std::for_each(maLabelNames.begin(), maLabelNames.end(), InsertLabel(aExistingNames));
-    sal_Int32 nSuffix = 1;
-    rtl::OUString aNewName = rLabel;
-    while (true)
-    {
-        if (!aExistingNames.count(aNewName))
-        {
-            // unique name found!
-            maLabelNames.push_back(aNewName);
-            return;
-        }
-
-        // Name already exists.
-        rtl::OUStringBuffer aBuf(rLabel);
-        aBuf.append(++nSuffix);
-        aNewName = aBuf.makeStringAndClear();
-    }
-}
-
-SCROW ScDPCache::GetItemDataId(sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty) const
-{
-    OSL_ENSURE( IsValid(), "  IsValid() == false " );
-    OSL_ENSURE(nDim < mnColumnCount, "ScDPTableDataCache::GetItemDataId ");
-
-    const Field& rField = maFields[nDim];
-    if (bRepeatIfEmpty)
-    {
-        while (nRow > 0 && rField.maItems[rField.maData[nRow]].IsEmpty())
-            --nRow;
-    }
-
-    return rField.maData[nRow];
-}
-
-const ScDPItemData* ScDPCache::GetItemDataById(long nDim, SCROW nId) const
-{
-    if (nDim < 0 || nId < 0)
-        return NULL;
-
-    size_t nSourceCount = maFields.size();
-    size_t nDimPos = static_cast<size_t>(nDim);
-    size_t nItemId = static_cast<size_t>(nId);
-    if (nDimPos < nSourceCount)
-    {
-        // source field.
-        const Field& rField = maFields[nDimPos];
-        if (nItemId < rField.maItems.size())
-            return &rField.maItems[nItemId];
-
-        if (!rField.mpGroup)
-            return NULL;
-
-        nItemId -= rField.maItems.size();
-        const DataListType& rGI = rField.mpGroup->maItems;
-        if (nItemId >= rGI.size())
-            return NULL;
-
-        return &rGI[nItemId];
-    }
-
-    // Try group fields.
-    nDimPos -= nSourceCount;
-    if (nDimPos >= maGroupFields.size())
-        return NULL;
-
-    const DataListType& rGI = maGroupFields[nDimPos].maItems;
-    if (nItemId >= rGI.size())
-        return NULL;
-
-    return &rGI[nItemId];
-}
-
-SCROW ScDPCache::GetRowCount() const
-{
-    if (maFields.empty() || maFields[0].maData.empty())
-        return 0;
-
-    return maFields[0].maData.size();
-}
-
-const ScDPCache::DataListType& ScDPCache::GetDimMemberValues(SCCOL nDim) const
-{
-    OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," nDim < mnColumnCount ");
-    return maFields[nDim].maItems;
-}
-
-sal_uLong ScDPCache::GetNumberFormat( long nDim ) const
-{
-    if ( nDim >= mnColumnCount )
-        return 0;
-
-    const std::vector<sal_uLong>& rNumFormats = maFields[nDim].maNumFormats;
-    if (rNumFormats.empty())
-        return 0;
-
-    // TODO: Find a way to determine the dominant number format in presence of
-    // multiple number formats in the same field.
-    return *rNumFormats.begin();
-}
-
-bool ScDPCache::IsDateDimension( long nDim ) const
-{
-    if (nDim >= mnColumnCount)
-        return false;
-
-    SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
-    if (!pFormatter)
-        return false;
-
-    const std::vector<sal_uLong>& rNumFormats = maFields[nDim].maNumFormats;
-    if (rNumFormats.empty())
-        return false;
-
-    short eType = pFormatter->GetType(rNumFormats[0]);
-    return (eType == NUMBERFORMAT_DATE) || (eType == NUMBERFORMAT_DATETIME);
-}
-
-SCROW ScDPCache::GetDimMemberCount( SCCOL nDim ) const
-{
-    OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," ScDPTableDataCache::GetDimMemberCount : out of bound ");
-    return maFields[nDim].maItems.size();
-}
-
-SCCOL ScDPCache::GetDimensionIndex(const rtl::OUString& sName) const
-{
-    for (size_t i = 1; i < maLabelNames.size(); ++i)
-    {
-        if (maLabelNames[i].equals(sName))
-            return static_cast<SCCOL>(i-1);
-    }
-    return -1;
-}
-
-void ScDPCache::AddReference(ScDPObject* pObj) const
-{
-    maRefObjects.insert(pObj);
-}
-
-void ScDPCache::RemoveReference(ScDPObject* pObj) const
-{
-    if (mbDisposing)
-        // Object being deleted.
-        return;
-
-    maRefObjects.erase(pObj);
-    if (maRefObjects.empty())
-        mpDoc->GetDPCollection()->RemoveCache(this);
-}
-
-const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const
-{
-    return maRefObjects;
-}
-
-SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
-{
-    if (nDim < 0)
-        return -1;
-
-    if (nDim < mnColumnCount)
-    {
-        // source field.
-        const DataListType& rItems = maFields[nDim].maItems;
-        for (size_t i = 0, n = rItems.size(); i < n; ++i)
-        {
-            if (rItems[i] == rItem)
-                return i;
-        }
-
-        if (!maFields[nDim].mpGroup)
-            return -1;
-
-        // grouped source field.
-        const DataListType& rGI = maFields[nDim].mpGroup->maItems;
-        for (size_t i = 0, n = rGI.size(); i < n; ++i)
-        {
-            if (rGI[i] == rItem)
-                return rItems.size() + i;
-        }
-        return -1;
-    }
-
-    // group field.
-    nDim -= mnColumnCount;
-    if (static_cast<size_t>(nDim) < maGroupFields.size())
-    {
-        const DataListType& rGI = maGroupFields[nDim].maItems;
-        for (size_t i = 0, n = rGI.size(); i < n; ++i)
-        {
-            if (rGI[i] == rItem)
-                return i;
-        }
-    }
-
-    return -1;
-}
-
-rtl::OUString ScDPCache::GetFormattedString(long nDim, const ScDPItemData& rItem) const
-{
-    if (nDim < 0)
-        return rItem.GetString();
-
-    ScDPItemData::Type eType = rItem.GetType();
-    if (eType == ScDPItemData::Value)
-    {
-        // Format value using the stored number format.
-        sal_uLong nNumFormat = GetNumberFormat(nDim);
-        SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
-        if (pFormatter)
-        {
-            Color* pColor = NULL;
-            String aStr;
-            pFormatter->GetOutputString(rItem.GetValue(), nNumFormat, aStr, &pColor);
-            return aStr;
-        }
-    }
-
-    if (eType == ScDPItemData::GroupValue)
-    {
-        ScDPItemData::GroupValueAttr aAttr = rItem.GetGroupValue();
-        double fStart = 0.0, fEnd = 0.0;
-        const GroupItems* p = GetGroupItems(nDim);
-        if (p)
-        {
-            fStart = p->maInfo.mfStart;
-            fEnd = p->maInfo.mfEnd;
-        }
-        return ScDPUtil::getDateGroupName(
-            aAttr.mnGroupType, aAttr.mnValue, mpDoc->GetFormatTable(), fStart, fEnd);
-    }
-
-    if (eType == ScDPItemData::RangeStart)
-    {
-        double fVal = rItem.GetValue();
-        const GroupItems* p = GetGroupItems(nDim);
-        if (!p)
-            return rItem.GetString();
-
-        sal_Unicode cDecSep = ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0);
-        return ScDPUtil::getNumGroupName(fVal, p->maInfo, cDecSep, mpDoc->GetFormatTable());
-    }
-
-    return rItem.GetString();
-}
-
-long ScDPCache::AppendGroupField()
-{
-    maGroupFields.push_back(new GroupItems);
-    return static_cast<long>(maFields.size() + maGroupFields.size() - 1);
-}
-
-void ScDPCache::ResetGroupItems(long nDim, const ScDPNumGroupInfo& rNumInfo)
-{
-    if (nDim < 0)
-        return;
-
-    long nSourceCount = static_cast<long>(maFields.size());
-    if (nDim < nSourceCount)
-    {
-        maFields.at(nDim).mpGroup.reset(new GroupItems(rNumInfo));
-        return;
-    }
-
-    nDim -= nSourceCount;
-    if (nDim < static_cast<long>(maGroupFields.size()))
-    {
-        GroupItems& rGI = maGroupFields[nDim];
-        rGI.maItems.clear();
-        rGI.maInfo = rNumInfo;
-    }
-}
-
-SCROW ScDPCache::SetGroupItem(long nDim, const ScDPItemData& rData)
-{
-    if (nDim < 0)
-        return -1;
-
-    long nSourceCount = static_cast<long>(maFields.size());
-    if (nDim < nSourceCount)
-    {
-        GroupItems& rGI = *maFields.at(nDim).mpGroup;
-        rGI.maItems.push_back(new ScDPItemData(rData));
-        SCROW nId = maFields[nDim].maItems.size() + rGI.maItems.size() - 1;
-        return nId;
-    }
-
-    nDim -= nSourceCount;
-    if (nDim < static_cast<long>(maGroupFields.size()))
-    {
-        DataListType& rItems = maGroupFields.at(nDim).maItems;
-        rItems.push_back(new ScDPItemData(rData));
-        return rItems.size()-1;
-    }
-
-    return -1;
-}
-
-const ScDPCache::DataListType* ScDPCache::GetGroupDimMemberValues(long nDim) const
-{
-    if (nDim < 0)
-        return NULL;
-
-    long nSourceCount = static_cast<long>(maFields.size());
-    if (nDim < nSourceCount)
-    {
-        if (!maFields.at(nDim).mpGroup)
-            return NULL;
-
-        return &maFields[nDim].mpGroup->maItems;
-    }
-
-    nDim -= nSourceCount;
-    if (nDim < static_cast<long>(maGroupFields.size()))
-        return &maGroupFields.at(nDim).maItems;
-
-    return NULL;
-}
-
-void ScDPCache::GetGroupDimMemberIds(long nDim, std::vector<SCROW>& rIds) const
-{
-    if (nDim < 0)
-        return;
-
-    long nSourceCount = static_cast<long>(maFields.size());
-    if (nDim < nSourceCount)
-    {
-        if (!maFields.at(nDim).mpGroup)
-            return;
-
-        size_t nOffset = maFields[nDim].maItems.size();
-        const DataListType& rGI = maFields[nDim].mpGroup->maItems;
-        for (size_t i = 0, n = rGI.size(); i < n; ++i)
-            rIds.push_back(static_cast<SCROW>(i + nOffset));
-
-        return;
-    }
-
-    nDim -= nSourceCount;
-    if (nDim < static_cast<long>(maGroupFields.size()))
-    {
-        const DataListType& rGI = maGroupFields.at(nDim).maItems;
-        for (size_t i = 0, n = rGI.size(); i < n; ++i)
-            rIds.push_back(static_cast<SCROW>(i));
-    }
-}
-
-namespace {
-
-struct ClearGroupItems : std::unary_function<ScDPCache::Field, void>
-{
-    void operator() (ScDPCache::Field& r) const
-    {
-        r.mpGroup.reset();
-    }
-};
-
-}
-
-void ScDPCache::ClearGroupFields()
-{
-    maGroupFields.clear();
-    std::for_each(maFields.begin(), maFields.end(), ClearGroupItems());
-}
-
-SCROW ScDPCache::GetOrder(long nDim, SCROW nIndex) const
-{
-    OSL_ENSURE( IsValid(), "  IsValid() == false " );
-    OSL_ENSURE( nDim >=0 && nDim < mnColumnCount, "ScDPTableDataCache::GetOrder : out of bound" );
-
-    const Field& rField = maFields[nDim];
-    if (rField.maIndexOrder.size() !=  rField.maGlobalOrder.size())
-    { //not inited
-        SCROW nRow  = 0;
-        rField.maIndexOrder.resize(rField.maGlobalOrder.size(), 0);
-        for (size_t i = 0, n = rField.maGlobalOrder.size(); i < n; ++i)
-        {
-            nRow = rField.maGlobalOrder[i];
-            rField.maIndexOrder[nRow] = i;
-        }
-    }
-
-    OSL_ENSURE(nIndex >= 0 && sal::static_int_cast<sal_uInt32>(nIndex) < rField.maIndexOrder.size() , "ScDPTableDataCache::GetOrder");
-    return rField.maIndexOrder[nIndex];
-}
-
-ScDocument* ScDPCache::GetDoc() const
-{
-    return mpDoc;
-};
-
-long ScDPCache::GetColumnCount() const
-{
-    return mnColumnCount;
-}
-
-long ScDPCache::GetGroupFieldCount() const
-{
-    return maGroupFields.size();
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list