Index: src/wherecode.c ================================================================== --- src/wherecode.c +++ src/wherecode.c @@ -1692,10 +1692,29 @@ VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); + + if( bSeekPastNull && (pLoop->wsFlags & WHERE_TOP_LIMIT)==0 ){ + /* If bSeekPastNull is set only to skip past the NULL values for + ** a query like "SELECT min(a), b FROM t1", then add code so that + ** if there are no rows with (a IS NOT NULL), then do the seek + ** without jumping past NULLs instead. This allows the code in + ** select.c to pick a value for "b" in the above query. */ + assert( startEq==0 && (op==OP_SeekGT || op==OP_SeekLT) ); + assert( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0 && pWInfo->nOBSat>0 ); + sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1); + sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); + + op = aStartOp[(start_constraints<<2) + (1<<1) + bRev]; + assert( op!=0 ); + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); + VdbeCoverage(v); + VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); + VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); + } } /* Load the value for the inequality constraint at the end of the ** range (if any). */ Index: test/minmax4.test ================================================================== --- test/minmax4.test +++ test/minmax4.test @@ -17,10 +17,11 @@ # the maximum q. # set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix minmax4 ifcapable !compound { finish_test return } @@ -146,8 +147,35 @@ db eval { SELECT a, min(b), b, min(c), c FROM t2 GROUP BY a ORDER BY a; } } {1 1 {} 2 2 2 3 3 5 5} - +#------------------------------------------------------------------------- +foreach {tn sql} { + 1 { CREATE INDEX i1 ON t1(a) } + 2 { CREATE INDEX i1 ON t1(a DESC) } + 3 { } +} { + reset_db + do_execsql_test 3.$tn.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(NULL, 1); + } + execsql $sql + do_execsql_test 3.$tn.1 { + SELECT min(a), b FROM t1; + } {{} 1} + do_execsql_test 3.$tn.2 { + SELECT min(a), b FROM t1 WHERE a<50; + } {{} {}} + do_execsql_test 3.$tn.3 { + INSERT INTO t1 VALUES(2, 2); + } + do_execsql_test 3.$tn.4 { + SELECT min(a), b FROM t1; + } {2 2} + do_execsql_test 3.$tn.5 { + SELECT min(a), b FROM t1 WHERE a<50; + } {2 2} +} finish_test