1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Fix the skip-ahead-distinct optimization so that it works with indexes that

have repeated columns with different collating sequences.

FossilOrigin-Name: ce1e2b88777e00a82c04abe5ba35eec81b5f324e462f099cd00b21054f369688
This commit is contained in:
drh
2017-04-13 21:29:02 +00:00
parent c04ea80f64
commit 172806e489
5 changed files with 58 additions and 48 deletions

View File

@@ -1,5 +1,5 @@
C Simplification\sof\sthe\sskip-ahead-distinct\slogic.\s\sThere\sis\sstill\san\sissue\nwith\shandling\sCOLLATE.
D 2017-04-13T19:48:29.675
C Fix\sthe\sskip-ahead-distinct\soptimization\sso\sthat\sit\sworks\swith\sindexes\sthat\nhave\srepeated\scolumns\swith\sdifferent\scollating\ssequences.
D 2017-04-13T21:29:02.792
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
@@ -482,8 +482,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
F src/where.c 2b88a9abe28584178a395f286479dda0b103a758c3bf3c70e52a0560f40b467d
F src/whereInt.h 7a21ef633e26acbf46df04add2eba6e0a2100c78dc5879049e93f981fc3344df
F src/where.c 911bf344a45e63528933d92ba2574a8382ed2dcd980960888ad809e1b76a1068
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -658,7 +658,7 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c
F test/distinct2.test 5bf7cb4233222cf275b72bcde9149107d300297dd88711aa7f7902d4884b6730
F test/distinct2.test faef8a3f27424e2cfbe19b2a40752294de3b5d957e049e3336be53ec0476cb58
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
@@ -1572,7 +1572,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 70ac9ea1a6cb2f4906f00f1a04f668e5ba5eeed8d4d0fa4be57a9c9eb0683697
R a148756c1ff7d66b58143c3257e91f62
P 57c5173b6376a76013b0611ce9770100bd8c04e80402e35d821d8614709f4795
R 74434244bfed2daca1fdf1468b8ad643
U drh
Z 90de4c6922e024a076aa3621c058524e
Z 9e01ec1a39b84d7c7feff809a6e0c2eb

View File

@@ -1 +1 @@
57c5173b6376a76013b0611ce9770100bd8c04e80402e35d821d8614709f4795
ce1e2b88777e00a82c04abe5ba35eec81b5f324e462f099cd00b21054f369688

View File

@@ -3532,6 +3532,8 @@ static i8 wherePathSatisfiesOrderBy(
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
if( pLoop->u.vtab.isOrdered ) obSat = obDone;
break;
}else{
pLoop->u.btree.nIdxCol = 0;
}
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
@@ -3677,6 +3679,7 @@ static i8 wherePathSatisfiesOrderBy(
if( !pColl ) pColl = db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
if( pLoop->u.btree.nIdxCol<=j ) pLoop->u.btree.nIdxCol = j+1;
isMatch = 1;
break;
}
@@ -4850,53 +4853,20 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->op!=OP_Noop ){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
int addrSeek = 0;
int n = -1;
int j, k, op;
int r1 = pParse->nMem+1;
Index *pIdx;
int n;
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
&& (pLoop->wsFlags & WHERE_INDEXED)!=0
&& OptimizationEnabled(db, SQLITE_SkipAhead)
&& (pIdx = pLoop->u.btree.pIndex)->hasStat1
&& pIdx->aiRowLogEst[(n = pLoop->u.btree.nIdxCol)-1]>=36
){
/* This is the Skip-ahead optimization. When doing a DISTINCT query
** that has WHERE_DISTINCT_ORDERED, use OP_SkipGT/OP_SkipLT to skip
** over all duplicate entries, rather than visiting all duplicates
** using OP_Next/OP_Prev. */
ExprList *pX = pWInfo->pResultSet;
for(j=0; j<pX->nExpr; j++){
Expr *pE = sqlite3ExprSkipCollate(pX->a[j].pExpr);
if( pE->op==TK_COLUMN ){
if( pE->iTable==pLevel->iIdxCur ){
k = pE->iColumn+1;
}else{
if( pE->iTable!=pLevel->iTabCur ) continue;
k = 1+sqlite3ColumnOfIndex(pIdx, pE->iColumn);
}
if( k>n ) n = k;
}
#ifdef SQLITE_DEBUG
/* Any expressions in the result-set that match columns of the
** index should have already been transformed to TK_COLUMN
** operations by whereIndexExprTrans(). */
else if( pIdx->aColExpr ){
for(k=0; k<pIdx->nKeyCol; k++){
Expr *pI = pIdx->aColExpr->a[k].pExpr;
assert( pI==0 || sqlite3ExprCompare(pE, pI, pE->iTable)!=0 );
}
}
#endif
}
}
/* TUNING: Only try to skip ahead using OP_Seek if we expect to
** skip over 11 or more rows. Otherwise, OP_Next is just as fast.
*/
assert( 36==sqlite3LogEst(12) );
if( n>0 && pIdx->aiRowLogEst[n]>=36 ){
int r1 = pParse->nMem+1;
int j, op;
for(j=0; j<n; j++){
sqlite3VdbeAddOp3(v, OP_Column, pLevel->iIdxCur, j, r1+j);
}
pParse->nMem += n;
pParse->nMem += n+1;
op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
VdbeCoverageIf(v, op==OP_SeekLT);

View File

@@ -124,6 +124,7 @@ struct WhereLoop {
u16 nEq; /* Number of equality constraints */
u16 nBtm; /* Size of BTM vector */
u16 nTop; /* Size of TOP vector */
u16 nIdxCol; /* Index column used for ORDER BY */
Index *pIndex; /* Index used, or NULL */
} btree;
struct { /* Information for virtual tables */

View File

@@ -139,6 +139,45 @@ do_execsql_test 830 {
SELECT DISTINCT a, b, c FROM t8 WHERE b=3;
} {1 3 1}
do_execsql_test 900 {
CREATE TABLE t9(v);
INSERT INTO t9 VALUES
('abcd'), ('Abcd'), ('aBcd'), ('ABcd'), ('abCd'), ('AbCd'), ('aBCd'),
('ABCd'), ('abcD'), ('AbcD'), ('aBcD'), ('ABcD'), ('abCD'), ('AbCD'),
('aBCD'), ('ABCD'),
('wxyz'), ('Wxyz'), ('wXyz'), ('WXyz'), ('wxYz'), ('WxYz'), ('wXYz'),
('WXYz'), ('wxyZ'), ('WxyZ'), ('wXyZ'), ('WXyZ'), ('wxYZ'), ('WxYZ'),
('wXYZ'), ('WXYZ');
}
do_execsql_test 910 {
SELECT DISTINCT v COLLATE NOCASE, v FROM t9 ORDER BY +v;
} {
ABCD ABCD ABCd ABCd ABcD ABcD ABcd ABcd AbCD
AbCD AbCd AbCd AbcD AbcD Abcd Abcd
WXYZ WXYZ WXYz WXYz WXyZ WXyZ WXyz WXyz WxYZ
WxYZ WxYz WxYz WxyZ WxyZ Wxyz Wxyz
aBCD aBCD aBCd aBCd aBcD aBcD aBcd aBcd abCD
abCD abCd abCd abcD abcD abcd abcd
wXYZ wXYZ wXYz wXYz wXyZ wXyZ wXyz wXyz wxYZ
wxYZ wxYz wxYz wxyZ wxyZ wxyz wxyz
}
do_execsql_test 920 {
CREATE INDEX i9 ON t9(v COLLATE NOCASE, v);
ANALYZE;
SELECT DISTINCT v COLLATE NOCASE, v FROM t9 ORDER BY +v;
} {
ABCD ABCD ABCd ABCd ABcD ABcD ABcd ABcd AbCD
AbCD AbCd AbCd AbcD AbcD Abcd Abcd
WXYZ WXYZ WXYz WXYz WXyZ WXyZ WXyz WXyz WxYZ
WxYZ WxYz WxYz WxyZ WxyZ Wxyz Wxyz
aBCD aBCD aBCd aBCd aBcD aBcD aBcd aBcd abCD
abCD abCd abCd abcD abcD abcd abcd
wXYZ wXYZ wXYz wXYz wXyZ wXyZ wXyz wXyz wxYZ
wxYZ wxYz wxYz wxyZ wxyZ wxyz wxyz
}
finish_test