LibreOffice Module sc (master) 1
queryiter.hxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#pragma once
21
22#include "address.hxx"
23#include "global.hxx"
24#include "scdllapi.h"
25#include "queryparam.hxx"
26#include "mtvelements.hxx"
27#include "types.hxx"
28
29struct ScComplexRefData;
31
32/*
33Query-related iterators. There is one template class ScQueryCellIteratorBase
34that implements most of the shared functionality, specific parts are done
35by specializing the templates and then subclassing as the actual class to use.
36A template is used for maximum performance, as that allows fast code specializing,
37inlining, etc.
38There are two template arguments:
39* ScQueryCellIteratorAccess specifies how cells are accessed:
40 + Direct - direct access to cells using mdds.
41 + SortedCache - for accessing unsorted cells in a sorted way using ScSortedRangeCache.
42* ScQueryCellIteratorType specifies the type of the query operation:
43 + Generic - the generic lookup, used e.g. by VLOOKUP.
44 + CountIf - faster implementation for COUNTIF(S).
45
46Specific data should be in specific templated base classes, otherwise adding data
47members would mean specializing the entire ScQueryCellIteratorBase. Some specific
48functionality may also be implemented in the base classes or depending on the template
49parameter.
50*/
51
52// Data and functionality for accessing cells in a specific way.
53// Needs specialization, see ScQueryCellIteratorAccess::Direct for what is needed.
54template< ScQueryCellIteratorAccess accessType >
56{
57};
58
59// The implementation using linear direct mdds access.
60template<>
62{
63protected:
65 const ScQueryParam& rParam );
66 // Initialize position for new column.
67 void InitPos();
68 // Increase position (next row).
69 void IncPos();
70 // Next mdds block. If access is not direct/linear, then
71 // should call IncPos().
72 void IncBlock();
73
74 // These members needs to be available already in the base class.
75 typedef sc::CellStoreType::const_position_type PositionType;
83
84 class NonEmptyCellIndexer;
85 typedef std::pair<ScRefCellValue, SCROW> BinarySearchCellType;
86 static NonEmptyCellIndexer MakeBinarySearchIndexer(const sc::CellStoreType& rCells,
87 SCROW nStartRow, SCROW nEndRow);
88};
89
90// The implementation using ScSortedRangeCache, which allows sorted iteration
91// of unsorted cells.
92template<>
94{
95public:
96 void SetSortedRangeCache( const ScSortedRangeCache& cache );
97 template<bool fast>
98 bool IncPosImpl();
99protected:
101 const ScQueryParam& rParam );
102 void InitPosStart();
103 void InitPosFinish( SCROW beforeRow, SCROW lastRow );
104 void IncPos() { IncPosImpl<false>(); }
105 bool IncPosFast() { return IncPosImpl<true>(); }
106 void IncBlock() { IncPos(); } // Cannot skip entire block, not linear.
107
108 // These members needs to be available already in the base class.
109 typedef sc::CellStoreType::const_position_type PositionType;
117 const ScColumn* pColumn; // matching nCol, set by InitPos()
118
122
123 class SortedCacheIndexer;
124 typedef std::pair<ScRefCellValue, SCROW> BinarySearchCellType;
125 SortedCacheIndexer MakeBinarySearchIndexer(const sc::CellStoreType& rCells,
126 SCROW nStartRow, SCROW nEndRow);
127};
128
129// Data and functionality for specific types of query.
130template< ScQueryCellIteratorType iteratorType >
132{
133protected:
134 bool HandleItemFound(); // not implemented, needs specialization
135};
136
137// Shared code for query-based iterators. The main class.
138template< ScQueryCellIteratorAccess accessType, ScQueryCellIteratorType queryType >
140 : public ScQueryCellIteratorAccessSpecific< accessType >
141 , public ScQueryCellIteratorTypeSpecific< queryType >
142{
145protected:
147 {
152 };
153
155 {
160 };
161
166
167 // Make base members directly visible here (templated bases need 'this->').
168 using AccessBase::maCurPos;
169 using AccessBase::maParam;
170 using AccessBase::rDoc;
171 using AccessBase::mrContext;
172 using AccessBase::nTab;
173 using AccessBase::nCol;
174 using AccessBase::nRow;
175 using AccessBase::IncPos;
176 using AccessBase::IncBlock;
177 using typename AccessBase::BinarySearchCellType;
178 using AccessBase::MakeBinarySearchIndexer;
180
181 void InitPos();
182
183 // The actual query function. It will call HandleItemFound() for any matching type
184 // and return if HandleItemFound() returns true.
185 void PerformQuery();
186
187 /* Only works if no regular expression is involved, only searches for rows in one column,
188 and only the first query entry is considered with simple conditions SC_LESS,SC_LESS_EQUAL,
189 SC_EQUAL (sorted ascending) or SC_GREATER,SC_GREATER_EQUAL (sorted descending). It
190 delivers a starting point set to nRow, i.e. the last row that either matches the searched
191 for value, or the last row that matches the condition. Continue with e.g. GetThis() and
192 GetNext() afterwards. Returns false if the searched for value is not in the search range
193 or if the range is not properly sorted, with nRow in that case set to the first row or after
194 the last row. In that case use GetFirst().
195 */
196 bool BinarySearch( SCCOL col, bool forEqual = false );
197
208 void SetStopOnMismatch( bool bVal )
209 {
210 nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled :
212 }
213 bool StoppedOnMismatch() const
215
221 void SetTestEqualCondition( bool bVal )
222 {
223 nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ?
226 }
229
230public:
231 ScQueryCellIteratorBase(ScDocument& rDocument, ScInterpreterContext& rContext, SCTAB nTable,
232 const ScQueryParam& aParam, bool bMod);
233 // when !bMod, the QueryParam has to be filled
234 // (bIsString)
235
236 // increments all Entry.nField, if column
237 // changes, for ScInterpreter ScHLookup()
239 { bAdvanceQuery = bVal; }
241};
242
243
244template<>
246{
247protected:
248 bool HandleItemFound();
250};
251
252// The generic query iterator, used e.g. by VLOOKUP.
253template< ScQueryCellIteratorAccess accessType >
255 : public ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::Generic >
256{
258 // Make base members directly visible here (templated bases need 'this->').
259 using Base::maParam;
260 using Base::rDoc;
261 using Base::mrContext;
262 using Base::nTab;
263 using Base::nCol;
264 using Base::nRow;
265 using Base::InitPos;
266 using Base::IncPos;
270 using Base::BinarySearch;
271 using typename Base::PositionType;
272 using Base::maCurPos;
280 using Base::PerformQuery;
281 using Base::getThisResult;
282
283 bool GetThis();
284
285public:
287 const ScQueryParam& aParam, bool bMod)
288 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
289 bool GetFirst();
290 bool GetNext();
291 SCCOL GetCol() const { return nCol; }
292 SCROW GetRow() const { return nRow; }
293
312 bool FindEqualOrSortedLastInRange( SCCOL& nFoundCol, SCROW& nFoundRow );
313};
314
316
318 : public ScQueryCellIterator< ScQueryCellIteratorAccess::SortedCache >
319{
321public:
323 SCTAB nTable, const ScQueryParam& aParam, bool bMod)
324 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
325 // Returns true if this iterator can be used for the given query.
326 static bool CanBeUsed(ScDocument& rDoc, const ScQueryParam& aParam,
327 SCTAB nTab, const ScFormulaCell* cell, const ScComplexRefData* refData,
328 ScInterpreterContext& context);
329};
330
331
332template<>
334{
335protected:
336 bool HandleItemFound();
337 sal_uInt64 countIfCount;
338};
339
340// Used by ScInterpreter::ScCountIf.
341template< ScQueryCellIteratorAccess accessType >
343 : public ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::CountIf >
344{
345protected:
347 // Make base members directly visible here (templated bases need 'this->').
348 using Base::maParam;
349 using Base::rDoc;
350 using Base::nTab;
351 using Base::nCol;
352 using Base::nRow;
353 using Base::InitPos;
354 using Base::PerformQuery;
356 using Base::countIfCount;
357
358public:
360 const ScQueryParam& aParam, bool bMod)
361 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
362 sal_uInt64 GetCount();
363};
364
366
368 : public ScCountIfCellIterator< ScQueryCellIteratorAccess::SortedCache >
369{
371public:
373 SCTAB nTable, const ScQueryParam& aParam, bool bMod)
374 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
375 // Returns true if this iterator can be used for the given query.
376 static bool CanBeUsed(ScDocument& rDoc, const ScQueryParam& aParam,
377 SCTAB nTab, const ScFormulaCell* cell, const ScComplexRefData* refData,
378 ScInterpreterContext& context);
379};
380
381/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool CanBeUsed(ScDocument &rDoc, const ScQueryParam &aParam, SCTAB nTab, const ScFormulaCell *cell, const ScComplexRefData *refData, ScInterpreterContext &context)
Definition: queryiter.cxx:1370
ScCountIfCellIterator< ScQueryCellIteratorAccess::SortedCache > Base
Definition: queryiter.hxx:370
ScCountIfCellIteratorSortedCache(ScDocument &rDocument, ScInterpreterContext &rContext, SCTAB nTable, const ScQueryParam &aParam, bool bMod)
Definition: queryiter.hxx:372
sal_uInt64 GetCount()
Definition: queryiter.cxx:1355
ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::CountIf > Base
Definition: queryiter.hxx:346
ScCountIfCellIterator(ScDocument &rDocument, ScInterpreterContext &rContext, SCTAB nTable, const ScQueryParam &aParam, bool bMod)
Definition: queryiter.hxx:359
ScQueryCellIteratorTypeSpecific< queryType > TypeBase
Definition: queryiter.hxx:144
bool BinarySearch(SCCOL col, bool forEqual=false)
Definition: queryiter.cxx:329
bool IsEqualConditionFulfilled() const
Definition: queryiter.hxx:227
sal_uInt8 nTestEqualCondition
Definition: queryiter.hxx:163
ScQueryCellIteratorBase(ScDocument &rDocument, ScInterpreterContext &rContext, SCTAB nTable, const ScQueryParam &aParam, bool bMod)
Definition: queryiter.cxx:63
ScQueryCellIteratorAccessSpecific< accessType > AccessBase
Definition: queryiter.hxx:143
void SetTestEqualCondition(bool bVal)
If set, an additional test for SC_EQUAL condition is executed in ScTable::ValidQuery() if SC_LESS_EQU...
Definition: queryiter.hxx:221
void SetAdvanceQueryParamEntryField(bool bVal)
Definition: queryiter.hxx:238
void AdvanceQueryParamEntryField()
Definition: queryiter.cxx:288
void SetStopOnMismatch(bool bVal)
If set, iterator stops on first non-matching cell content.
Definition: queryiter.hxx:208
bool StoppedOnMismatch() const
Definition: queryiter.hxx:213
ScQueryCellIterator< ScQueryCellIteratorAccess::SortedCache > Base
Definition: queryiter.hxx:320
ScQueryCellIteratorSortedCache(ScDocument &rDocument, ScInterpreterContext &rContext, SCTAB nTable, const ScQueryParam &aParam, bool bMod)
Definition: queryiter.hxx:322
static bool CanBeUsed(ScDocument &rDoc, const ScQueryParam &aParam, SCTAB nTab, const ScFormulaCell *cell, const ScComplexRefData *refData, ScInterpreterContext &context)
Definition: queryiter.cxx:1339
ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::Generic > Base
Definition: queryiter.hxx:257
ScQueryCellIterator(ScDocument &rDocument, ScInterpreterContext &rContext, SCTAB nTable, const ScQueryParam &aParam, bool bMod)
Definition: queryiter.hxx:286
SCROW GetRow() const
Definition: queryiter.hxx:292
SCCOL GetCol() const
Definition: queryiter.hxx:291
bool FindEqualOrSortedLastInRange(SCCOL &nFoundCol, SCROW &nFoundRow)
In a range assumed to be sorted find either the last of a sequence of equal entries or the last being...
Definition: queryiter.cxx:667
Sorted cache for one range used with interpreter functions such as VLOOKUP and MATCH.
Definition: rangecache.hxx:45
mdds::mtv::soa::multi_type_vector< CellFunc, CellStoreTrait > CellStoreType
ScQueryCellIterator< ScQueryCellIteratorAccess::Direct > ScQueryCellIteratorDirect
Definition: queryiter.hxx:315
ScCountIfCellIterator< ScQueryCellIteratorAccess::Direct > ScCountIfCellIteratorDirect
Definition: queryiter.hxx:365
Complex reference (a range) into the sheet.
Definition: refdata.hxx:123
unsigned char sal_uInt8
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
ScQueryCellIteratorAccess
Definition: types.hxx:145
ScQueryCellIteratorType
Definition: types.hxx:138
sal_Int32 SCROW
Definition: types.hxx:17