summaryrefslogtreecommitdiff
path: root/sc/source/core/data/dptablecache.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/data/dptablecache.cxx')
-rw-r--r--sc/source/core/data/dptablecache.cxx95
1 files changed, 59 insertions, 36 deletions
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 008cdfcf3935..35782e05bab7 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -48,6 +48,8 @@
#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;
@@ -57,26 +59,37 @@ 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 {
-bool lcl_isDate( sal_uLong nNumType )
+bool isDate( sal_uLong nNumType )
{
return ((nNumType & NUMBERFORMAT_DATE) != 0) ? 1 : 0;
}
-bool lcl_Search( const ScDPCache::DataListType& list, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex)
+/**
+ * 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 ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex)
{
- rIndex = list.size();
+ rIndex = rArray.size();
bool bFound = false;
SCROW nLo = 0;
- SCROW nHi = list.size() - 1;
- SCROW nIndex;
+ SCROW nHi = rArray.size() - 1;
long nCompare;
while (nLo <= nHi)
{
- nIndex = (nLo + nHi) / 2;
- nCompare = ScDPItemData::Compare( list[rOrder[nIndex]], item );
+ SCROW nIndex = (nLo + nHi) / 2;
+ nCompare = ScDPItemData::Compare( rArray[rOrder[nIndex]], item );
if (nCompare < 0)
nLo = nIndex + 1;
else
@@ -173,7 +186,7 @@ ScDPItemData* lcl_GetItemValue(
ScDPItemData::ScDPItemData(const String& rS, double fV, bool bHV, const sal_uLong nNumFormatP, bool bData) :
nNumFormat( nNumFormatP ), aString(rS), fValue(fV),
- mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) | (MK_DATE*!!lcl_isDate( nNumFormat ) ) )
+ mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) | (MK_DATE*!!isDate( nNumFormat ) ) )
{
}
@@ -203,7 +216,7 @@ ScDPItemData::ScDPItemData(ScDocument* pDoc, SCROW nRow, sal_uInt16 nCol, sal_uI
fValue = fVal;
mbFlag |= MK_VAL|MK_DATA;
nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) );
- lcl_isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE);
+ isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE);
}
else if ( pDoc->HasData( nCol,nRow, nDocTab ) )
SetString ( aDocStr );
@@ -473,15 +486,12 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
maIndexOrder.push_back(new vector<SCROW>());
}
//check valid
- for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow ++ )
+
+ for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
{
- for ( sal_uInt16 nCol = nStartCol; nCol <= nEndCol; nCol++ )
- {
- if ( nRow == nStartRow )
- AddLabel( new ScDPItemData( pDoc, nRow, nCol, nDocTab ) );
- else
- AddData( nCol - nStartCol, new ScDPItemData( pDoc, nRow, nCol, nDocTab ) );
- }
+ AddLabel(new ScDPItemData(pDoc, nStartRow, nCol, nDocTab));
+ for (SCROW nRow = nStartRow + 1; nRow <= nEndRow; ++nRow)
+ AddData(nCol - nStartCol, new ScDPItemData(pDoc, nRow, nCol, nDocTab));
}
return true;
}
@@ -489,7 +499,7 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate)
{
if (!xRowSet.is())
- // Dont' even waste time to go any further.
+ // Don't even waste time to go any further.
return false;
try
{
@@ -565,7 +575,7 @@ sal_uLong ScDPCache::GetDimNumType( SCCOL nDim) const
return GetNumType(maTableDataValues[nDim][0].nNumFormat);
}
-bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial)
+bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial) const
{
if (!rParam.GetEntry(0).bDoQuery)
return true;
@@ -787,23 +797,23 @@ bool ScDPCache::IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const
return !GetItemDataById( nColumn, GetItemDataId( nColumn, nRow, false ) )->IsHasData();
}
-bool ScDPCache::AddData(long nDim, ScDPItemData* pitemData)
+bool ScDPCache::AddData(long nDim, ScDPItemData* pData)
{
DBG_ASSERT( IsValid(), " IsValid() == false " );
DBG_ASSERT( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" );
- SCROW nIndex = 0;
- bool bInserted = false;
+ // Wrap this instance with scoped pointer to ensure proper deletion.
+ auto_ptr<ScDPItemData> p(pData);
+ pData->SetDate(isDate(GetNumType(pData->nNumFormat)));
- pitemData->SetDate( lcl_isDate( GetNumType( pitemData->nNumFormat ) ) );
-
- if ( !lcl_Search( maTableDataValues[nDim], maGlobalOrder[nDim], *pitemData, nIndex ) )
+ SCROW nIndex = 0;
+ if (!hasItemInDimension(maTableDataValues[nDim], maGlobalOrder[nDim], *pData, nIndex))
{
- maTableDataValues[nDim].push_back( pitemData );
+ // This item doesn't exist in the dimension array yet.
+ maTableDataValues[nDim].push_back(p);
maGlobalOrder[nDim].insert( maGlobalOrder[nDim].begin()+nIndex, maTableDataValues[nDim].size()-1 );
DBG_ASSERT( (size_t) maGlobalOrder[nDim][nIndex] == maTableDataValues[nDim].size()-1 ,"ScDPTableDataCache::AddData ");
maSourceData[nDim].push_back( maTableDataValues[nDim].size()-1 );
- bInserted = true;
}
else
maSourceData[nDim].push_back( maGlobalOrder[nDim][nIndex] );
@@ -813,12 +823,9 @@ bool ScDPCache::AddData(long nDim, ScDPItemData* pitemData)
while ( mbEmptyRow.size() <= nCurRow )
mbEmptyRow.push_back( true );
- if ( pitemData->IsHasData() )
+ if ( pData->IsHasData() )
mbEmptyRow[ nCurRow ] = false;
- if ( !bInserted )
- delete pitemData;
-
return true;
}
@@ -928,10 +935,26 @@ sal_uLong ScDPCache::GetNumberFormat( long nDim ) const
{
if ( nDim >= mnColumnCount )
return 0;
- if ( maTableDataValues[nDim].size()==0 )
+
+ if (maTableDataValues[nDim].empty())
return 0;
- else
- return maTableDataValues[nDim][0].nNumFormat;
+
+ // TODO: This is very ugly, but the best we can do right now. Check the
+ // first 10 dimension members, and take the first non-zero number format,
+ // else return the default number format (of 0). For the long-term, we
+ // need to redo this cache structure to properly indicate empty cells, and
+ // skip them when trying to determine the representative number format for
+ // a dimension.
+ size_t nCount = maTableDataValues[nDim].size();
+ if (nCount > 10)
+ nCount = 10;
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ sal_uLong n = maTableDataValues[nDim][i].nNumFormat;
+ if (n)
+ return n;
+ }
+ return 0;
}
bool ScDPCache::IsDateDimension( long nDim ) const
@@ -967,7 +990,7 @@ SCCOL ScDPCache::GetDimensionIndex(String sName) const
return -1;
}
-SCROW ScDPCache::GetIdByItemData(long nDim, String sItemData ) const
+SCROW ScDPCache::GetIdByItemData(long nDim, const String& sItemData ) const
{
if ( nDim < mnColumnCount && nDim >=0 )
{
@@ -995,7 +1018,7 @@ SCROW ScDPCache::GetIdByItemData( long nDim, const ScDPItemData& rData ) const
return GetRowCount() + maAdditionalData.getDataId(rData);
}
-SCROW ScDPCache::GetAdditionalItemID ( String sItemData ) const
+SCROW ScDPCache::GetAdditionalItemID ( const String& sItemData ) const
{
ScDPItemData rData ( sItemData );
return GetAdditionalItemID( rData );