summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/queryiter.hxx7
-rw-r--r--sc/source/core/data/queryiter.cxx33
-rw-r--r--sc/source/core/inc/interpre.hxx4
-rw-r--r--sc/source/core/tool/interpr1.cxx29
-rw-r--r--sc/source/core/tool/interpr4.cxx23
5 files changed, 79 insertions, 17 deletions
diff --git a/sc/inc/queryiter.hxx b/sc/inc/queryiter.hxx
index 545955d77963..7c454f784a2e 100644
--- a/sc/inc/queryiter.hxx
+++ b/sc/inc/queryiter.hxx
@@ -26,6 +26,7 @@
#include "mtvelements.hxx"
#include "types.hxx"
+struct ScComplexRefData;
class ScSortedRangeCache;
/*
@@ -318,7 +319,8 @@ public:
SCTAB nTable, const ScQueryParam& aParam, bool bMod)
: Base( rDocument, rContext, nTable, aParam, bMod ) {}
// Returns true if this iterator can be used for the given query.
- static bool CanBeUsed(const ScDocument& rDoc, const ScQueryParam& aParam);
+ static bool CanBeUsed(const ScDocument& rDoc, const ScQueryParam& aParam,
+ const ScFormulaCell* cell, const ScComplexRefData* refData);
};
@@ -366,7 +368,8 @@ public:
SCTAB nTable, const ScQueryParam& aParam, bool bMod)
: Base( rDocument, rContext, nTable, aParam, bMod ) {}
// Returns true if this iterator can be used for the given query.
- static bool CanBeUsed(const ScDocument& rDoc, const ScQueryParam& aParam);
+ static bool CanBeUsed(const ScDocument& rDoc, const ScQueryParam& aParam,
+ const ScFormulaCell* cell, const ScComplexRefData* refData);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/queryiter.cxx b/sc/source/core/data/queryiter.cxx
index ffb37c0e272f..8a7bf2ce6e5b 100644
--- a/sc/source/core/data/queryiter.cxx
+++ b/sc/source/core/data/queryiter.cxx
@@ -1198,7 +1198,8 @@ ScQueryCellIteratorAccessSpecific< ScQueryCellIteratorAccess::SortedCache >::Mak
return SortedCacheIndexer(rCells, nStartRow, nEndRow, sortedCache);
}
-static bool CanBeUsedForSorterCache(const ScDocument& rDoc, const ScQueryParam& rParam)
+static bool CanBeUsedForSorterCache(const ScDocument& rDoc, const ScQueryParam& rParam,
+ const ScFormulaCell* cell, const ScComplexRefData* refData)
{
if(!rParam.GetEntry(0).bDoQuery || rParam.GetEntry(1).bDoQuery
|| rParam.GetEntry(0).GetQueryItems().size() != 1 )
@@ -1221,6 +1222,26 @@ static bool CanBeUsedForSorterCache(const ScDocument& rDoc, const ScQueryParam&
&& rParam.GetEntry(0).eOp != SC_GREATER && rParam.GetEntry(0).eOp != SC_GREATER_EQUAL
&& rParam.GetEntry(0).eOp != SC_EQUAL)
return false;
+ // For unittests allow inefficient caching, in order for the code to be checked.
+ static bool inUnitTest = getenv("LO_TESTNAME") != nullptr;
+ if(refData == nullptr || refData->Ref1.IsRowRel() || refData->Ref2.IsRowRel())
+ {
+ // If this is not a range, then a cache is not worth it. If rows are relative, then each
+ // computation will use a different area, so the cache wouldn't be reused. Tab/cols are
+ // not a problem, because formula group computations are done for the same tab/col.
+ if(!inUnitTest)
+ return false;
+ }
+ if(rParam.nRow2 - rParam.nRow1 < 10)
+ {
+ if(!inUnitTest)
+ return false;
+ }
+ if( !cell || !cell->GetCellGroup() || cell->GetCellGroup()->mnLength < 10 )
+ {
+ if(!inUnitTest)
+ return false;
+ }
return true;
}
@@ -1260,9 +1281,10 @@ bool ScQueryCellIterator< accessType >::GetNext()
return GetThis();
}
-bool ScQueryCellIteratorSortedCache::CanBeUsed(const ScDocument& rDoc, const ScQueryParam& rParam)
+bool ScQueryCellIteratorSortedCache::CanBeUsed(const ScDocument& rDoc, const ScQueryParam& rParam,
+ const ScFormulaCell* cell, const ScComplexRefData* refData)
{
- return CanBeUsedForSorterCache(rDoc, rParam);
+ return CanBeUsedForSorterCache(rDoc, rParam, cell, refData);
}
// Countifs implementation.
@@ -1289,9 +1311,10 @@ sal_uInt64 ScCountIfCellIterator< accessType >::GetCount()
}
-bool ScCountIfCellIteratorSortedCache::CanBeUsed(const ScDocument& rDoc, const ScQueryParam& rParam)
+bool ScCountIfCellIteratorSortedCache::CanBeUsed(const ScDocument& rDoc, const ScQueryParam& rParam,
+ const ScFormulaCell* cell, const ScComplexRefData* refData)
{
- return CanBeUsedForSorterCache(rDoc, rParam);
+ return CanBeUsedForSorterCache(rDoc, rParam, cell, refData);
}
template<>
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 47763ed8fea4..30e79d9272bb 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -345,6 +345,8 @@ private:
ScDBRangeBase* PopDBDoubleRef();
void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 );
+ // peek double ref data
+ const ScComplexRefData* GetStackDoubleRef(size_t rRefInList = 0);
void PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef);
@@ -481,7 +483,7 @@ private:
inline void TreatDoubleError( double& rVal );
// Lookup using ScLookupCache, @returns true if found and result address
bool LookupQueryWithCache( ScAddress & o_rResultPos,
- const ScQueryParam & rParam ) const;
+ const ScQueryParam & rParam, const ScComplexRefData* refData ) const;
void ScIfJump();
void ScIfError( bool bNAonly );
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index e80b299f4771..afd9079de498 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -4839,6 +4839,7 @@ void ScInterpreter::ScMatch()
rParam.nRow1 = nRow1;
rParam.nCol2 = nCol2;
rParam.nTab = nTab1;
+ const ScComplexRefData* refData = nullptr;
ScQueryEntry& rEntry = rParam.GetEntry(0);
ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
@@ -4863,6 +4864,8 @@ void ScInterpreter::ScMatch()
}
break;
case svDoubleRef :
+ refData = GetStackDoubleRef();
+ [[fallthrough]];
case svSingleRef :
{
ScAddress aAdr;
@@ -5037,7 +5040,7 @@ void ScInterpreter::ScMatch()
rParam.nRow2 = nRow2;
rEntry.nField = nCol1;
ScAddress aResultPos( nCol1, nRow1, nTab1);
- if (!LookupQueryWithCache( aResultPos, rParam))
+ if (!LookupQueryWithCache( aResultPos, rParam, refData))
{
PushNA();
return;
@@ -5689,6 +5692,7 @@ void ScInterpreter::ScCountIf()
SCROW nRow2 = 0;
SCTAB nTab2 = 0;
ScMatrixRef pQueryMatrix;
+ const ScComplexRefData* refData = nullptr;
switch ( GetStackType() )
{
case svRefList :
@@ -5696,6 +5700,7 @@ void ScInterpreter::ScCountIf()
[[fallthrough]];
case svDoubleRef :
{
+ refData = GetStackDoubleRef(nRefInList);
ScRange aRange;
PopDoubleRef( aRange, nParam, nRefInList);
aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
@@ -5788,7 +5793,7 @@ void ScInterpreter::ScCountIf()
}
else
{
- if(ScCountIfCellIteratorSortedCache::CanBeUsed(mrDoc, rParam))
+ if(ScCountIfCellIteratorSortedCache::CanBeUsed(mrDoc, rParam, pMyFormulaCell, refData))
{
ScCountIfCellIteratorSortedCache aCellIter(mrDoc, mrContext, nTab1, rParam, false);
fCount += aCellIter.GetCount();
@@ -5979,6 +5984,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf
ScMatrixRef pQueryMatrix;
while (nParam-- == nParamCount)
{
+ const ScComplexRefData* refData = nullptr;
switch ( GetStackType() )
{
case svRefList :
@@ -6015,12 +6021,14 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf
}
nRefArrayPos = nRefInList;
}
+ refData = GetStackDoubleRef(nRefInList);
ScRange aRange;
PopDoubleRef( aRange, nParam, nRefInList);
aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
}
break;
case svDoubleRef :
+ refData = GetStackDoubleRef();
PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
break;
case svSingleRef :
@@ -6150,7 +6158,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf
}
else
{
- if( ScQueryCellIteratorSortedCache::CanBeUsed( mrDoc, rParam ))
+ if( ScQueryCellIteratorSortedCache::CanBeUsed( mrDoc, rParam, pMyFormulaCell, refData ))
{
ScQueryCellIteratorSortedCache aCellIter(mrDoc, mrContext, nTab1, rParam, false);
// Increment Entry.nField in iterator when switching to next column.
@@ -7250,9 +7258,11 @@ void ScInterpreter::CalculateLookup(bool bHLookup)
SCTAB nTab1 = 0;
SCCOL nCol2 = 0;
SCROW nRow2 = 0;
+ const ScComplexRefData* refData = nullptr;
StackVar eType = GetStackType();
if (eType == svDoubleRef)
{
+ refData = GetStackDoubleRef(0);
SCTAB nTab2;
PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
if (nTab1 != nTab2)
@@ -7467,7 +7477,7 @@ void ScInterpreter::CalculateLookup(bool bHLookup)
else
{
ScAddress aResultPos( nCol1, nRow1, nTab1);
- bFound = LookupQueryWithCache( aResultPos, aParam);
+ bFound = LookupQueryWithCache( aResultPos, aParam, refData);
nRow = aResultPos.Row();
nCol = nSpIndex;
}
@@ -9967,7 +9977,8 @@ utl::SearchParam::SearchType ScInterpreter::DetectSearchType( std::u16string_vie
}
static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInterpreterContext& rContext,
- const ScQueryParam & rParam, const ScQueryEntry & rEntry )
+ const ScQueryParam & rParam, const ScQueryEntry & rEntry, const ScFormulaCell* cell,
+ const ScComplexRefData* refData )
{
if (rEntry.eOp != SC_EQUAL)
{
@@ -9984,7 +9995,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
}
else // EQUAL
{
- if( ScQueryCellIteratorSortedCache::CanBeUsed( rDoc, rParam ))
+ if( ScQueryCellIteratorSortedCache::CanBeUsed( rDoc, rParam, cell, refData ))
{
ScQueryCellIteratorSortedCache aCellIter( rDoc, rContext, rParam.nTab, rParam, false);
if (aCellIter.GetFirst())
@@ -10047,7 +10058,7 @@ static SCROW lcl_getPrevRowWithEmptyValueLookup( const ScLookupCache& rCache,
}
bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
- const ScQueryParam & rParam ) const
+ const ScQueryParam & rParam, const ScComplexRefData* refData ) const
{
bool bFound = false;
const ScQueryEntry& rEntry = rParam.GetEntry(0);
@@ -10060,7 +10071,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
* direct lookups here. We could even further attribute volatility per
* parameter so it would affect only the lookup range parameter. */
if (!bColumnsMatch || GetVolatileType() != NOT_VOLATILE)
- bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry);
+ bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry, pMyFormulaCell, refData);
else
{
ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab,
@@ -10091,7 +10102,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
{
case ScLookupCache::NOT_CACHED :
case ScLookupCache::CRITERIA_DIFFERENT :
- bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry);
+ bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry, pMyFormulaCell, refData);
if (eCacheResult == ScLookupCache::NOT_CACHED)
rCache.insert( o_rResultPos, aCriteria, aPos, bFound);
break;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 658cc2b5f9fd..540928f0bee6 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1114,6 +1114,29 @@ void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
SetError( FormulaError::UnknownStackVariable);
}
+const ScComplexRefData* ScInterpreter::GetStackDoubleRef(size_t rRefInList)
+{
+ if( sp )
+ {
+ const FormulaToken* p = pStack[ sp - 1 ];
+ switch (p->GetType())
+ {
+ case svDoubleRef:
+ return p->GetDoubleRef();
+ case svRefList:
+ {
+ const ScRefList* pList = p->GetRefList();
+ if (rRefInList < pList->size())
+ return &(*pList)[rRefInList];
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return nullptr;
+}
+
void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef)
{
if (!sp)