Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -4579,11 +4579,13 @@ int addr; pLevel = &pWInfo->a[i]; pLoop = pLevel->pWLoop; sqlite3VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ - if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){ + if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED + && (pLoop->wsFlags & WHERE_INDEXED)!=0 + ){ int j, k, op; int r1 = pParse->nMem+1; int n = 0; ExprList *pX = pWInfo->pDistinctSet; for(j=0; jnExpr; j++){ @@ -4592,16 +4594,18 @@ } for(j=0; jiIdxCur, j, r1+j); } pParse->nMem += n; - op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT; - k = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n); - VdbeCoverageIf(v, op==OP_SeekLT); - VdbeCoverageIf(v, op==OP_SeekGT); - sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2); - sqlite3VdbeJumpHere(v, k); + if( n>0 ){ + op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT; + k = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n); + VdbeCoverageIf(v, op==OP_SeekLT); + VdbeCoverageIf(v, op==OP_SeekGT); + sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2); + sqlite3VdbeJumpHere(v, k); + } }else{ sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeChangeP5(v, pLevel->p5); VdbeCoverage(v); VdbeCoverageIf(v, pLevel->op==OP_Next); ADDED test/distinct2.test Index: test/distinct2.test ================================================================== --- /dev/null +++ test/distinct2.test @@ -0,0 +1,52 @@ +# 2016-04-15 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this script is DISTINCT queries using the skip-ahead +# optimization. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +set testprefix distinct2 + +do_execsql_test 100 { + CREATE TABLE t1(x INTEGER PRIMARY KEY); + INSERT INTO t1 VALUES(0),(1),(2); + CREATE TABLE t2 AS + SELECT DISTINCT a.x AS aa, b.x AS bb + FROM t1 a, t1 b; + SELECT *, '|' FROM t2 ORDER BY aa, bb; +} {0 0 | 0 1 | 0 2 | 1 0 | 1 1 | 1 2 | 2 0 | 2 1 | 2 2 |} +do_execsql_test 110 { + DROP TABLE t2; + CREATE TABLE t2 AS + SELECT DISTINCT a.x AS aa, b.x AS bb + FROM t1 a, t1 b + WHERE a.x IN t1 AND b.x IN t1; + SELECT *, '|' FROM t2 ORDER BY aa, bb; +} {0 0 | 0 1 | 0 2 | 1 0 | 1 1 | 1 2 | 2 0 | 2 1 | 2 2 |} +do_execsql_test 120 { + CREATE TABLE t102 (i0 TEXT UNIQUE NOT NULL); + INSERT INTO t102 VALUES ('0'),('1'),('2'); + DROP TABLE t2; + CREATE TABLE t2 AS + SELECT DISTINCT * + FROM t102 AS t0 + JOIN t102 AS t4 ON (t2.i0 IN t102) + NATURAL JOIN t102 AS t3 + JOIN t102 AS t1 ON (t0.i0 IN t102) + JOIN t102 AS t2 ON (t2.i0=+t0.i0 OR (t0.i0<>500 AND t2.i0=t1.i0)); + SELECT *, '|' FROM t2 ORDER BY 1, 2, 3, 4, 5; +} {0 0 0 0 | 0 0 1 0 | 0 0 1 1 | 0 0 2 0 | 0 0 2 2 | 0 1 0 0 | 0 1 1 0 | 0 1 1 1 | 0 1 2 0 | 0 1 2 2 | 0 2 0 0 | 0 2 1 0 | 0 2 1 1 | 0 2 2 0 | 0 2 2 2 | 1 0 0 0 | 1 0 0 1 | 1 0 1 1 | 1 0 2 1 | 1 0 2 2 | 1 1 0 0 | 1 1 0 1 | 1 1 1 1 | 1 1 2 1 | 1 1 2 2 | 1 2 0 0 | 1 2 0 1 | 1 2 1 1 | 1 2 2 1 | 1 2 2 2 | 2 0 0 0 | 2 0 0 2 | 2 0 1 1 | 2 0 1 2 | 2 0 2 2 | 2 1 0 0 | 2 1 0 2 | 2 1 1 1 | 2 1 1 2 | 2 1 2 2 | 2 2 0 0 | 2 2 0 2 | 2 2 1 1 | 2 2 1 2 | 2 2 2 2 |} + + +finish_test