Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -873,18 +873,18 @@ if( zRet==0 ){ sqlite3_result_error_nomem(context); return; } - sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); + /* Never let the estimated number of rows be less than 10 */ + sqlite3_snprintf(24, zRet, "%llu", MAX((u64)p->nRow, 10)); z = zRet + sqlite3Strlen30(zRet); for(i=0; inKeyCol; i++){ u64 nDistinct = p->current.anDLt[i] + 1; u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; sqlite3_snprintf(24, z, " %llu", iVal); z += sqlite3Strlen30(z); - assert( p->current.anEq[i] ); } assert( z[0]=='\0' && z>zRet ); sqlite3_result_text(context, zRet, -1, sqlite3_free); } @@ -982,11 +982,10 @@ Index *pIdx; /* An index to being analyzed */ int iIdxCur; /* Cursor open on index being analyzed */ int iTabCur; /* Table cursor */ Vdbe *v; /* The virtual machine being built up */ int i; /* Loop counter */ - int jZeroRows = -1; /* Jump from here if number of rows is zero */ int iDb; /* Index of database containing pTab */ u8 needTableCnt = 1; /* True to count the table */ int regNewRowid = iMem++; /* Rowid for the inserted record */ int regStat4 = iMem++; /* Register to hold Stat4Accum object */ int regChng = iMem++; /* Index of changed index field */ @@ -1217,10 +1216,11 @@ (char*)&statPushFuncdef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, 2+IsStat34); sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); /* Add the entry to the stat1 table. */ + sqlite3VdbeJumpHere(v, addrRewind); callStatGet(v, regStat4, STAT_GET_STAT1, regStat1); assert( "BBB"[0]==SQLITE_AFF_TEXT ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); @@ -1239,10 +1239,12 @@ int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; pParse->nMem = MAX(pParse->nMem, regCol+nCol); + addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur); + VdbeCoverage(v); addrNext = sqlite3VdbeCurrentAddr(v); callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); VdbeCoverage(v); callStatGet(v, regStat4, STAT_GET_NEQ, regEq); @@ -1264,32 +1266,31 @@ sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */ sqlite3VdbeJumpHere(v, addrIsNull); + sqlite3VdbeJumpHere(v, addrRewind); } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* End of analysis */ - sqlite3VdbeJumpHere(v, addrRewind); } /* Create a single sqlite_stat1 entry containing NULL as the index ** name and the row count as the content. */ if( pOnlyIdx==0 && needTableCnt ){ VdbeComment((v, "%s", pTab->zName)); sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1); - jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_AddImm, regStat1, 10); sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); assert( "BBB"[0]==SQLITE_AFF_TEXT ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeJumpHere(v, jZeroRows); } } /* Index: test/analyze.test ================================================================== --- test/analyze.test +++ test/analyze.test @@ -94,46 +94,46 @@ } {0 {}} do_test analyze-1.11 { execsql { SELECT * FROM sqlite_stat1 } -} {} +} {t1 {} 0} do_test analyze-1.12 { catchsql { ANALYZE t1; } } {0 {}} do_test analyze-1.13 { execsql { SELECT * FROM sqlite_stat1 } -} {} +} {t1 {} 0} -# Create some indices that can be analyzed. But do not yet add -# data. Without data in the tables, no analysis is done. +# Create some indices that can be analyzed. +# Zero sqlite_stat1 entries are created. # do_test analyze-2.1 { execsql { CREATE INDEX t1i1 ON t1(a); ANALYZE main.t1; SELECT * FROM sqlite_stat1 ORDER BY idx; } -} {} +} {t1 t1i1 {0 0}} do_test analyze-2.2 { execsql { CREATE INDEX t1i2 ON t1(b); ANALYZE t1; SELECT * FROM sqlite_stat1 ORDER BY idx; } -} {} +} {t1 t1i1 {0 0} t1 t1i2 {0 0}} do_test analyze-2.3 { execsql { CREATE INDEX t1i3 ON t1(a,b); ANALYZE main; SELECT * FROM sqlite_stat1 ORDER BY idx; } -} {} +} {t1 t1i1 {0 0} t1 t1i2 {0 0} t1 t1i3 {0 0 0}} # Start adding data to the table. Verify that the analysis # is done correctly. # do_test analyze-3.1 { Index: test/analyze3.test ================================================================== --- test/analyze3.test +++ test/analyze3.test @@ -696,8 +696,8 @@ ANALYZE; SELECT * FROM sqlite_stat1; INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); ANALYZE sqlite_master; -} +} {t1 t1a {0 0}} finish_test