diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2019-05-15 15:58:46 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2019-05-16 12:34:42 +0200 |
commit | ace16e500c92797bb47ad580cf535de0702137bd (patch) | |
tree | 165eb099aa0bb9eeadaf4806b8e98e52739aa05e /sc/source | |
parent | 0d58f51d7672c569c93c6e814dbfffa586eebfb7 (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.cxx | 16 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 29 |
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++) |