Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -183,10 +183,11 @@ { "sqlite_stat3", 0 }, }; int i; sqlite3 *db = pParse->db; Db *pDb; + int nRowLimit; Vdbe *v = sqlite3GetVdbe(pParse); int aRoot[ArraySize(aTable)]; u8 aCreateTbl[ArraySize(aTable)]; #ifdef SQLITE_ENABLE_STAT4 const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1; @@ -196,10 +197,13 @@ if( v==0 ) return; assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; + assert( pParse->eAux1==2 ); + nRowLimit = pParse->aux1.nRowLimit; + pParse->eAux1 = 0; /* Create new statistic tables if they do not exist, or clear them ** if they do already exist. */ for(i=0; ieAux1 = 2; + pParse->aux1.nRowLimit = nRowLimit; /* Open the sqlite_stat[134] tables for writing. */ for(i=0; inAnalysisLimit, regTemp2); + assert( pParse->eAux1==2 ); + sqlite3VdbeAddOp2(v, OP_Integer, pParse->aux1.nRowLimit, regTemp2); sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4, &statInitFuncdef, 0); /* Implementation of the following: ** @@ -1223,11 +1230,12 @@ #endif assert( regChng==(regStat+1) ); { sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4, &statPushFuncdef, 0); - if( db->nAnalysisLimit ){ + assert( pParse->eAux1==2 ); + if( pParse->aux1.nRowLimit ){ int j1, j2, j3; j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v); j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v); j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1); sqlite3VdbeJumpHere(v, j1); @@ -1250,11 +1258,12 @@ #endif sqlite3VdbeChangeP5(v, OPFLAG_APPEND); /* Add the entries to the stat4 table. */ #ifdef SQLITE_ENABLE_STAT4 - if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){ + assert( pParse->eAux1==2 ); + if( OptimizationEnabled(db, SQLITE_Stat4) && pParse->aux1.nRowLimit==0 ){ int regEq = regStat1; int regLt = regStat1+1; int regDLt = regStat1+2; int regSample = regStat1+3; int regCol = regStat1+4; @@ -1397,10 +1406,15 @@ /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return; + } + assert( pParse->eAux1==0 || pParse->eAux1==2 ); + if( pParse->eAux1==0 ){ + pParse->aux1.nRowLimit = db->nAnalysisLimit; + pParse->eAux1 = 2; } assert( pName2!=0 || pName1==0 ); if( pName1==0 ){ /* Form 1: Analyze everything */ Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -1157,12 +1157,14 @@ if( isView || isVirtual ){ sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); }else #endif { - pParse->addrCrTab = + assert( pParse->eAux1==0 || pParse->eAux1==1 ); + pParse->aux1.addrCrTab = sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY); + pParse->eAux1 = 1; } sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); @@ -2006,13 +2008,14 @@ } /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY ** into BTREE_BLOBKEY. */ - if( pParse->addrCrTab ){ + assert( pParse->eAux1==0 || pParse->eAux1==1 ); + if( pParse->eAux1 ){ assert( v ); - sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY); + sqlite3VdbeChangeP3(v, pParse->aux1.addrCrTab, BTREE_BLOBKEY); } /* Locate the PRIMARY KEY index. Or, if this table was originally ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. */ Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -1554,12 +1554,24 @@ cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);} %endif SQLITE_OMIT_REINDEX /////////////////////////////////// ANALYZE /////////////////////////////////// %ifndef SQLITE_OMIT_ANALYZE -cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0);} -cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);} +cmd ::= ANALYZE anlyzcfg. {sqlite3Analyze(pParse, 0, 0);} +cmd ::= ANALYZE nm(X) dbnm(Y) anlyzcfg. {sqlite3Analyze(pParse, &X, &Y);} +anlyzcfg ::= . +anlyzcfg ::= WITH LIMIT EQ INTEGER(X). { + char *z = sqlite3NameFromToken(pParse->db, &X); + if( z ){ + i64 x; + sqlite3DecOrHexToI64(z, &x); + pParse->eAux1 = 2; + pParse->aux1.nRowLimit = x>0x7ffffff0 ? 0 : (int)x; + sqlite3DbFree(pParse->db, z); + } +} + %endif //////////////////////// ALTER TABLE table ... //////////////////////////////// %ifndef SQLITE_OMIT_ALTERTABLE cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3318,14 +3318,18 @@ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ Parse *pParentParse; /* Parent parser if this parser is nested */ - int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */ u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ + union { + int addrCrTab; /* (1) Addr of OP_CreateBtree opcode on CREATE TABLE */ + int nRowLimit; /* (2) LIMIT= value for ANALYZE */ + } aux1; + u8 eAux1; /* Which field of the aux1 union is in use */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ /**************************************************************************