[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