ooo-build r15085 - in branches/ooo-build-3-0-1: . patches/dev300
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r15085 - in branches/ooo-build-3-0-1: . patches/dev300
- Date: Thu, 15 Jan 2009 21:29:27 +0000 (UTC)
Author: kyoshida
Date: Thu Jan 15 21:29:26 2009
New Revision: 15085
URL: http://svn.gnome.org/viewvc/ooo-build?rev=15085&view=rev
Log:
2009-01-15 Kohei Yoshida <kyoshida novell com>
* patches/dev300/calc-dp-drilldown-hidden-items.diff:
* patches/dev300/apply: ported from opensuse-11-1 branch.
Added:
branches/ooo-build-3-0-1/patches/dev300/calc-dp-drilldown-hidden-items.diff
Modified:
branches/ooo-build-3-0-1/ChangeLog
branches/ooo-build-3-0-1/patches/dev300/apply
Modified: branches/ooo-build-3-0-1/patches/dev300/apply
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/apply (original)
+++ branches/ooo-build-3-0-1/patches/dev300/apply Thu Jan 15 21:29:26 2009
@@ -1813,6 +1813,10 @@
# strip the fraction part of a date-time value when using DATEVALUE.
calc-formula-datevalue-strip-time.diff, i#94765, kohei
+# correctly evaluate the visibility of dimension members when generating a
+# drill-down sheet & also reduce memory use on cache tables.
+calc-dp-drilldown-hidden-items.diff i#93918, i#93998, kohei
+
[ CalcExperimental ]
# Implement external range names.
Added: branches/ooo-build-3-0-1/patches/dev300/calc-dp-drilldown-hidden-items.diff
==============================================================================
--- (empty file)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-dp-drilldown-hidden-items.diff Thu Jan 15 21:29:26 2009
@@ -0,0 +1,1604 @@
+diff --git sc/inc/dpcachetable.hxx sc/inc/dpcachetable.hxx
+index e894eed..deaa0f2 100644
+--- sc/inc/dpcachetable.hxx
++++ sc/inc/dpcachetable.hxx
+@@ -38,8 +38,8 @@
+ #include "collect.hxx"
+
+ #include <vector>
+-#include <set>
+ #include <hash_map>
++#include <hash_set>
+ #include <boost/shared_ptr.hpp>
+ #include <com/sun/star/uno/Reference.hxx>
+
+@@ -57,62 +57,24 @@ class Date;
+ class ScDocument;
+ class ScRange;
+ class ScDPDimension;
++class ScDPCollection;
++class ScDPCacheCell;
+ struct ScDPItemData;
+ class Date;
+
+ // ----------------------------------------------------------------------------
+
+-/** public interface for string-sharing */
+-class ScSharedString
+-{
+-public:
+- static const sal_Int32 EMPTY = 0;
+-
+- static const String* getString(sal_Int32 nId);
+- static sal_Int32 getStringId(const String& aStr);
+- static sal_Int32 insertString(const String& aStr);
+-
+-private:
+-
+- /** internal shared string table implementation */
+- class StringTable
+- {
+- public:
+- sal_Int32 insertString(const String& aStr);
+- sal_Int32 getStringId(const String& aStr);
+- const String* getString(sal_Int32 nId) const;
+-
+- StringTable();
+- ~StringTable();
+-
+- private:
+- typedef ::std::hash_map< String, sal_Int32, ScStringHashCode, ::std::equal_to< String > > SharedStrMap;
+-
+- ::std::vector<String> maSharedStrings;
+- SharedStrMap maSharedStringIds;
+- sal_Int32 mnStrCount;
+- };
+-
+- static ::osl::Mutex maStrMutex;
+- static StringTable maStringTable;
+-};
+-
+-// ----------------------------------------------------------------------------
+-
+ class ScDPCacheTable
+ {
+ public:
+
+- /** individual cell within table. */
+ struct Cell
+ {
+- SCROW mnCategoryRef;
+- sal_Int32 mnStrId;
+- sal_uInt8 mnType;
+- double mfValue;
+- bool mbNumeric;
++ SCROW mnCategoryRef;
++ ScDPCacheCell* mpContent;
+
+ Cell();
++ ~Cell();
+ };
+
+ /** individual filter item used in SingleFilter and GroupFilter. */
+@@ -131,38 +93,47 @@ public:
+ public:
+ /** returns true if the matching condition is met for a single cell
+ value, or false otherwise. */
+- virtual bool match(const Cell& rCell) const = 0;
++ virtual bool match(const ScDPCacheCell& rCell) const = 0;
+ };
+
+ /** ordinary single-item filter. */
+ class SingleFilter : public FilterBase
+ {
+ public:
+- explicit SingleFilter();
+- explicit SingleFilter(sal_Int32 nMatchStrId, double fValue, bool bHasValue);
++ explicit SingleFilter(ScSimpleSharedString& rSharedString,
++ sal_Int32 nMatchStrId, double fValue, bool bHasValue);
+
+- virtual bool match(const Cell& rCell) const;
++ virtual bool match(const ScDPCacheCell& rCell) const;
+
+- const String getMatchString() const;
++ const String getMatchString();
+ double getMatchValue() const;
+ bool hasValue() const;
+
+ private:
++ explicit SingleFilter();
++
+ FilterItem maItem;
++ ScSimpleSharedString mrSharedString;
+ };
+
+ /** multi-item (group) filter. */
+ class GroupFilter : public FilterBase
+ {
+ public:
+- GroupFilter();
++ GroupFilter(ScSimpleSharedString& rSharedString);
+ virtual ~GroupFilter(){}
+- virtual bool match(const Cell& rCell) const;
++ virtual bool match(const ScDPCacheCell& rCell) const;
+
++ void setMatchIfFound(bool b);
+ void addMatchItem(const String& rStr, double fVal, bool bHasValue);
++ size_t getMatchItemCount() const;
+
+ private:
++ GroupFilter();
++
+ ::std::vector<FilterItem> maItems;
++ ScSimpleSharedString mrSharedString;
++ bool mbMatchIfFound;
+ };
+
+ /** single filtering criterion. */
+@@ -174,7 +145,7 @@ public:
+ Criterion();
+ };
+
+- ScDPCacheTable();
++ ScDPCacheTable(ScDPCollection* pCollection);
+ ~ScDPCacheTable();
+
+ sal_Int32 getHeaderSize() const;
+@@ -203,7 +174,7 @@ public:
+ /** Get the cell instance at specified location within the data grid. Note
+ that the data grid doesn't include the header row. Don't delete the
+ returned object! */
+- const ::ScDPCacheTable::Cell* getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty = false) const;
++ const ScDPCacheCell* getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty = false) const;
+
+ const String* getFieldName(sal_Int32 nIndex) const;
+
+@@ -229,12 +200,14 @@ public:
+ bool empty() const;
+
+ private:
++ ScDPCacheTable();
++ ScDPCacheTable(const ScDPCacheTable&);
++
+ /**
+ * Check if a given row meets all specified criteria.
+ */
+ bool isRowQualified(sal_Int32 nRow, const ::std::vector<Criterion>& rCriteria, bool bRepeatIfEmpty) const;
+- void getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell& rCell);
+- ScDPCacheTable::Cell getSelectedDimension(ScDPDimension* pDim) const;
++ void getValueData(ScDocument* pDoc, const ScAddress& rPos, ScDPCacheCell& rCell);
+
+ private:
+ typedef ::boost::shared_ptr<TypedStrCollection> TypedStrCollectionPtr;
+@@ -251,6 +224,9 @@ private:
+ /** used to track visibility of rows. The first row below the header row
+ has the index of 0. */
+ ::std::vector<bool> maRowsVisible;
++
++ ScSimpleSharedString& mrSharedString;
++ ScDPCollection* mpCollection;
+ };
+
+
+diff --git sc/inc/dpgroup.hxx sc/inc/dpgroup.hxx
+index 391f5fb..1749a1a 100644
+--- sc/inc/dpgroup.hxx
++++ sc/inc/dpgroup.hxx
+@@ -196,7 +196,7 @@ class ScDPGroupTableData : public ScDPTableData
+ void GetNumGroupInfo( long nDimension, ScDPNumGroupInfo& rInfo,
+ bool& rNonInteger, sal_Unicode& rDecimal );
+
+- void ModifyFilterCriteria(::std::vector<ScDPCacheTable::Criterion>& rCriteria) const;
++ void ModifyFilterCriteria(::std::vector<ScDPCacheTable::Criterion>& rCriteria);
+
+ public:
+ // takes ownership of pSource
+diff --git sc/inc/dpobject.hxx sc/inc/dpobject.hxx
+index fb62f81..6a2978b 100644
+--- sc/inc/dpobject.hxx
++++ sc/inc/dpobject.hxx
+@@ -250,11 +250,39 @@ public:
+ PivotField* pRefPageFields = NULL, SCSIZE nRefPageCount = 0 );
+ };
+
++// ============================================================================
++
++struct ScDPCacheCell
++{
++ sal_Int32 mnStrId;
++ sal_uInt8 mnType;
++ double mfValue;
++ bool mbNumeric;
++
++ ScDPCacheCell();
++ ScDPCacheCell(const ScDPCacheCell& r);
++ ~ScDPCacheCell();
++};
++
++// ============================================================================
+
+ class ScDPCollection : public Collection
+ {
+ private:
+ ScDocument* pDoc;
++ ScSimpleSharedString maSharedString;
++
++ struct CacheCellHash
++ {
++ size_t operator()(const ScDPCacheCell* pCell) const;
++ };
++ struct CacheCellEqual
++ {
++ bool operator()(const ScDPCacheCell* p1, const ScDPCacheCell* p2) const;
++ };
++ typedef ::std::hash_set<ScDPCacheCell*, CacheCellHash, CacheCellEqual> CacheCellPoolType;
++
++ CacheCellPoolType maCacheCellPool;
+
+ public:
+ ScDPCollection(ScDocument* pDocument);
+@@ -279,7 +307,12 @@ public:
+ void WriteRefsTo( ScDPCollection& r ) const;
+
+ String CreateNewName( USHORT nMin = 1 ) const;
+- void EnsureNames();
++ void EnsureNames();
++
++ ScSimpleSharedString& GetSharedString();
++
++ ScDPCacheCell* getCacheCellFromPool(const ScDPCacheCell& rCell);
++ void clearCacheCellPool();
+ };
+
+
+diff --git sc/inc/dpsdbtab.hxx sc/inc/dpsdbtab.hxx
+index c007658..788ad86 100644
+--- sc/inc/dpsdbtab.hxx
++++ sc/inc/dpsdbtab.hxx
+@@ -44,6 +44,7 @@ namespace com { namespace sun { namespace star {
+ #include <set>
+
+ class ScDPCacheTable;
++class ScDocument;
+
+ // --------------------------------------------------------------------
+ //
+@@ -75,6 +76,7 @@ private:
+
+ public:
+ ScDatabaseDPData(
++ ScDocument* pDoc,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory > xSMgr,
+ const ScImportSourceDesc& rImport );
+diff --git sc/inc/dptabdat.hxx sc/inc/dptabdat.hxx
+index acb8ce0..4946df3 100644
+--- sc/inc/dptabdat.hxx
++++ sc/inc/dptabdat.hxx
+@@ -46,6 +46,7 @@ namespace com { namespace sun { namespace star { namespace sheet {
+ }}}}
+
+ class TypedStrCollection;
++class ScSimpleSharedString;
+
+ // -----------------------------------------------------------------------
+
+@@ -112,6 +113,7 @@ class ScDPDimension;
+ class ScDPLevel;
+ class ScDPInitState;
+ class ScDPResultMember;
++class ScDocument;
+
+ class ScDPTableData
+ {
+@@ -120,6 +122,7 @@ class ScDPTableData
+ long nLastHier;
+ long nLastLevel;
+ long nLastRet;
++ ScSimpleSharedString& mrSharedString;
+
+ public:
+
+@@ -146,7 +149,7 @@ public:
+ CalcInfo();
+ };
+
+- ScDPTableData();
++ ScDPTableData(ScDocument* pDoc);
+ virtual ~ScDPTableData();
+
+ long GetDatePart( long nDateVal, long nHierarchy, long nLevel );
+@@ -165,11 +168,11 @@ public:
+
+ virtual bool IsRepeatIfEmpty();
+
+- virtual void CreateCacheTable();
+- virtual void FilterCacheTable(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria);
++ virtual void CreateCacheTable() = 0;
++ virtual void FilterCacheTable(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria) = 0;
+ virtual void GetDrillDownData(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria,
+- ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
+- virtual void CalcResults(CalcInfo& rInfo, bool bAutoShow);
++ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData) = 0;
++ virtual void CalcResults(CalcInfo& rInfo, bool bAutoShow) = 0;
+ virtual const ScDPCacheTable& GetCacheTable() const = 0;
+
+ // overloaded in ScDPGroupTableData:
+@@ -181,6 +184,8 @@ public:
+ virtual BOOL HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex,
+ const ScDPItemData& rSecondData, long nSecondIndex ) const;
+
++ ScSimpleSharedString& GetSharedString();
++
+ protected:
+ /** This structure stores vector arrays that hold intermediate data for
+ each row during cache table iteration. */
+diff --git sc/inc/dptabres.hxx sc/inc/dptabres.hxx
+index dbe1b35..3fb5ef8 100644
+--- sc/inc/dptabres.hxx
++++ sc/inc/dptabres.hxx
+@@ -31,14 +31,15 @@
+ #ifndef SC_DPTABRES_HXX
+ #define SC_DPTABRES_HXX
+
+-#include <vector>
+ #include <svtools/svarray.hxx>
+ #include <tools/string.hxx>
+ #include <com/sun/star/sheet/MemberResult.hpp>
+ #include <com/sun/star/sheet/DataResult.hpp>
+ #include <com/sun/star/uno/Sequence.hxx>
+ #include "global.hxx" // enum ScSubTotalFunc
++#include "dpcachetable.hxx"
+ #include <hash_map>
++#include <hash_set>
+ #include <vector>
+
+ namespace com { namespace sun { namespace star { namespace sheet {
+@@ -50,10 +51,12 @@ class ScAddress;
+ class ScDocument;
+ class ScDPSource;
+ class ScDPDimension;
++class ScDPDimensions;
+ class ScDPLevel;
+ class ScDPMember;
+ class ScDPAggData;
+ class ScDPResultMember;
++class ScDPResultVisibilityData;
+
+ struct ScDPValueData;
+ struct ScDPItemData;
+@@ -370,6 +373,8 @@ public:
+ const ScDPLevel* GetParentLevel() const { return pParentLevel; } //! Ref
+
+ ScDPAggData* GetColTotal( long nMeasure ) const;
++
++ void FillVisibilityData(ScDPResultVisibilityData& rData) const;
+ };
+
+ class ScDPDataMember
+@@ -538,6 +543,8 @@ public:
+ long GetAutoCount() const { return nAutoCount; }
+
+ ScDPResultDimension* GetFirstChildDimension() const;
++
++ void FillVisibilityData(ScDPResultVisibilityData& rData) const;
+ };
+
+ class ScDPDataDimension
+@@ -580,5 +587,33 @@ public:
+ ScDPDataMember* GetMember(long n) const;
+ };
+
++// ----------------------------------------------------------------------------
++
++/**
++ * This class collects visible members of each dimension and uses that
++ * information to create filtering criteria (e.g. for drill-down data).
++ */
++class ScDPResultVisibilityData
++{
++public:
++ ScDPResultVisibilityData(ScSimpleSharedString& rSharedString, ScDPSource* pSource);
++ ~ScDPResultVisibilityData();
++
++ void addVisibleMember(const String& rDimName, const ScDPItemData& rMemberItem);
++ void fillFieldFilters(::std::vector<ScDPCacheTable::Criterion>& rFilters) const;
++
++private:
++ struct MemberHash
++ {
++ size_t operator()(const ScDPItemData& r) const;
++ };
++ typedef ::std::hash_set<ScDPItemData, MemberHash> VisibleMemberType;
++ typedef ::std::hash_map<String, VisibleMemberType, ScStringHashCode> DimMemberType;
++ DimMemberType maDimensions;
++
++ ScSimpleSharedString& mrSharedString;
++ ScDPSource* mpSource;
++};
++
+ #endif
+
+diff --git sc/inc/global.hxx sc/inc/global.hxx
+index 7cd5b8b..f239322 100644
+--- sc/inc/global.hxx
++++ sc/inc/global.hxx
+@@ -38,6 +38,8 @@
+ #include <com/sun/star/uno/Reference.hxx>
+ #include "scdllapi.h"
+
++#include <hash_map>
++
+ class ImageList;
+ class Bitmap;
+ class SfxItemSet;
+@@ -895,6 +897,46 @@ struct ScConsolidateParam
+ };
+
+ // -----------------------------------------------------------------------
++
++class ScSimpleSharedString
++{
++public:
++ static const sal_Int32 EMPTY = 0;
++
++ ScSimpleSharedString();
++ ScSimpleSharedString(const ScSimpleSharedString& r);
++ ~ScSimpleSharedString();
++
++ const String* getString(sal_Int32 nId);
++ sal_Int32 getStringId(const String& aStr);
++ sal_Int32 insertString(const String& aStr);
++
++private:
++
++ /** internal shared string table implementation */
++ class StringTable
++ {
++ public:
++ sal_Int32 insertString(const String& aStr);
++ sal_Int32 getStringId(const String& aStr);
++ const String* getString(sal_Int32 nId) const;
++
++ StringTable();
++ StringTable(const StringTable& r);
++ ~StringTable();
++
++ private:
++ typedef ::std::hash_map< String, sal_Int32, ScStringHashCode, ::std::equal_to< String > > SharedStrMap;
++
++ ::std::vector<String> maSharedStrings;
++ SharedStrMap maSharedStringIds;
++ sal_Int32 mnStrCount;
++ };
++
++ StringTable maStringTable;
++};
++
++// -----------------------------------------------------------------------
+ extern ::utl::TransliterationWrapper* GetScGlobalpTransliteration();//CHINA001
+ extern const LocaleDataWrapper* GetScGlobalpLocaleData();
+
+diff --git sc/source/core/data/dpcachetable.cxx sc/source/core/data/dpcachetable.cxx
+index 1be291c..07a54f3 100644
+--- sc/source/core/data/dpcachetable.cxx
++++ sc/source/core/data/dpcachetable.cxx
+@@ -37,8 +37,7 @@
+ #include "cell.hxx"
+ #include "dptabdat.hxx"
+ #include "dptabsrc.hxx"
+-
+-#include <stdio.h>
++#include "dpobject.hxx"
+
+ #include <com/sun/star/i18n/LocaleDataItem.hpp>
+ #include <com/sun/star/sdbc/DataType.hpp>
+@@ -56,7 +55,7 @@ using namespace ::com::sun::star;
+
+ using ::rtl::OUString;
+ using ::std::vector;
+-using ::std::set;
++using ::std::pair;
+ using ::std::hash_map;
+ using ::std::auto_ptr;
+ using ::com::sun::star::i18n::LocaleDataItem;
+@@ -76,94 +75,26 @@ static BOOL lcl_HasQueryEntry( const ScQueryParam& rParam )
+ rParam.GetEntry(0).bDoQuery;
+ }
+
+-ScSharedString::StringTable::StringTable() :
+- mnStrCount(0)
+-{
+- // empty string (ID = 0)
+- maSharedStrings.push_back(String());
+- maSharedStringIds.insert( SharedStrMap::value_type(String(), mnStrCount++) );
+-}
+-
+-ScSharedString::StringTable::~StringTable()
+-{
+-}
+-
+-sal_Int32 ScSharedString::StringTable::insertString(const String& aStr)
+-{
+- SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
+- itrEnd = maSharedStringIds.end();
+-
+- if (itr == itrEnd)
+- {
+- // new string.
+- maSharedStrings.push_back(aStr);
+- maSharedStringIds.insert( SharedStrMap::value_type(aStr, mnStrCount) );
+- return mnStrCount++;
+- }
+-
+- // existing string.
+- return itr->second;
+-}
+-
+-sal_Int32 ScSharedString::StringTable::getStringId(const String& aStr)
+-{
+- SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
+- itrEnd = maSharedStringIds.end();
+- if (itr == itrEnd)
+- {
+- // string not found.
+- return insertString(aStr);
+- }
+- return itr->second;
+-}
+-
+-const String* ScSharedString::StringTable::getString(sal_Int32 nId) const
+-{
+- if (nId >= mnStrCount)
+- return NULL;
+-
+- return &maSharedStrings[nId];
+-}
+-
+ // ----------------------------------------------------------------------------
+
+-// static
+-::osl::Mutex ScSharedString::maStrMutex;
+-ScSharedString::StringTable ScSharedString::maStringTable;
+-
+-sal_Int32 ScSharedString::insertString(const String& aStr)
+-{
+- ::osl::MutexGuard aGuard(maStrMutex);
+- return maStringTable.insertString(aStr);
+-}
+-
+-const String* ScSharedString::getString(sal_Int32 nId)
+-{
+- ::osl::MutexGuard aGuard(maStrMutex);
+- return maStringTable.getString(nId);
+-}
+-
+-sal_Int32 ScSharedString::getStringId(const String& aStr)
+-{
+- ::osl::MutexGuard aGuard(maStrMutex);
+- return maStringTable.getStringId(aStr);
+-}
++static ScDPCacheCell EmptyCellContent = ScDPCacheCell();
+
+ // ----------------------------------------------------------------------------
+
+ ScDPCacheTable::Cell::Cell() :
+ mnCategoryRef(0),
+- mnStrId(ScSharedString::EMPTY),
+- mnType(SC_VALTYPE_EMPTY),
+- mfValue(0.0),
+- mbNumeric(false)
++ mpContent(NULL)
++{
++}
++
++ScDPCacheTable::Cell::~Cell()
+ {
+ }
+
+ // ----------------------------------------------------------------------------
+
+ ScDPCacheTable::FilterItem::FilterItem() :
+- mnMatchStrId(ScSharedString::EMPTY),
++ mnMatchStrId(ScSimpleSharedString::EMPTY),
+ mfValue(0.0),
+ mbHasValue(false)
+ {
+@@ -171,18 +102,16 @@ ScDPCacheTable::FilterItem::FilterItem() :
+
+ // ----------------------------------------------------------------------------
+
+-ScDPCacheTable::SingleFilter::SingleFilter()
+-{
+-}
+-
+-ScDPCacheTable::SingleFilter::SingleFilter(sal_Int32 nMatchStrId, double fValue, bool bHasValue)
++ScDPCacheTable::SingleFilter::SingleFilter(ScSimpleSharedString& rSharedString,
++ sal_Int32 nMatchStrId, double fValue, bool bHasValue) :
++ mrSharedString(rSharedString)
+ {
+ maItem.mnMatchStrId = nMatchStrId;
+ maItem.mfValue = fValue;
+ maItem.mbHasValue = bHasValue;
+ }
+
+-bool ScDPCacheTable::SingleFilter::match(const Cell& rCell) const
++bool ScDPCacheTable::SingleFilter::match(const ScDPCacheCell& rCell) const
+ {
+ if (rCell.mnStrId != maItem.mnMatchStrId &&
+ (!rCell.mbNumeric || rCell.mfValue != maItem.mfValue))
+@@ -191,9 +120,9 @@ bool ScDPCacheTable::SingleFilter::match(const Cell& rCell) const
+ return true;
+ }
+
+-const String ScDPCacheTable::SingleFilter::getMatchString() const
++const String ScDPCacheTable::SingleFilter::getMatchString()
+ {
+- const String* pStr = ScSharedString::getString(maItem.mnMatchStrId);
++ const String* pStr = mrSharedString.getString(maItem.mnMatchStrId);
+ if (pStr)
+ return *pStr;
+
+@@ -212,11 +141,13 @@ bool ScDPCacheTable::SingleFilter::hasValue() const
+
+ // ----------------------------------------------------------------------------
+
+-ScDPCacheTable::GroupFilter::GroupFilter()
++ScDPCacheTable::GroupFilter::GroupFilter(ScSimpleSharedString& rSharedString) :
++ mrSharedString(rSharedString),
++ mbMatchIfFound(true)
+ {
+ }
+
+-bool ScDPCacheTable::GroupFilter::match(const Cell& rCell) const
++bool ScDPCacheTable::GroupFilter::match(const ScDPCacheCell& rCell) const
+ {
+ vector<FilterItem>::const_iterator itrEnd = maItems.end();
+ for (vector<FilterItem>::const_iterator itr = maItems.begin(); itr != itrEnd; ++itr)
+@@ -228,14 +159,19 @@ bool ScDPCacheTable::GroupFilter::match(const Cell& rCell) const
+ bMatch = (itr->mnMatchStrId == rCell.mnStrId);
+
+ if (bMatch)
+- return true;
++ return mbMatchIfFound ? true : false;
+ }
+- return false;
++ return mbMatchIfFound ? false : true;
++}
++
++void ScDPCacheTable::GroupFilter::setMatchIfFound(bool b)
++{
++ mbMatchIfFound = b;
+ }
+
+ void ScDPCacheTable::GroupFilter::addMatchItem(const String& rStr, double fVal, bool bHasValue)
+ {
+- sal_Int32 nStrId = ScSharedString::getStringId(rStr);
++ sal_Int32 nStrId = mrSharedString.getStringId(rStr);
+ FilterItem aItem;
+ aItem.mnMatchStrId = nStrId;
+ aItem.mfValue = fVal;
+@@ -243,6 +179,11 @@ void ScDPCacheTable::GroupFilter::addMatchItem(const String& rStr, double fVal,
+ maItems.push_back(aItem);
+ }
+
++size_t ScDPCacheTable::GroupFilter::getMatchItemCount() const
++{
++ return maItems.size();
++}
++
+ // ----------------------------------------------------------------------------
+
+ ScDPCacheTable::Criterion::Criterion() :
+@@ -253,7 +194,9 @@ ScDPCacheTable::Criterion::Criterion() :
+
+ // ----------------------------------------------------------------------------
+
+-ScDPCacheTable::ScDPCacheTable()
++ScDPCacheTable::ScDPCacheTable(ScDPCollection* pCollection) :
++ mrSharedString(pCollection->GetSharedString()),
++ mpCollection(pCollection)
+ {
+ }
+
+@@ -300,7 +243,7 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc
+ {
+ String aStr;
+ pDoc->GetString(nCol + nStartCol, nStartRow, nTab, aStr);
+- sal_Int32 nStrId = ScSharedString::insertString(aStr);
++ sal_Int32 nStrId = mrSharedString.insertString(aStr);
+ maHeader.push_back(nStrId);
+ }
+
+@@ -339,24 +282,28 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc
+ Cell& rCell = maTable.back().back();
+ rCell.mnCategoryRef = maTable.size()-1;
+
+- if (nRow == 0 || pDoc->HasData(nStartCol + nCol, nStartRow + nRow, nTab))
++ String aCellStr;
++ bool bReadCell = nRow == 0 || pDoc->HasData(nStartCol + nCol, nStartRow + nRow, nTab);
++ if (bReadCell)
++ {
+ aLastNonEmptyRows[nCol] = maTable.size()-1;
++ ScDPCacheCell aCell;
++ pDoc->GetString(nStartCol + nCol, nStartRow + nRow, nTab, aCellStr);
++ aCell.mnStrId = mrSharedString.insertString(aCellStr);
++ aCell.mnType = SC_VALTYPE_STRING;
++ aCell.mbNumeric = false;
++ ScAddress aPos(nStartCol + nCol, nStartRow + nRow, nTab);
++ getValueData(pDoc, aPos, aCell);
++ rCell.mpContent = mpCollection->getCacheCellFromPool(aCell);
++ }
+ else
+ rCell.mnCategoryRef = aLastNonEmptyRows[nCol];
+
+- String aStr;
+- pDoc->GetString(nStartCol + nCol, nStartRow + nRow, nTab, aStr);
+- rCell.mnStrId = ScSharedString::insertString(aStr);
+- rCell.mnType = SC_VALTYPE_STRING;
+- rCell.mbNumeric = false;
+- ScAddress aPos(nStartCol + nCol, nStartRow + nRow, nTab);
+- getValueData(pDoc, aPos, rCell);
+-
+ TypedStrData* pNew;
+- if (rCell.mbNumeric)
+- pNew = new TypedStrData(aStr, rCell.mfValue, SC_STRTYPE_VALUE);
++ if (rCell.mpContent && rCell.mpContent->mbNumeric)
++ pNew = new TypedStrData(aCellStr, rCell.mpContent->mfValue, SC_STRTYPE_VALUE);
+ else
+- pNew = new TypedStrData(aStr);
++ pNew = new TypedStrData(aCellStr);
+
+ if (!maFieldEntries[nCol]->Insert(pNew))
+ delete pNew;
+@@ -365,14 +312,15 @@ void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const Sc
+ }
+
+ void lcl_GetCellValue(const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol,
+- const Date& rNullDate, ScDPCacheTable::Cell& rCell, String& rStr)
++ const Date& rNullDate, ScDPCacheCell& rCell, String& rStr,
++ ScSimpleSharedString& rSharedString)
+ {
+ short nNumType = NUMBERFORMAT_NUMBER;
+ BOOL bEmptyFlag = FALSE;
+ try
+ {
+ rStr = xRow->getString(nCol);
+- rCell.mnStrId = ScSharedString::getStringId(rStr);
++ rCell.mnStrId = rSharedString.getStringId(rStr);
+ rCell.mnType = SC_VALTYPE_STRING;
+
+ switch (nType)
+@@ -487,7 +435,7 @@ void ScDPCacheTable::fillTable(const Reference<sdbc::XRowSet>& xRowSet, const Da
+ {
+ String aColTitle = xMeta->getColumnLabel(nCol+1);
+ aColTypes[nCol] = xMeta->getColumnType(nCol+1);
+- maHeader.push_back( ScSharedString::getStringId(aColTitle) );
++ maHeader.push_back( mrSharedString.getStringId(aColTitle) );
+ }
+
+ // Initialize field entries container.
+@@ -513,12 +461,14 @@ void ScDPCacheTable::fillTable(const Reference<sdbc::XRowSet>& xRowSet, const Da
+ {
+ maTable.back().push_back( Cell() );
+ Cell& rCell = maTable.back().back();
++ ScDPCacheCell aCellContent;
+ String aStr;
+- lcl_GetCellValue(xRow, aColTypes[nCol], nCol+1, rNullDate, rCell, aStr);
++ lcl_GetCellValue(xRow, aColTypes[nCol], nCol+1, rNullDate, aCellContent, aStr, mrSharedString);
++ rCell.mpContent = mpCollection->getCacheCellFromPool(aCellContent);
+
+ TypedStrData* pNew;
+- if (rCell.mbNumeric)
+- pNew = new TypedStrData(aStr, rCell.mfValue, SC_STRTYPE_VALUE);
++ if (rCell.mpContent->mbNumeric)
++ pNew = new TypedStrData(aStr, rCell.mpContent->mfValue, SC_STRTYPE_VALUE);
+ else
+ pNew = new TypedStrData(aStr);
+
+@@ -557,20 +507,21 @@ void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, b
+ maRowsVisible[nRow] = isRowQualified(nRow, rCriteria, bRepeatIfEmpty);
+ }
+
+-const ::ScDPCacheTable::Cell* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
++const ScDPCacheCell* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const
+ {
+ if ( nRow >= static_cast<SCROW>(maTable.size()) )
+ return NULL;
+
+- const vector<Cell>& rRow = maTable.at(nRow);
++ const vector<Cell>& rRow = maTable[nRow];
+ if ( nCol < 0 || static_cast<size_t>(nCol) >= rRow.size() )
+ return NULL;
+
+- const Cell* pCell = &rRow.at(nCol);
+- if (bRepeatIfEmpty && pCell && pCell->mnType == SC_VALTYPE_EMPTY)
+- pCell = getCell(nCol, pCell->mnCategoryRef, false);
++ const Cell& rCell = rRow[nCol];
++ const ScDPCacheCell* pCell = rCell.mpContent;
++ if (bRepeatIfEmpty && !pCell)
++ pCell = getCell(nCol, rCell.mnCategoryRef, false);
+
+- return pCell;
++ return pCell ? pCell : &EmptyCellContent;
+ }
+
+ const String* ScDPCacheTable::getFieldName(sal_Int32 nIndex) const
+@@ -578,12 +529,12 @@ const String* ScDPCacheTable::getFieldName(sal_Int32 nIndex) const
+ if (nIndex >= static_cast<sal_Int32>(maHeader.size()))
+ return NULL;
+
+- return ScSharedString::getString(maHeader[nIndex]);
++ return mrSharedString.getString(maHeader[nIndex]);
+ }
+
+ sal_Int32 ScDPCacheTable::getFieldIndex(const String& rStr) const
+ {
+- sal_Int32 nStrId = ScSharedString::getStringId(rStr);
++ sal_Int32 nStrId = mrSharedString.getStringId(rStr);
+ if (nStrId < 0)
+ // string not found.
+ return nStrId;
+@@ -628,7 +579,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
+ for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol)
+ {
+ OUString str;
+- const String* pStr = ScSharedString::getString(maHeader[nCol]);
++ const String* pStr = mrSharedString.getString(maHeader[nCol]);
+ if (pStr)
+ str = *pStr;
+
+@@ -654,7 +605,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
+ for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
+ {
+ Any any;
+- const Cell* pCell = getCell(nCol, nRow, bRepeatIfEmpty);
++ const ScDPCacheCell* pCell = getCell(nCol, nRow, bRepeatIfEmpty);
+ if (!pCell)
+ {
+ // This should never happen, but in case this happens, just
+@@ -670,7 +621,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S
+ else
+ {
+ OUString str;
+- const String* pStr = ScSharedString::getString(pCell->mnStrId);
++ const String* pStr = mrSharedString.getString(pCell->mnStrId);
+ if (pStr)
+ str = *pStr;
+ any <<= str;
+@@ -719,7 +670,7 @@ bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCr
+ // use this criterion.
+ continue;
+
+- const Cell* pCell = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty);
++ const ScDPCacheCell* pCell = getCell(static_cast<SCCOL>(itr->mnFieldIndex), nRow, bRepeatIfEmpty);
+ if (!pCell)
+ // This should never happen, but just in case...
+ return false;
+@@ -730,7 +681,7 @@ bool ScDPCacheTable::isRowQualified(sal_Int32 nRow, const vector<Criterion>& rCr
+ return true;
+ }
+
+-void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell& rCell)
++void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, ScDPCacheCell& rCell)
+ {
+ ScBaseCell* pCell = pDoc->GetCell(rPos);
+ if (!pCell)
+@@ -768,12 +719,3 @@ void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell&
+ }
+ }
+
+-ScDPCacheTable::Cell ScDPCacheTable::getSelectedDimension(ScDPDimension* pDim) const
+-{
+- const ScDPItemData& rData = pDim->GetSelectedData();
+- Cell aCell;
+- aCell.mfValue = rData.fValue;
+- aCell.mbNumeric = rData.bHasValue;
+- aCell.mnStrId = ScSharedString::getStringId(rData.aString);
+- return aCell;
+-}
+diff --git sc/source/core/data/dpgroup.cxx sc/source/core/data/dpgroup.cxx
+index 5cc1893..2c60d1b 100644
+--- sc/source/core/data/dpgroup.cxx
++++ sc/source/core/data/dpgroup.cxx
+@@ -49,6 +49,7 @@
+ #include "dpcachetable.hxx"
+ #include "dptabsrc.hxx"
+ #include "dptabres.hxx"
++#include "dpobject.hxx"
+
+ #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+@@ -86,7 +87,7 @@ public:
+ ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart,
+ const Date* pNullDate, const ScDPNumGroupInfo* pNumInfo);
+
+- virtual bool match(const ScDPCacheTable::Cell &rCell) const;
++ virtual bool match(const ScDPCacheCell &rCell) const;
+
+ private:
+ ScDPGroupDateFilter(); // disabled
+@@ -110,7 +111,7 @@ ScDPGroupDateFilter::ScDPGroupDateFilter(double fMatchValue, sal_Int32 nDatePart
+ // mfMatchValue, mnDatePart);
+ }
+
+-bool ScDPGroupDateFilter::match(const ScDPCacheTable::Cell& rCell) const
++bool ScDPGroupDateFilter::match(const ScDPCacheCell& rCell) const
+ {
+ using namespace ::com::sun::star::sheet;
+ using ::rtl::math::approxFloor;
+@@ -977,6 +978,7 @@ String lcl_GetNumGroupForValue( double fValue, const ScDPNumGroupInfo& rInfo, bo
+ }
+
+ ScDPGroupTableData::ScDPGroupTableData( ScDPTableData* pSource, ScDocument* pDocument ) :
++ ScDPTableData(pDocument),
+ pSourceData( pSource ),
+ pDoc( pDocument )
+ {
+@@ -1136,7 +1138,7 @@ void ScDPGroupTableData::CreateCacheTable()
+ pSourceData->CreateCacheTable();
+ }
+
+-void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& rCriteria) const
++void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>& rCriteria)
+ {
+ typedef hash_map<long, const ScDPGroupDimension*> GroupFieldMapType;
+ GroupFieldMapType aGroupFieldIds;
+@@ -1225,7 +1227,7 @@ void ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPCacheTable::Criterion>&
+
+ ScDPCacheTable::Criterion aCri;
+ aCri.mnFieldIndex = nSrcDim;
+- aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter);
++ aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(GetSharedString()));
+ ScDPCacheTable::GroupFilter* pGrpFilter =
+ static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get());
+
+diff --git sc/source/core/data/dpobject.cxx sc/source/core/data/dpobject.cxx
+index 6e0392d..8e1c9b8 100644
+--- sc/source/core/data/dpobject.cxx
++++ sc/source/core/data/dpobject.cxx
+@@ -408,7 +408,7 @@ void ScDPObject::CreateObjects()
+ if ( pImpDesc )
+ {
+ // database data
+- pData = new ScDatabaseDPData( pDoc->GetServiceManager(), *pImpDesc );
++ pData = new ScDatabaseDPData( pDoc, pDoc->GetServiceManager(), *pImpDesc );
+ }
+ else
+ {
+@@ -2514,7 +2514,49 @@ uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPS
+ return xRet;
+ }
+
+-// -----------------------------------------------------------------------
++// ============================================================================
++
++ScDPCacheCell::ScDPCacheCell() :
++ mnStrId(ScSimpleSharedString::EMPTY),
++ mnType(SC_VALTYPE_EMPTY),
++ mfValue(0.0),
++ mbNumeric(false)
++{
++}
++
++ScDPCacheCell::ScDPCacheCell(const ScDPCacheCell& r) :
++ mnStrId(r.mnStrId),
++ mnType(r.mnType),
++ mfValue(r.mfValue),
++ mbNumeric(r.mbNumeric)
++{
++}
++
++ScDPCacheCell::~ScDPCacheCell()
++{
++}
++
++// ============================================================================
++
++size_t ScDPCollection::CacheCellHash::operator()(const ScDPCacheCell* pCell) const
++{
++ return pCell->mnStrId + static_cast<size_t>(pCell->mnType) +
++ static_cast<size_t>(pCell->mfValue) + static_cast<size_t>(pCell->mbNumeric);
++}
++
++bool ScDPCollection::CacheCellEqual::operator()(const ScDPCacheCell* p1, const ScDPCacheCell* p2) const
++{
++ if (!p1 && !p2)
++ return true;
++
++ if ((!p1 && p2) || (p1 && !p2))
++ return false;
++
++ return p1->mnStrId == p2->mnStrId && p1->mfValue == p2->mfValue &&
++ p1->mbNumeric == p2->mbNumeric && p1->mnType == p2->mnType;
++}
++
++// ----------------------------------------------------------------------------
+
+ ScDPCollection::ScDPCollection(ScDocument* pDocument) :
+ pDoc( pDocument )
+@@ -2523,12 +2565,15 @@ ScDPCollection::ScDPCollection(ScDocument* pDocument) :
+
+ ScDPCollection::ScDPCollection(const ScDPCollection& r) :
+ Collection(r),
+- pDoc(r.pDoc)
++ pDoc(r.pDoc),
++ maSharedString(r.maSharedString),
++ maCacheCellPool(r.maCacheCellPool)
+ {
+ }
+
+ ScDPCollection::~ScDPCollection()
+ {
++ clearCacheCellPool();
+ }
+
+ DataObject* ScDPCollection::Clone() const
+@@ -2716,9 +2761,66 @@ void ScDPCollection::EnsureNames()
+ ((ScDPObject*)At(i))->SetName( CreateNewName() );
+ }
+
++ScSimpleSharedString& ScDPCollection::GetSharedString()
++{
++ return maSharedString;
++}
++
++ScDPCacheCell* ScDPCollection::getCacheCellFromPool(const ScDPCacheCell& rCell)
++{
++ ScDPCacheCell aCell(rCell);
++ CacheCellPoolType::iterator itr = maCacheCellPool.find(&aCell);
++ if (itr == maCacheCellPool.end())
++ {
++ // Insert a new instance.
++ ScDPCacheCell* p = new ScDPCacheCell(rCell);
++ ::std::pair<CacheCellPoolType::iterator, bool> r =
++ maCacheCellPool.insert(p);
++ if (!r.second)
++ delete p;
++
++ ScDPCacheCell* p2 = r.second ? *r.first : NULL;
++ DBG_ASSERT(p == p2, "ScDPCollection::getCacheCellFromPool: pointer addresses differ");
++ return p2;
++ }
++ return *itr;
++}
++
++namespace {
++
++class DeleteCacheCells : public ::std::unary_function<ScDPCacheCell*, void>
++{
++public:
++ void operator()(ScDPCacheCell* p) const
++ {
++ delete p;
++ }
++};
++
++}
++
++void ScDPCollection::clearCacheCellPool()
++{
++ // Transferring all the pointers to a vector first. For some reason,
++ // deleting the cell content instances directly by iterating through
++ // pointers stored in the hash set caused the iteration to return an
++ // identical pointer value twice, causing a double-delete. I have no idea
++ // why.
++
++ using ::std::copy;
++ using ::std::back_inserter;
++
++ vector<ScDPCacheCell*> ps;
++ ps.reserve(maCacheCellPool.size());
++ copy(maCacheCellPool.begin(), maCacheCellPool.end(), back_inserter(ps));
++ for_each(ps.begin(), ps.end(), DeleteCacheCells());
++ maCacheCellPool.clear();
++}
++
+ //------------------------------------------------------------------------
+ // convert old pivot tables into new datapilot tables
+
++#if OLD_PIVOT_IMPLEMENTATION
+ void ScDPCollection::ConvertOldTables( ScPivotCollection& rOldColl )
+ {
+ // convert old pivot tables into new datapilot tables
+diff --git sc/source/core/data/dpsdbtab.cxx sc/source/core/data/dpsdbtab.cxx
+index 5ac8d6d..e8d0509 100644
+--- sc/source/core/data/dpsdbtab.cxx
++++ sc/source/core/data/dpsdbtab.cxx
+@@ -58,6 +58,8 @@
+ #include "globstr.hrc"
+ #include "dpcachetable.hxx"
+ #include "dptabres.hxx"
++#include "document.hxx"
++#include "dpobject.hxx"
+
+ using namespace com::sun::star;
+
+@@ -91,16 +93,21 @@ public:
+
+ ScDPCacheTable aCacheTable;
+
+- ScDatabaseDPData_Impl() {}
++ ScDatabaseDPData_Impl(ScDPCollection* p) :
++ aCacheTable(p)
++ {
++ }
+ };
+
+ // -----------------------------------------------------------------------
+
+ ScDatabaseDPData::ScDatabaseDPData(
++ ScDocument* pDoc,
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr,
+- const ScImportSourceDesc& rImport )
++ const ScImportSourceDesc& rImport ) :
++ ScDPTableData(pDoc)
+ {
+- pImpl = new ScDatabaseDPData_Impl;
++ pImpl = new ScDatabaseDPData_Impl(pDoc->GetDPCollection());
+ pImpl->xServiceManager = xSMgr;
+ pImpl->aDesc = rImport;
+ pImpl->nColCount = 0;
+diff --git sc/source/core/data/dpshttab.cxx sc/source/core/data/dpshttab.cxx
+index 9dab27c..76410c6 100644
+--- sc/source/core/data/dpshttab.cxx
++++ sc/source/core/data/dpshttab.cxx
+@@ -44,6 +44,7 @@
+ #include "collect.hxx"
+ #include "cell.hxx"
+ #include "dpcachetable.hxx"
++#include "dpobject.hxx"
+ #include "globstr.hrc"
+
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+@@ -74,17 +75,19 @@ public:
+
+ ScDPCacheTable aCacheTable;
+
+- ScSheetDPData_Impl() :
+- pSpecial(NULL)
++ ScSheetDPData_Impl(ScDPCollection* p) :
++ pSpecial(NULL),
++ aCacheTable(p)
+ {
+ }
+ };
+
+ // -----------------------------------------------------------------------
+
+-ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc )
++ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc ) :
++ ScDPTableData(pD)
+ {
+- pImpl = new ScSheetDPData_Impl;
++ pImpl = new ScSheetDPData_Impl(pD->GetDPCollection());
+ pImpl->pDoc = pD;
+ pImpl->aRange = rDesc.aSourceRange;
+ pImpl->aQuery = rDesc.aQueryParam;
+diff --git sc/source/core/data/dptabdat.cxx sc/source/core/data/dptabdat.cxx
+index dc42601..77521a6 100644
+--- sc/source/core/data/dptabdat.cxx
++++ sc/source/core/data/dptabdat.cxx
+@@ -48,6 +48,8 @@
+ #include "global.hxx"
+ #include "dpcachetable.hxx"
+ #include "dptabres.hxx"
++#include "document.hxx"
++#include "dpobject.hxx"
+
+ using namespace ::com::sun::star;
+ using ::com::sun::star::uno::Sequence;
+@@ -125,7 +127,8 @@ ScDPTableData::CalcInfo::CalcInfo() :
+
+ // ---------------------------------------------------------------------------
+
+-ScDPTableData::ScDPTableData()
++ScDPTableData::ScDPTableData(ScDocument* pDoc) :
++ mrSharedString(pDoc->GetDPCollection()->GetSharedString())
+ {
+ nLastDateVal = nLastHier = nLastLevel = nLastRet = -1; // invalid
+
+@@ -186,26 +189,6 @@ bool ScDPTableData::IsRepeatIfEmpty()
+ return false;
+ }
+
+-void ScDPTableData::CreateCacheTable()
+-{
+- fprintf(stdout, "ScDPTableData::CreateCacheTable: un-implemented...\n");fflush(stdout);
+-}
+-
+-void ScDPTableData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>&)
+-{
+- fprintf(stdout, "ScDPTableData::FilterCacheTable: un-implemented...\n");
+-}
+-
+-void ScDPTableData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>&, Sequence< Sequence<Any> >&)
+-{
+- fprintf(stdout, "ScDPTableData::GetDrillDownData: un-implemented...\n");fflush(stdout);
+-}
+-
+-void ScDPTableData::CalcResults(CalcInfo&, bool)
+-{
+- fprintf(stdout, "ScDPTableData::CalcResults: un-implemented...\n");fflush(stdout);
+-}
+-
+ UINT32 ScDPTableData::GetNumberFormat(long)
+ {
+ return 0; // default format
+@@ -240,6 +223,11 @@ BOOL ScDPTableData::HasCommonElement( const ScDPItemData&, long,
+ return FALSE;
+ }
+
++ScSimpleSharedString& ScDPTableData::GetSharedString()
++{
++ return mrSharedString;
++}
++
+ void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable,
+ const CalcInfo& rInfo, CalcRowData& rData)
+ {
+@@ -258,7 +246,8 @@ void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTab
+ long nDim = rInfo.aDataSrcCols[i];
+ rData.aValues.push_back( ScDPValueData() );
+ ScDPValueData& rVal = rData.aValues.back();
+- const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow));
++ const ScDPCacheCell* pCell = rCacheTable.getCell(
++ static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow));
+ if (pCell)
+ {
+ rVal.fValue = pCell->mbNumeric ? pCell->mfValue : 0.0;
+@@ -321,11 +310,12 @@ void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRo
+ continue;
+ }
+
+- const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty());
++ const ScDPCacheCell* pCell = rCacheTable.getCell(
++ static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty());
+ if (!pCell || pCell->mnType == SC_VALTYPE_EMPTY)
+ continue;
+
+- const String* pString = ScSharedString::getString(pCell->mnStrId);
++ const String* pString = GetSharedString().getString(pCell->mnStrId);
+ if (!pString)
+ continue;
+
+diff --git sc/source/core/data/dptabres.cxx sc/source/core/data/dptabres.cxx
+index bfbe34b..c52139c 100644
+--- sc/source/core/data/dptabres.cxx
++++ sc/source/core/data/dptabres.cxx
+@@ -41,6 +41,7 @@
+ #include <float.h> //! Test !!!
+
+ #include <algorithm>
++#include <hash_map>
+
+ #include "dptabdat.hxx"
+ #include "dptabres.hxx"
+@@ -59,9 +60,13 @@
+ #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+
+ using namespace com::sun::star;
+ using ::std::vector;
++using ::std::pair;
++using ::std::hash_map;
++using ::com::sun::star::uno::Sequence;
+
+ // -----------------------------------------------------------------------
+
+@@ -1577,6 +1582,12 @@ ScDPAggData* ScDPResultMember::GetColTotal( long nMeasure ) const
+ return lcl_GetChildTotal( const_cast<ScDPAggData*>(&aColTotal), nMeasure );
+ }
+
++void ScDPResultMember::FillVisibilityData(ScDPResultVisibilityData& rData) const
++{
++ if (pChildDimension)
++ pChildDimension->FillVisibilityData(rData);
++}
++
+ // -----------------------------------------------------------------------
+
+ ScDPDataMember::ScDPDataMember( const ScDPResultData* pData, const ScDPResultMember* pRes ) :
+@@ -3231,6 +3242,26 @@ ScDPResultDimension* ScDPResultDimension::GetFirstChildDimension() const
+ return NULL;
+ }
+
++void ScDPResultDimension::FillVisibilityData(ScDPResultVisibilityData& rData) const
++{
++ if (IsDataLayout())
++ return;
++
++ MemberArray::const_iterator itr = maMemberArray.begin(), itrEnd = maMemberArray.end();
++
++ for (;itr != itrEnd; ++itr)
++ {
++ ScDPResultMember* pMember = *itr;
++ if (pMember->IsValid())
++ {
++ ScDPItemData aItem;
++ pMember->FillItemData(aItem);
++ rData.addVisibleMember(GetName(), aItem);
++ pMember->FillVisibilityData(rData);
++ }
++ }
++}
++
+ // -----------------------------------------------------------------------
+
+ ScDPDataDimension::ScDPDataDimension( const ScDPResultData* pData ) :
+@@ -3559,3 +3590,88 @@ ScDPDataMember* ScDPDataDimension::GetMember(long n) const
+ return aMembers[(USHORT)n];
+ }
+
++// ----------------------------------------------------------------------------
++
++ScDPResultVisibilityData::ScDPResultVisibilityData(
++ ScSimpleSharedString& rSharedString, ScDPSource* pSource) :
++ mrSharedString(rSharedString),
++ mpSource(pSource)
++{
++}
++
++ScDPResultVisibilityData::~ScDPResultVisibilityData()
++{
++}
++
++void ScDPResultVisibilityData::addVisibleMember(const String& rDimName, const ScDPItemData& rMemberItem)
++{
++ DimMemberType::iterator itr = maDimensions.find(rDimName);
++ if (itr == maDimensions.end())
++ {
++ pair<DimMemberType::iterator, bool> r = maDimensions.insert(
++ DimMemberType::value_type(rDimName, VisibleMemberType()));
++
++ if (!r.second)
++ // insertion failed.
++ return;
++
++ itr = r.first;
++ }
++ VisibleMemberType& rMem = itr->second;
++ VisibleMemberType::iterator itrMem = rMem.find(rMemberItem);
++ if (itrMem == rMem.end())
++ rMem.insert(rMemberItem);
++}
++
++void ScDPResultVisibilityData::fillFieldFilters(vector<ScDPCacheTable::Criterion>& rFilters) const
++{
++ typedef hash_map<String, long, ScStringHashCode> FieldNameMapType;
++ FieldNameMapType aFieldNames;
++ ScDPTableData* pData = mpSource->GetData();
++ long nColumnCount = pData->GetColumnCount();
++ for (long i = 0; i < nColumnCount; ++i)
++ {
++ aFieldNames.insert(
++ FieldNameMapType::value_type(pData->getDimensionName(i), i));
++ }
++
++ const ScDPDimensions* pDims = mpSource->GetDimensionsObject();
++ for (DimMemberType::const_iterator itr = maDimensions.begin(), itrEnd = maDimensions.end();
++ itr != itrEnd; ++itr)
++ {
++ const String& rDimName = itr->first;
++ ScDPCacheTable::Criterion aCri;
++ FieldNameMapType::const_iterator itrField = aFieldNames.find(rDimName);
++ if (itrField == aFieldNames.end())
++ // This should never happen!
++ continue;
++
++ long nDimIndex = itrField->second;
++ aCri.mnFieldIndex = static_cast<sal_Int32>(nDimIndex);
++ aCri.mpFilter.reset(new ScDPCacheTable::GroupFilter(mrSharedString));
++ ScDPCacheTable::GroupFilter* pGrpFilter =
++ static_cast<ScDPCacheTable::GroupFilter*>(aCri.mpFilter.get());
++
++ const VisibleMemberType& rMem = itr->second;
++ for (VisibleMemberType::const_iterator itrMem = rMem.begin(), itrMemEnd = rMem.end();
++ itrMem != itrMemEnd; ++itrMem)
++ {
++ const ScDPItemData& rMemItem = *itrMem;
++ pGrpFilter->addMatchItem(rMemItem.aString, rMemItem.fValue, rMemItem.bHasValue);
++ }
++
++ ScDPDimension* pDim = pDims->getByIndex(nDimIndex);
++ ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
++ GetLevelsObject()->getByIndex(0)->GetMembersObject();
++ if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(pMembers->getCount()))
++ rFilters.push_back(aCri);
++ }
++}
++
++size_t ScDPResultVisibilityData::MemberHash::operator() (const ScDPItemData& r) const
++{
++ if (r.bHasValue)
++ return static_cast<size_t>(::rtl::math::approxFloor(r.fValue));
++ else
++ return rtl_ustr_hashCode_WithLength(r.aString.GetBuffer(), r.aString.Len());
++}
+diff --git sc/source/core/data/dptabsrc.cxx sc/source/core/data/dptabsrc.cxx
+index 6881c70..600eb7b 100644
+--- sc/source/core/data/dptabsrc.cxx
++++ sc/source/core/data/dptabsrc.cxx
+@@ -31,7 +31,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+
+-#include <stdio.h>
++
+
+
+ // INCLUDE ---------------------------------------------------------------
+@@ -68,6 +68,7 @@
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
++#include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
+ #include <com/sun/star/table/CellAddress.hpp>
+
+ #include <unotools/collatorwrapper.hxx>
+@@ -81,6 +82,7 @@ using ::std::hash_map;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Any;
++using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
+
+ // -----------------------------------------------------------------------
+
+@@ -422,6 +424,15 @@ Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<s
+ throw (uno::RuntimeException)
+ {
+ long nColumnCount = GetData()->GetColumnCount();
++ ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
++
++ typedef hash_map<String, long, ScStringHashCode> FieldNameMapType;
++ FieldNameMapType aFieldNames;
++ for (long i = 0; i < nColumnCount; ++i)
++ {
++ aFieldNames.insert(
++ FieldNameMapType::value_type(GetData()->getDimensionName(i), i));
++ }
+
+ // collect ScDPItemData for each filtered column
+ vector<ScDPCacheTable::Criterion> aFilterCriteria;
+@@ -443,15 +454,21 @@ Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<s
+ ScDPItemData aItem;
+ pMembers->getByIndex(nIndex)->FillItemData( aItem );
+ aFilterCriteria.push_back( ScDPCacheTable::Criterion() );
+- sal_Int32 nMatchStrId = ScSharedString::getStringId(aItem.aString);
++ sal_Int32 nMatchStrId = rSharedString.getStringId(aItem.aString);
+ aFilterCriteria.back().mnFieldIndex = nCol;
+ aFilterCriteria.back().mpFilter.reset(
+- new ScDPCacheTable::SingleFilter(nMatchStrId, aItem.fValue, aItem.bHasValue) );
++ new ScDPCacheTable::SingleFilter(rSharedString, nMatchStrId, aItem.fValue, aItem.bHasValue) );
+ }
+ }
+ }
+ }
+
++ // Take into account the visibilities of field members.
++ ScDPResultVisibilityData aResVisData(rSharedString, this);
++ pRowResRoot->FillVisibilityData(aResVisData);
++ pColResRoot->FillVisibilityData(aResVisData);
++ aResVisData.fillFieldFilters(aFilterCriteria);
++
+ Sequence< Sequence<Any> > aTabData;
+ pData->GetDrillDownData(aFilterCriteria, aTabData);
+ return aTabData;
+@@ -834,6 +851,8 @@ void ScDPSource::CreateRes_Impl()
+ else
+ {
+ {
++ ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
++
+ // filter table by page dimensions.
+ vector<ScDPCacheTable::Criterion> aCriteria;
+ for (i = 0; i < nPageDimCount; ++i)
+@@ -847,9 +866,9 @@ void ScDPSource::CreateRes_Impl()
+ aCriteria.push_back(ScDPCacheTable::Criterion());
+ ScDPCacheTable::Criterion& r = aCriteria.back();
+ r.mnFieldIndex = static_cast<sal_Int32>(nField);
+- sal_Int32 nStrId = ScSharedString::getStringId(rData.aString);
++ sal_Int32 nStrId = rSharedString.getStringId(rData.aString);
+ r.mpFilter.reset(
+- new ScDPCacheTable::SingleFilter(nStrId, rData.fValue, rData.bHasValue));
++ new ScDPCacheTable::SingleFilter(rSharedString, nStrId, rData.fValue, rData.bHasValue));
+ }
+ if (!aCriteria.empty())
+ pData->FilterCacheTable(aCriteria);
+diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
+index 2cbda72..abfae52 100644
+--- sc/source/core/data/global2.cxx
++++ sc/source/core/data/global2.cxx
+@@ -1311,4 +1311,90 @@ String ScGlobal::GetDocTabName( const String& rFileName,
+ return aDocTab;
+ }
+
++// ============================================================================
+
++ScSimpleSharedString::StringTable::StringTable() :
++ mnStrCount(0)
++{
++ // empty string (ID = 0)
++ maSharedStrings.push_back(String());
++ maSharedStringIds.insert( SharedStrMap::value_type(String(), mnStrCount++) );
++}
++
++ScSimpleSharedString::StringTable::StringTable(const ScSimpleSharedString::StringTable& r) :
++ maSharedStrings(r.maSharedStrings),
++ maSharedStringIds(r.maSharedStringIds),
++ mnStrCount(r.mnStrCount)
++{
++}
++
++ScSimpleSharedString::StringTable::~StringTable()
++{
++}
++
++sal_Int32 ScSimpleSharedString::StringTable::insertString(const String& aStr)
++{
++ SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
++ itrEnd = maSharedStringIds.end();
++
++ if (itr == itrEnd)
++ {
++ // new string.
++ maSharedStrings.push_back(aStr);
++ maSharedStringIds.insert( SharedStrMap::value_type(aStr, mnStrCount) );
++ return mnStrCount++;
++ }
++
++ // existing string.
++ return itr->second;
++}
++
++sal_Int32 ScSimpleSharedString::StringTable::getStringId(const String& aStr)
++{
++ SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr),
++ itrEnd = maSharedStringIds.end();
++ if (itr == itrEnd)
++ {
++ // string not found.
++ return insertString(aStr);
++ }
++ return itr->second;
++}
++
++const String* ScSimpleSharedString::StringTable::getString(sal_Int32 nId) const
++{
++ if (nId >= mnStrCount)
++ return NULL;
++
++ return &maSharedStrings[nId];
++}
++
++// ----------------------------------------------------------------------------
++
++ScSimpleSharedString::ScSimpleSharedString()
++{
++}
++
++ScSimpleSharedString::ScSimpleSharedString(const ScSimpleSharedString& r) :
++ maStringTable(r.maStringTable)
++{
++}
++
++ScSimpleSharedString::~ScSimpleSharedString()
++{
++}
++
++sal_Int32 ScSimpleSharedString::insertString(const String& aStr)
++{
++ return maStringTable.insertString(aStr);
++}
++
++const String* ScSimpleSharedString::getString(sal_Int32 nId)
++{
++ return maStringTable.getString(nId);
++}
++
++sal_Int32 ScSimpleSharedString::getStringId(const String& aStr)
++{
++ return maStringTable.getStringId(aStr);
++}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]