summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2019-05-15 15:58:46 +0200
committerLuboš Luňák <l.lunak@collabora.com>2019-05-16 12:34:42 +0200
commitace16e500c92797bb47ad580cf535de0702137bd (patch)
tree165eb099aa0bb9eeadaf4806b8e98e52739aa05e /sc/source
parent0d58f51d7672c569c93c6e814dbfffa586eebfb7 (diff)
cache mdds access in ScTable::ValidQuery() (tdf#80853)
Once more, mdds always searches from the start of the container, so iterating is quadratic. Change-Id: I8f8f3b5aad5c3342a10c21df3ad2d0d3fcaea8ad Reviewed-on: https://gerrit.libreoffice.org/72368 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/column2.cxx16
-rw-r--r--sc/source/core/data/table3.cxx29
2 files changed, 40 insertions, 5 deletions
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 25680418ca39..d8e2646d99f5 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -3100,6 +3100,22 @@ bool ScColumn::HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow,
return aPos.first->type != sc::element_type_empty;
}
+bool ScColumn::HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow,
+ bool bConsiderCellNotes, bool bConsiderCellDrawObjects)
+{
+ if (bConsiderCellNotes && !IsNotesEmptyBlock(nRow, nRow))
+ return true;
+
+ if (bConsiderCellDrawObjects && !IsDrawObjectsEmptyBlock(nRow, nRow))
+ return true;
+
+ std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow);
+ if (aPos.first == maCells.end())
+ return false;
+ rBlockPos.miCellPos = aPos.first; // Store this for next call.
+ return aPos.first->type != sc::element_type_empty;
+}
+
bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
{
if (pAttrArray && rCol.pAttrArray)
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index d04d704937d2..da1e5e981753 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -2729,7 +2729,7 @@ public:
bool ScTable::ValidQuery(
SCROW nRow, const ScQueryParam& rParam, const ScRefCellValue* pCell, bool* pbTestEqualCondition,
- const ScInterpreterContext* pContext)
+ const ScInterpreterContext* pContext, sc::TableColumnBlockPositionSet* pBlockPos)
{
if (!rParam.GetEntry(0).bDoQuery)
return true;
@@ -2753,19 +2753,36 @@ bool ScTable::ValidQuery(
// We can only handle one single direct query passed as a known pCell,
// subsequent queries have to obtain the cell.
- ScRefCellValue aCell( (pCell && it == itBeg) ? *pCell : GetCellValue(nCol, nRow));
+ ScRefCellValue aCell;
+ if(pCell && it == itBeg)
+ aCell = *pCell;
+ else if( pBlockPos )
+ { // hinted mdds access
+ ScColumn* column = FetchColumn(nCol);
+ aCell = column->GetCellValue(*pBlockPos->getBlockPosition( nCol ), nRow);
+ }
+ else
+ aCell = GetCellValue(nCol, nRow);
std::pair<bool,bool> aRes(false, false);
const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
if (rItems.size() == 1 && rItems.front().meType == ScQueryEntry::ByEmpty)
{
+ bool hasData;
+ if( pBlockPos )
+ {
+ ScColumn* column = FetchColumn(rEntry.nField);
+ hasData = column->HasDataAt(*pBlockPos->getBlockPosition(rEntry.nField), nRow);
+ }
+ else
+ hasData = aCol[rEntry.nField].HasDataAt(nRow);
if (rEntry.IsQueryByEmpty())
- aRes.first = !aCol[rEntry.nField].HasDataAt(nRow);
+ aRes.first = !hasData;
else
{
assert(rEntry.IsQueryByNonEmpty());
- aRes.first = aCol[rEntry.nField].HasDataAt(nRow);
+ aRes.first = hasData;
}
}
else
@@ -3056,11 +3073,13 @@ SCSIZE ScTable::Query(const ScQueryParam& rParamOrg, bool bKeepSub)
aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
}
+ sc::TableColumnBlockPositionSet blockPos( GetDoc(), nTab ); // cache mdds access
+
SCROW nRealRow2 = aParam.nRow2;
for (SCROW j = aParam.nRow1 + nHeader; j <= nRealRow2; ++j)
{
bool bResult; // Filter result
- bool bValid = ValidQuery(j, aParam);
+ bool bValid = ValidQuery(j, aParam, nullptr, nullptr, nullptr, &blockPos);
if (!bValid && bKeepSub) // Keep subtotals
{
for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++)