Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1015,11 +1015,11 @@ int argc, sqlite3_value **argv ){ unsigned char *z, *zOut; int i; - zOut = z = sqlite3_malloc( argc*4 ); + zOut = z = sqlite3_malloc( argc*4+1 ); if( z==0 ){ sqlite3_result_error_nomem(context); return; } for(i=0; ifd, &locked); if( rc==SQLITE_OK && !locked ){ Pgno nPage; /* Number of pages in database file */ - /* Check the size of the database file. If it consists of 0 pages - ** and the journal is not being persisted, then delete the journal - ** file. See the header comment above for the reasoning here. - ** Delete the obsolete journal file under a RESERVED lock to avoid - ** race conditions and to avoid violating [H33020]. - */ rc = pagerPagecount(pPager, &nPage); if( rc==SQLITE_OK ){ + /* If the database is zero pages in size, that means that either (1) the + ** journal is a remnant from a prior database with the same name where + ** the database file but not the journal was deleted, or (2) the initial + ** transaction that populates a new database is being rolled back. + ** In either case, the journal file can be deleted. However, take care + ** not to delete the journal file if it is already open due to + ** journal_mode=PERSIST. + */ if( nPage==0 && !jrnlOpen ){ sqlite3BeginBenignMalloc(); if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){ sqlite3OsDelete(pVfs, pPager->zJournal, 0); if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -822,11 +822,11 @@ ** is always on by default regardless of the sign of the default cache ** size. But continue to take the absolute value of the default cache ** size of historical compatibility. */ case PragTyp_DEFAULT_CACHE_SIZE: { - static const int iLn = __LINE__+2; + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList getCacheSize[] = { { OP_Transaction, 0, 0, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ { OP_IfPos, 1, 8, 0}, { OP_Integer, 0, 2, 0}, @@ -1085,11 +1085,11 @@ /* When setting the auto_vacuum mode to either "full" or ** "incremental", write the value of meta[6] in the database ** file. Before writing to meta[6], check that meta[3] indicates ** that this really is an auto-vacuum capable database. */ - static const int iLn = __LINE__+2; + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList setMeta6[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, { OP_If, 1, 0, 0}, /* 2 */ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ @@ -1788,11 +1788,11 @@ /* Code that appears at the end of the integrity check. If no error ** messages have been generated, output OK. Otherwise output the ** error message */ - static const int iLn = __LINE__+2; + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ { OP_IfNeg, 1, 0, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ { OP_ResultRow, 3, 1, 0}, Index: src/trigger.c ================================================================== --- src/trigger.c +++ src/trigger.c @@ -564,11 +564,11 @@ /* Generate code to destroy the database record of the trigger. */ assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ int base; - static const int iLn = __LINE__+2; + static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList dropTrigger[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String8, 0, 1, 0}, /* 1 */ { OP_Column, 0, 1, 2}, { OP_Ne, 2, ADDR(8), 1}, Index: src/vdbe.h ================================================================== --- src/vdbe.h +++ src/vdbe.h @@ -272,13 +272,15 @@ void sqlite3VdbeSetLineNumber(Vdbe*,int); # define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) # define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); # define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); +# define VDBE_OFFSET_LINENO(x) (__LINE__+x) #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) +# define VDBE_OFFSET_LINENO(x) 0 #endif #endif Index: src/vdbeblob.c ================================================================== --- src/vdbeblob.c +++ src/vdbeblob.c @@ -133,11 +133,11 @@ ** ** The sqlite3_blob_close() function finalizes the vdbe program, ** which closes the b-tree cursor and (possibly) commits the ** transaction. */ - static const int iLn = __LINE__+4; + static const int iLn = VDBE_OFFSET_LINENO(4); static const VdbeOpList openBlob[] = { /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */ {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */ /* One of the following two instructions is replaced by an OP_Noop. */ {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -3972,11 +3972,14 @@ pNew->u.btree.nEq++; pNew->u.btree.nSkip++; pNew->aLTerm[pNew->nLTerm++] = 0; pNew->wsFlags |= WHERE_SKIPSCAN; nIter = sqlite3LogEst(pProbe->aiRowEst[0]/pProbe->aiRowEst[saved_nEq+1]); + pNew->rRun = rLogSize + nIter; + pNew->nOut += nIter; whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter); + pNew->nOut = saved_nOut; } for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nRecValid = pBuilder->nRecValid; Index: test/func.test ================================================================== --- test/func.test +++ test/func.test @@ -1359,6 +1359,11 @@ } for {set i 65536} {$i<=0x10ffff} {incr i 139} { do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i } +# Test char(). +# +do_execsql_test func-31.1 { + SELECT char(), length(char()), typeof(char()) +} {{} 0 text} finish_test Index: test/skipscan1.test ================================================================== --- test/skipscan1.test +++ test/skipscan1.test @@ -206,7 +206,45 @@ SELECT i FROM t4 WHERE e=5; SELECT i FROM t4 WHERE f=6; SELECT i FROM t4 WHERE g=7; SELECT i FROM t4 WHERE h=8; } {9 9 9 9 9 9 9 9} + +# Make sure skip-scan cost computation in the query planner takes into +# account the fact that the seek must occur multiple times. +# +# Prior to 2014-03-10, the costs were computed incorrectly which would +# cause index t5i2 to be used instead of t5i1 on the skipscan1-5.3. +# +do_execsql_test skipscan1-5.1 { + CREATE TABLE t5( + id INTEGER PRIMARY KEY, + loc TEXT, + lang INTEGER, + utype INTEGER, + xa INTEGER, + xd INTEGER, + xh INTEGER + ); + CREATE INDEX t5i1 on t5(loc, xh, xa, utype, lang); + CREATE INDEX t5i2 ON t5(xd,loc,utype,lang); + EXPLAIN QUERY PLAN + SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N'; +} {/.*COVERING INDEX t5i1 .*/} +do_execsql_test skipscan1-5.2 { + ANALYZE; + DELETE FROM sqlite_stat1; + DROP TABLE IF EXISTS sqlite_stat4; + DROP TABLE IF EXISTS sqlite_stat3; + INSERT INTO sqlite_stat1 VALUES('t5','t5i1','2702931 3 2 2 2 2'); + INSERT INTO sqlite_stat1 VALUES('t5','t5i2','2702931 686 2 2 2'); + ANALYZE sqlite_master; +} {} +db cache flush +do_execsql_test skipscan1-5.3 { + EXPLAIN QUERY PLAN + SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N'; +} {/.*COVERING INDEX t5i1 .*/} + + finish_test