summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/queryiter.hxx6
-rw-r--r--sc/qa/unit/ucalc_sort.cxx80
-rw-r--r--sc/source/core/data/queryiter.cxx54
3 files changed, 121 insertions, 19 deletions
diff --git a/sc/inc/queryiter.hxx b/sc/inc/queryiter.hxx
index e247a471db65..847241124a2e 100644
--- a/sc/inc/queryiter.hxx
+++ b/sc/inc/queryiter.hxx
@@ -140,9 +140,9 @@ protected:
void PerformQuery();
/* Only works if no regular expression is involved, only searches for rows in one column,
- and only the first query entry is considered with simple conditions SC_LESS_EQUAL
- (sorted ascending) or SC_GREATER_EQUAL (sorted descending). Delivers a starting point,
- continue with e.g. GetThis() and GetNext() afterwards. Introduced
+ and only the first query entry is considered with simple conditions SC_LESS,SC_LESS_EQUAL,
+ SC_EQUAL (sorted ascending) or SC_GREATER,SC_GREATER_EQUAL (sorted descending). Delivers
+ a starting point, continue with e.g. GetThis() and GetNext() afterwards. Introduced
for FindEqualOrSortedLastInRange(). */
bool BinarySearch();
diff --git a/sc/qa/unit/ucalc_sort.cxx b/sc/qa/unit/ucalc_sort.cxx
index 698cbb1bde97..e99b0a38cec3 100644
--- a/sc/qa/unit/ucalc_sort.cxx
+++ b/sc/qa/unit/ucalc_sort.cxx
@@ -2102,6 +2102,18 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(8), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_LESS, 5 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(2), it.GetRow());
+ }
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_EQUAL, 5 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(8), it.GetRow());
+ }
{
// Descending, this should return the last 5.
@@ -2114,6 +2126,12 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(6), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, descendingCol, SC_GREATER, 5 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(1), it.GetRow());
+ }
{
// There's no 6, so this should return the last 5.
@@ -2126,6 +2144,18 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(8), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_LESS, 6 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(8), it.GetRow());
+ }
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_EQUAL, 6 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(8), it.GetRow());
+ }
{
// Descending, there's no 6, so this should return the last 9.
@@ -2138,6 +2168,12 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(1), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, descendingCol, SC_GREATER, 6 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(1), it.GetRow());
+ }
{
// All values are larger than 0, so this should be an error.
@@ -2150,6 +2186,18 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(0), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_LESS, 0 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(0), it.GetRow());
+ }
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_EQUAL, 0 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(0), it.GetRow());
+ }
{
// Descending, all values are larger than 0, so this should return the last item.
@@ -2162,6 +2210,12 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, descendingCol, SC_GREATER, 0 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
+ }
{
// All values are smaller than 10, so this should return the last item.
@@ -2174,6 +2228,18 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_LESS, 10 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
+ }
+ {
+ ScQueryParam param = makeSearchParam( range, ascendingCol, SC_EQUAL, 10 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
+ }
{
// Descending, all values are smaller than 10, so this should be an error.
@@ -2186,6 +2252,12 @@ void TestSort::testQueryBinarySearch()
CPPUNIT_ASSERT(it.BinarySearch());
CPPUNIT_ASSERT_EQUAL(SCROW(0), it.GetRow());
}
+ {
+ ScQueryParam param = makeSearchParam( range, descendingCol, SC_GREATER, 10 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ CPPUNIT_ASSERT_EQUAL(SCROW(0), it.GetRow());
+ }
{
// Search as ascending but use descending range (=search will not work).
@@ -2203,6 +2275,14 @@ void TestSort::testQueryBinarySearch()
// CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
}
+ {
+ // SC_EQUAL with descending is considered an error.
+ ScQueryParam param = makeSearchParam( range, descendingCol, SC_EQUAL, 9 );
+ TestQueryIterator it( *m_pDoc, m_pDoc->GetNonThreadedContext(), 0, param, false );
+ CPPUNIT_ASSERT(it.BinarySearch());
+ // CPPUNIT_ASSERT_EQUAL(SCROW(10), it.GetRow());
+ }
+
m_pDoc->DeleteTab(0);
}
diff --git a/sc/source/core/data/queryiter.cxx b/sc/source/core/data/queryiter.cxx
index 60d62ad2da60..73a700f108f8 100644
--- a/sc/source/core/data/queryiter.cxx
+++ b/sc/source/core/data/queryiter.cxx
@@ -283,7 +283,9 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
assert(maParam.GetEntry(0).GetQueryItem().meType == ScQueryEntry::ByString
|| maParam.GetEntry(0).GetQueryItem().meType == ScQueryEntry::ByValue);
assert(maParam.bByRow);
- assert(maParam.GetEntry(0).eOp == SC_LESS_EQUAL || maParam.GetEntry(0).eOp == SC_GREATER_EQUAL);
+ assert(maParam.GetEntry(0).eOp == SC_LESS || maParam.GetEntry(0).eOp == SC_LESS_EQUAL
+ || maParam.GetEntry(0).eOp == SC_GREATER || maParam.GetEntry(0).eOp == SC_GREATER_EQUAL
+ || maParam.GetEntry(0).eOp == SC_EQUAL);
// TODO: This will be extremely slow with mdds::multi_type_vector.
@@ -301,7 +303,7 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
SvNumberFormatter& rFormatter = *(mrContext.GetFormatTable());
const ScQueryEntry& rEntry = maParam.GetEntry(0);
const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
- bool bLessEqual = rEntry.eOp == SC_LESS_EQUAL;
+ bool bAscending = rEntry.eOp == SC_LESS || rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_EQUAL;
bool bByString = rItem.meType == ScQueryEntry::ByString;
bool bAllStringIgnore = bIgnoreMismatchOnLeadingStrings && !bByString;
bool bFirstStringIgnore = bIgnoreMismatchOnLeadingStrings &&
@@ -323,7 +325,9 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
sal_Int32 nTmp = rCollator.compareString(aCellStr, rEntry.GetQueryItem().maString.getString());
if ((rEntry.eOp == SC_LESS_EQUAL && nTmp > 0) ||
(rEntry.eOp == SC_GREATER_EQUAL && nTmp < 0) ||
- (rEntry.eOp == SC_EQUAL && nTmp != 0))
+ (rEntry.eOp == SC_EQUAL && nTmp != 0) ||
+ (rEntry.eOp == SC_LESS && nTmp >= 0) ||
+ (rEntry.eOp == SC_GREATER && nTmp <= 0))
++nRow;
}
}
@@ -361,11 +365,11 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
// range isn't strictly sorted.
size_t nLastInRange = nLo;
size_t nFirstLastInRange = nLastInRange;
- double fLastInRangeValue = bLessEqual ?
+ double fLastInRangeValue = bAscending ?
-(::std::numeric_limits<double>::max()) :
::std::numeric_limits<double>::max();
OUString aLastInRangeString;
- if (!bLessEqual)
+ if (!bAscending)
aLastInRangeString = OUString(u'\xFFFF');
aCellData = aIndexer.getCell(nLastInRange);
@@ -424,7 +428,7 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
nCellVal, rItem.mfVal))
{
nRes = -1;
- if (bLessEqual)
+ if (bAscending)
{
if (fLastInRangeValue <= nCellVal)
{
@@ -443,7 +447,7 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
nCellVal, rItem.mfVal))
{
nRes = 1;
- if (!bLessEqual)
+ if (!bAscending)
{
if (fLastInRangeValue >= nCellVal)
{
@@ -465,7 +469,7 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
OUString aCellStr = ScCellFormat::GetInputString(aCell, nFormat, rFormatter, rDoc);
nRes = rCollator.compareString(aCellStr, rEntry.GetQueryItem().maString.getString());
- if (nRes < 0 && bLessEqual)
+ if (nRes < 0 && bAscending)
{
sal_Int32 nTmp = rCollator.compareString( aLastInRangeString,
aCellStr);
@@ -481,7 +485,7 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
bDone = true;
}
}
- else if (nRes > 0 && !bLessEqual)
+ else if (nRes > 0 && !bAscending)
{
sal_Int32 nTmp = rCollator.compareString( aLastInRangeString,
aCellStr);
@@ -501,18 +505,18 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
else if (!bStr && bByString)
{
nRes = -1; // numeric < string
- if (bLessEqual)
+ if (bAscending)
nLastInRange = i;
}
else // if (bStr && !bByString)
{
nRes = 1; // string > numeric
- if (!bLessEqual)
+ if (!bAscending)
nLastInRange = i;
}
if (nRes < 0)
{
- if (bLessEqual)
+ if (bAscending)
nLo = nMid + 1;
else // assumed to be SC_GREATER_EQUAL
{
@@ -524,7 +528,7 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
}
else if (nRes > 0)
{
- if (bLessEqual)
+ if (bAscending)
{
if (nMid > 0)
nHi = nMid - 1;
@@ -536,9 +540,27 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch()
}
else
{
- found = i;
- // But keep searching to find the last matching one.
- nLo = nMid + 1;
+ if(rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL || rEntry.eOp == SC_EQUAL)
+ {
+ found = i;
+ nLastInRange = i;
+ // But keep searching to find the last matching one.
+ nLo = nMid + 1;
+ }
+ else if (bAscending)
+ {
+ if (nMid > 0)
+ nHi = nMid - 1;
+ else
+ bDone = true;
+ }
+ else
+ {
+ if (nMid > 0)
+ nHi = nMid - 1;
+ else
+ bDone = true;
+ }
}
}