[Libreoffice-commits] core.git: 2 commits - sc/inc sc/source
Luboš Luňák (via logerrit)
logerrit at kemper.freedesktop.org
Thu May 16 10:35:28 UTC 2019
sc/inc/cellvalue.hxx | 6 ++++++
sc/inc/column.hxx | 3 +++
sc/inc/document.hxx | 15 +++++++++++----
sc/inc/table.hxx | 5 ++++-
sc/source/core/data/cellvalue.cxx | 10 ++++++++++
sc/source/core/data/column.cxx | 10 ++++++++++
sc/source/core/data/column2.cxx | 16 ++++++++++++++++
sc/source/core/data/documen2.cxx | 8 ++++++++
sc/source/core/data/documen4.cxx | 11 ++++++++---
sc/source/core/data/documen6.cxx | 13 +++++++++----
sc/source/core/data/table1.cxx | 8 ++++++++
sc/source/core/data/table3.cxx | 29 ++++++++++++++++++++++++-----
sc/source/filter/html/htmlexp.cxx | 18 +++++++++++-------
sc/source/filter/inc/htmlexp.hxx | 6 +++++-
14 files changed, 133 insertions(+), 25 deletions(-)
New commits:
commit 6f810e3d7dafcd7d0101173a501786226f4d8886
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Wed May 15 13:13:31 2019 +0200
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Thu May 16 12:34:51 2019 +0200
optimize ScHTMLExport::WriteTables() with large columns
Again, unless given a hint, mdds always starts a search from the beginning
of the container, so iterating over a column becomes quadratic.
Shows when selecting (the title of) a large column with different value types,
e.g. in tdf#120558, which triggers setting the selection from
VclQt5Clipboard::setContents(), which calls this.
Change-Id: Ida009c5ddf18ccdc8dff88c15530cc7e33ce80e7
Reviewed-on: https://gerrit.libreoffice.org/72366
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak at collabora.com>
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index 7b6e3aad5794..281612d8874e 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -18,6 +18,10 @@ class EditTextObject;
class ScColumn;
struct ScRefCellValue;
+namespace sc {
+struct ColumnBlockPosition;
+}
+
namespace svl {
class SharedString;
@@ -117,6 +121,7 @@ struct SC_DLLPUBLIC ScRefCellValue
* Take cell value from specified position in specified document.
*/
ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos );
+ ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos );
void clear();
@@ -124,6 +129,7 @@ struct SC_DLLPUBLIC ScRefCellValue
* Take cell value from specified position in specified document.
*/
void assign( ScDocument& rDoc, const ScAddress& rPos );
+ void assign( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos );
/**
* Set cell value at specified position in specified document.
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 9a4d22a3e664..340b5628faf6 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -189,6 +189,7 @@ public:
const sc::CellNoteStoreType& GetCellNoteStore() const { return maCellNotes; }
ScRefCellValue GetCellValue( SCROW nRow ) const;
+ ScRefCellValue GetCellValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow );
ScRefCellValue GetCellValue( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const;
static ScRefCellValue GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index dd59a74c44e4..af372c270675 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1550,7 +1550,7 @@ public:
void CopyTabToClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
SCTAB nTab, ScDocument* pClipDoc);
- bool InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol );
+ SC_DLLPUBLIC bool InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol );
void DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScMarkData& rMark,
sc::ColumnSpanSet& rBroadcastSpans );
@@ -1692,7 +1692,9 @@ public:
void RemoveCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex );
SC_DLLPUBLIC ScConditionalFormat* GetCondFormat( SCCOL nCol, SCROW nRow, SCTAB nTab ) const;
- SC_DLLPUBLIC const SfxItemSet* GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const;
+ // pCell is an optimization, must point to rPos
+ SC_DLLPUBLIC const SfxItemSet* GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab,
+ ScRefCellValue* pCell = nullptr ) const;
const SfxItemSet* GetCondResult( ScRefCellValue& rCell, const ScAddress& rPos,
const ScConditionalFormatList& rList,
const ScCondFormatIndexes& rIndex ) const;
@@ -1705,8 +1707,12 @@ public:
SC_DLLPUBLIC const css::uno::Reference< css::i18n::XBreakIterator >& GetBreakIterator();
bool HasStringWeakCharacters( const OUString& rString );
SC_DLLPUBLIC SvtScriptType GetStringScriptType( const OUString& rString );
- SC_DLLPUBLIC SvtScriptType GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat );
- SC_DLLPUBLIC SvtScriptType GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab );
+ // pCell is an optimization, must point to rPos
+ SC_DLLPUBLIC SvtScriptType GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat,
+ ScRefCellValue* pCell = nullptr );
+ // pCell is an optimization, must point to nCol,nRow,nTab
+ SC_DLLPUBLIC SvtScriptType GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab,
+ ScRefCellValue* pCell = nullptr );
SvtScriptType GetRangeScriptType( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rPos, SCROW nLength );
SvtScriptType GetRangeScriptType( const ScRangeList& rRanges );
@@ -2527,6 +2533,7 @@ private:
bool HasPartOfMerged( const ScRange& rRange );
ScRefCellValue GetRefCellValue( const ScAddress& rPos );
+ ScRefCellValue GetRefCellValue( const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos );
std::map< SCTAB, ScSortParam > mSheetSortParams;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 59dc2bbfd7dc..29a7b28fe635 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -998,6 +998,7 @@ public:
void RegroupFormulaCells( SCCOL nCol );
ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow );
+ ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow, sc::ColumnBlockPosition& rBlockPos );
SvtBroadcaster* GetBroadcaster( SCCOL nCol, SCROW nRow );
const SvtBroadcaster* GetBroadcaster( SCCOL nCol, SCROW nRow ) const;
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index 7fffc669ee6c..ef662c4818f7 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -567,6 +567,11 @@ ScRefCellValue::ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos )
assign( rDoc, rPos);
}
+ScRefCellValue::ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos )
+{
+ assign( rDoc, rPos, rBlockPos );
+}
+
void ScRefCellValue::clear()
{
// Reset to empty value.
@@ -579,6 +584,11 @@ void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
*this = rDoc.GetRefCellValue(rPos);
}
+void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos )
+{
+ *this = rDoc.GetRefCellValue(rPos, rBlockPos);
+}
+
void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
{
switch (meType)
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 70ee70b8e1f4..548e6403cc8b 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -726,6 +726,16 @@ ScRefCellValue ScColumn::GetCellValue( SCROW nRow ) const
return GetCellValue(aPos.first, aPos.second);
}
+ScRefCellValue ScColumn::GetCellValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow )
+{
+ std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow);
+ if (aPos.first == maCells.end())
+ return ScRefCellValue();
+
+ rBlockPos.miCellPos = aPos.first; // Store this for next call.
+ return GetCellValue(aPos.first, aPos.second);
+}
+
ScRefCellValue ScColumn::GetCellValue( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const
{
std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow);
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 2ffbd7806549..56506490ec5d 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -529,6 +529,14 @@ ScRefCellValue ScDocument::GetRefCellValue( const ScAddress& rPos )
return maTabs[rPos.Tab()]->GetRefCellValue(rPos.Col(), rPos.Row());
}
+ScRefCellValue ScDocument::GetRefCellValue( const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos )
+{
+ if (!TableExists(rPos.Tab()))
+ return ScRefCellValue(); // empty
+
+ return maTabs[rPos.Tab()]->GetRefCellValue(rPos.Col(), rPos.Row(), rBlockPos);
+}
+
svl::SharedStringPool& ScDocument::GetSharedStringPool()
{
return *mpCellStringPool;
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index a1f5a6861db2..1d36d52e3bfb 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -782,19 +782,24 @@ const SfxPoolItem* ScDocument::GetEffItem(
return nullptr;
}
-const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
+const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab, ScRefCellValue* pCell ) const
{
ScConditionalFormatList* pFormatList = GetCondFormList(nTab);
if (!pFormatList)
return nullptr;
ScAddress aPos(nCol, nRow, nTab);
- ScRefCellValue aCell(const_cast<ScDocument&>(*this), aPos);
+ ScRefCellValue aCell;
+ if( pCell == nullptr )
+ {
+ aCell.assign(const_cast<ScDocument&>(*this), aPos);
+ pCell = &aCell;
+ }
const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
const ScCondFormatIndexes& rIndex =
pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
- return GetCondResult(aCell, aPos, *pFormatList, rIndex);
+ return GetCondResult(*pCell, aPos, *pFormatList, rIndex);
}
const SfxItemSet* ScDocument::GetCondResult(
diff --git a/sc/source/core/data/documen6.cxx b/sc/source/core/data/documen6.cxx
index 4076cef8a2f4..9dd1f8b523a3 100644
--- a/sc/source/core/data/documen6.cxx
+++ b/sc/source/core/data/documen6.cxx
@@ -108,14 +108,19 @@ SvtScriptType ScDocument::GetStringScriptType( const OUString& rString )
return nRet;
}
-SvtScriptType ScDocument::GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat )
+SvtScriptType ScDocument::GetCellScriptType( const ScAddress& rPos, sal_uInt32 nNumberFormat,
+ ScRefCellValue* pCell )
{
SvtScriptType nStored = GetScriptType(rPos);
if ( nStored != SvtScriptType::UNKNOWN ) // stored value valid?
return nStored; // use stored value
Color* pColor;
- OUString aStr = ScCellFormat::GetString(*this, rPos, nNumberFormat, &pColor, *mxPoolHelper->GetFormTable());
+ OUString aStr;
+ if( pCell )
+ ScCellFormat::GetString(*pCell, nNumberFormat, aStr, &pColor, *mxPoolHelper->GetFormTable(), this);
+ else
+ ScCellFormat::GetString(*this, rPos, nNumberFormat, &pColor, *mxPoolHelper->GetFormTable());
SvtScriptType nRet = GetStringScriptType( aStr );
@@ -124,7 +129,7 @@ SvtScriptType ScDocument::GetCellScriptType( const ScAddress& rPos, sal_uInt32 n
return nRet;
}
-SvtScriptType ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab )
+SvtScriptType ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab, ScRefCellValue* pCell )
{
// if script type is set, don't have to get number formats
@@ -143,7 +148,7 @@ SvtScriptType ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab )
sal_uInt32 nFormat = pPattern->GetNumberFormat( mxPoolHelper->GetFormTable(), pCondSet );
- return GetCellScriptType(aPos, nFormat);
+ return GetCellScriptType(aPos, nFormat, pCell);
}
namespace {
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index c18c039c46db..be7d12b50150 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2421,6 +2421,14 @@ ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow )
return aCol[nCol].GetCellValue(nRow);
}
+ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow, sc::ColumnBlockPosition& rBlockPos )
+{
+ if ( !IsColRowValid( nCol, nRow ) )
+ return ScRefCellValue();
+
+ return aCol[nCol].GetCellValue(rBlockPos, nRow);
+}
+
SvtBroadcaster* ScTable::GetBroadcaster( SCCOL nCol, SCROW nRow )
{
if ( !IsColRowValid( nCol, nRow ) )
diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx
index ea7ae4c025da..8b9a5ade838b 100644
--- a/sc/source/filter/html/htmlexp.cxx
+++ b/sc/source/filter/html/htmlexp.cxx
@@ -59,6 +59,7 @@
#include <editutil.hxx>
#include <ftools.hxx>
#include <cellvalue.hxx>
+#include <mtvelements.hxx>
#include <editeng/flditem.hxx>
#include <editeng/borderline.hxx>
@@ -764,6 +765,10 @@ void ScHTMLExport::WriteTables()
// At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and
// <COL WIDTH=x> specified, but needs a width at every column.
bool bHasHiddenRows = pDoc->HasHiddenRows(nStartRow, nEndRow, nTab);
+ // We need to cache sc::ColumnBlockPosition per each column.
+ std::vector< sc::ColumnBlockPosition > blockPos( nEndCol - nStartCol + 1 );
+ for( SCCOL i = nStartCol; i <= nEndCol; ++i )
+ pDoc->InitColumnBlockPosition( blockPos[ i - nStartCol ], nTab, i );
for ( SCROW nRow=nStartRow; nRow<=nEndRow; nRow++ )
{
if ( bHasHiddenRows && pDoc->RowHidden(nRow, nTab) )
@@ -782,7 +787,7 @@ void ScHTMLExport::WriteTables()
if ( nCol2 == nEndCol )
IncIndent(-1);
- WriteCell( nCol2, nRow, nTab );
+ WriteCell( blockPos[ nCol2 - nStartCol ], nCol2, nRow, nTab );
bTableDataHeight = false;
}
@@ -822,16 +827,17 @@ void ScHTMLExport::WriteTables()
}
}
-void ScHTMLExport::WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
+void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow, SCTAB nTab )
{
+ ScAddress aPos( nCol, nRow, nTab );
+ ScRefCellValue aCell(*pDoc, aPos, rBlockPos);
const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
- const SfxItemSet* pCondItemSet = pDoc->GetCondResult( nCol, nRow, nTab );
+ const SfxItemSet* pCondItemSet = pDoc->GetCondResult( nCol, nRow, nTab, &aCell );
const ScMergeFlagAttr& rMergeFlagAttr = pAttr->GetItem( ATTR_MERGE_FLAG, pCondItemSet );
if ( rMergeFlagAttr.IsOverlapped() )
return ;
- ScAddress aPos( nCol, nRow, nTab );
ScHTMLGraphEntry* pGraphEntry = nullptr;
if ( bTabHasGraphics && !mbSkipImages )
{
@@ -852,13 +858,11 @@ void ScHTMLExport::WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
}
}
- ScRefCellValue aCell(*pDoc, aPos);
-
sal_uInt32 nFormat = pAttr->GetNumberFormat( pFormatter );
bool bValueData = aCell.hasNumeric();
SvtScriptType nScriptType = SvtScriptType::NONE;
if (!aCell.isEmpty())
- nScriptType = pDoc->GetScriptType(nCol, nRow, nTab);
+ nScriptType = pDoc->GetScriptType(nCol, nRow, nTab, &aCell);
if ( nScriptType == SvtScriptType::NONE )
nScriptType = aHTMLStyle.nDefaultScriptType;
diff --git a/sc/source/filter/inc/htmlexp.hxx b/sc/source/filter/inc/htmlexp.hxx
index f0507cc1738d..8642795baa8a 100644
--- a/sc/source/filter/inc/htmlexp.hxx
+++ b/sc/source/filter/inc/htmlexp.hxx
@@ -42,6 +42,10 @@ class EditTextObject;
enum class SvtScriptType;
namespace editeng { class SvxBorderLine; }
+namespace sc {
+struct ColumnBlockPosition;
+}
+
struct ScHTMLStyle
{ // Defaults from stylesheet
Color aBackgroundColor;
@@ -133,7 +137,7 @@ class ScHTMLExport : public ScExportBase
void WriteHeader();
void WriteOverview();
void WriteTables();
- void WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab );
+ void WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow, SCTAB nTab );
void WriteGraphEntry( ScHTMLGraphEntry* );
void WriteImage( OUString& rLinkName,
const Graphic&, const OString& rImgOptions,
commit ace16e500c92797bb47ad580cf535de0702137bd
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Wed May 15 15:58:46 2019 +0200
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Thu May 16 12:34:42 2019 +0200
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 at collabora.com>
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index f55bc63b9541..9a4d22a3e664 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -218,6 +218,8 @@ public:
bool bConsiderCellDrawObjects=false) const;
bool HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, bool bConsiderCellNotes=false,
bool bConsiderCellDrawObjects=false) const;
+ bool HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow, bool bConsiderCellNotes=false,
+ bool bConsiderCellDrawObjects=false);
bool HasVisibleDataAt(SCROW nRow) const;
SCROW GetFirstDataPos() const;
SCROW GetLastDataPos() const;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 547d9936e44b..59dc2bbfd7dc 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -64,6 +64,7 @@ class ColumnSpanSet;
class RangeColumnSpanSet;
class ColumnSet;
struct ColumnBlockPosition;
+class TableColumnBlockPositionSet;
struct RefUpdateContext;
struct RefUpdateInsertTabContext;
struct RefUpdateDeleteTabContext;
@@ -930,7 +931,8 @@ public:
bool ValidQuery(
SCROW nRow, const ScQueryParam& rQueryParam, const ScRefCellValue* pCell = nullptr,
- bool* pbTestEqualCondition = nullptr, const ScInterpreterContext* pContext = nullptr);
+ bool* pbTestEqualCondition = nullptr, const ScInterpreterContext* pContext = nullptr,
+ sc::TableColumnBlockPositionSet* pBlockPos = nullptr );
void TopTenQuery( ScQueryParam& );
SCSIZE Query(const ScQueryParam& rQueryParam, bool bKeepSub);
bool CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
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++)
More information about the Libreoffice-commits
mailing list