From: drh Date: Fri, 17 Feb 2017 16:26:34 +0000 (+0000) Subject: Add the "PRAGMA analyze_as_needed" command. X-Git-Tag: version-3.18.0~81^2~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=72052a73a3d1fc75015aa4123bea9af2f5a58e3f;p=thirdparty%2Fsqlite.git Add the "PRAGMA analyze_as_needed" command. FossilOrigin-Name: e93db2373127d31d33ec46ef918fa9386bb664a6 --- diff --git a/manifest b/manifest index 360ecf7903..9d27e603a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Set\sthe\sTF_StatsUsed\sflag\son\stables\swhen\sthe\squery\splanner\soutcome\sis\naffected\sby\sthe\ssqlite_stat1\sdata.\s\sAlso,\schange\sthe\scolumn\snames\sof\sthe\n"PRAGMA\sstats"\scommand\sso\sthat\sthey\sare\snot\skeywords. -D 2017-02-17T15:26:36.765 +C Add\sthe\s"PRAGMA\sanalyze_as_needed"\scommand. +D 2017-02-17T16:26:34.780 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2 @@ -331,7 +331,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121 -F src/analyze.c 1b7197d619788353437d390de42a9bccbb4aa2ac +F src/analyze.c 39206f31ca136a0a4d4f1d6bfd00bc81c6b3e5ec F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43 F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b @@ -383,12 +383,12 @@ F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa -F src/parse.y 591704fce84f814d9a3642774c1f011d38f4149c +F src/parse.y d5695ae4887a52352b1b8a3e3623477c7e79abeb F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953 -F src/pragma.c d4918a737f0bf1ad825654ebf07c4d009ff0ca63 -F src/pragma.h 9e65a9033cce7387c27cd89aecb2b2f205d1edf7 +F src/pragma.c e8b2ea66dfb1b90c53b920c08914ac26b109053a +F src/pragma.h 065e184494f12e94111da1ab6984faa7b6142e68 F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 @@ -399,7 +399,7 @@ F src/shell.c bb8e20789499aec921a01d8744c616b81b8214f1 F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae -F src/sqliteInt.h 5d50606deed2b38b35fb1b5e4ab658f8faa37d4a +F src/sqliteInt.h 85706e0963964336270590a1e508dec78540bc5c F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1495,7 +1495,7 @@ F tool/mkmsvcmin.tcl 95b37e202cbed873aa8ffdbb493b9db45927be2b F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e -F tool/mkpragmatab.tcl c955db934f7b1d800081447042cef692f26b2516 +F tool/mkpragmatab.tcl 6fd5ecb4a8debee39e3bb4e63f0634f69edfb861 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e @@ -1557,7 +1557,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 85026c8ee143bbd46565660fff8346ef81421546 -R 7cc0cc258beb93b198b99dc8e7b58520 +P fb2b8ae8310e4ea4b42354bbf36c3084a9d5c6d7 +R 23ff1c8d68460fd739a12857d6287bf8 U drh -Z 76eea0dfcfb8fa07347b6cdca98e2297 +Z 4884503796ef3cb7f91c7100ffa75ea8 diff --git a/manifest.uuid b/manifest.uuid index 1142241825..f532ee84dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb2b8ae8310e4ea4b42354bbf36c3084a9d5c6d7 \ No newline at end of file +e93db2373127d31d33ec46ef918fa9386bb664a6 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 3ecf469cd3..34de7fc744 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1286,28 +1286,66 @@ static void loadAnalysis(Parse *pParse, int iDb){ } /* -** Generate code that will do an analysis of an entire database +** Return true if table pTab is in need of being reanalyzed. */ -static void analyzeDatabase(Parse *pParse, int iDb){ +static int analyzeNeeded(Table *pTab){ + Index *pIdx; + if( (pTab->tabFlags & TF_StatsUsed)==0 ) return 0; + if( (pTab->tabFlags & TF_SizeChng)!=0 ) return 1; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( !pIdx->hasStat1 ) return 1; + } + return 0; +} + +/* +** Generate code that will do an analysis of an entire database. +** +** Return a count of the number of tables actually analyzed. Return 0 +** if nothing was analyzed. +*/ +static int analyzeDatabase(Parse *pParse, int iDbReq, int onlyIfNeeded){ sqlite3 *db = pParse->db; - Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ + Schema *pSchema; HashElem *k; int iStatCur; int iMem; int iTab; + int iDb; /* Database currently being analyzed */ + int iDbFirst, iDbLast; /* Range of databases to be analyzed */ + int cnt; /* Number of tables analyzed in a single database */ + int allCnt = 0; /* Number of tables analyzed across all databases */ - sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab; - pParse->nTab += 3; - openStatTable(pParse, iDb, iStatCur, 0, 0); - iMem = pParse->nMem+1; - iTab = pParse->nTab; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - Table *pTab = (Table*)sqliteHashData(k); - analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); + if( iDbReq>=0 ){ + iDbFirst = iDbLast = iDbReq; + }else{ + iDbFirst = 0; + iDbLast = db->nDb-1; } - loadAnalysis(pParse, iDb); + for(iDb=iDbFirst; iDb<=iDbLast; iDb++){ + if( iDb==1 ) continue; /* Do not analyze the TEMP database */ + pSchema = db->aDb[iDb].pSchema; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + cnt = 0; + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ + Table *pTab = (Table*)sqliteHashData(k); + if( !onlyIfNeeded || analyzeNeeded(pTab) ){ + if( cnt==0 ){ + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab; + pParse->nTab += 3; + openStatTable(pParse, iDb, iStatCur, 0, 0); + iMem = pParse->nMem+1; + iTab = pParse->nTab; + } + analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); + cnt++; + allCnt++; + } + } + if( cnt ) loadAnalysis(pParse, iDb); + } + return allCnt; } /* @@ -1345,16 +1383,21 @@ static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){ ** Form 1 causes all indices in all attached databases to be analyzed. ** Form 2 analyzes all indices the single database named. ** Form 3 analyzes all indices associated with the named table. +** +** If pName1 and pName2 are both NULL and if the ifNeeded flag is true, +** this routine computes an conditional ANALYZE on only those tables +** are believed to be in need of analysis. The conditional analysis +** might well be a no-op. */ -void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ +void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2, int ifNeeded){ sqlite3 *db = pParse->db; int iDb; - int i; char *z, *zDb; Table *pTab; Index *pIdx; Token *pTableName; Vdbe *v; + int needExpire = 1; /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ @@ -1366,15 +1409,12 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ assert( pName2!=0 || pName1==0 ); if( pName1==0 ){ /* Form 1: Analyze everything */ - for(i=0; inDb; i++){ - if( i==1 ) continue; /* Do not analyze the TEMP database */ - analyzeDatabase(pParse, i); - } + needExpire = analyzeDatabase(pParse, -1, ifNeeded) || ifNeeded==0; }else if( pName2->n==0 ){ /* Form 2: Analyze the database or table named */ iDb = sqlite3FindDb(db, pName1); if( iDb>=0 ){ - analyzeDatabase(pParse, iDb); + analyzeDatabase(pParse, iDb, 0); }else{ z = sqlite3NameFromToken(db, pName1); if( z ){ @@ -1402,8 +1442,10 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ } } } - v = sqlite3GetVdbe(pParse); - if( v ) sqlite3VdbeAddOp0(v, OP_Expire); + if( needExpire ){ + v = sqlite3GetVdbe(pParse); + if( v ) sqlite3VdbeAddOp0(v, OP_Expire); + } } /* diff --git a/src/parse.y b/src/parse.y index 9cada2a1be..ff03c128ac 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1512,8 +1512,8 @@ cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);} /////////////////////////////////// ANALYZE /////////////////////////////////// %ifndef SQLITE_OMIT_ANALYZE -cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0);} -cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);} +cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0, 0);} +cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y, 0);} %endif //////////////////////// ALTER TABLE table ... //////////////////////////////// diff --git a/src/pragma.c b/src/pragma.c index f28ff9d13c..789751958c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1828,6 +1828,14 @@ void sqlite3Pragma( break; } + /* + ** PRAGMA analyze_as_needed + */ + case PragTyp_ANALYZE_AS_NEEDED: { + sqlite3Analyze(pParse, 0, 0, 1); + break; + } + /* ** PRAGMA busy_timeout ** PRAGMA busy_timeout = N diff --git a/src/pragma.h b/src/pragma.h index 1592bbd2d5..ba107ec07e 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -5,49 +5,50 @@ */ /* The various pragma types */ -#define PragTyp_HEADER_VALUE 0 -#define PragTyp_AUTO_VACUUM 1 -#define PragTyp_FLAG 2 -#define PragTyp_BUSY_TIMEOUT 3 -#define PragTyp_CACHE_SIZE 4 -#define PragTyp_CACHE_SPILL 5 -#define PragTyp_CASE_SENSITIVE_LIKE 6 -#define PragTyp_COLLATION_LIST 7 -#define PragTyp_COMPILE_OPTIONS 8 -#define PragTyp_DATA_STORE_DIRECTORY 9 -#define PragTyp_DATABASE_LIST 10 -#define PragTyp_DEFAULT_CACHE_SIZE 11 -#define PragTyp_ENCODING 12 -#define PragTyp_FOREIGN_KEY_CHECK 13 -#define PragTyp_FOREIGN_KEY_LIST 14 -#define PragTyp_INCREMENTAL_VACUUM 15 -#define PragTyp_INDEX_INFO 16 -#define PragTyp_INDEX_LIST 17 -#define PragTyp_INTEGRITY_CHECK 18 -#define PragTyp_JOURNAL_MODE 19 -#define PragTyp_JOURNAL_SIZE_LIMIT 20 -#define PragTyp_LOCK_PROXY_FILE 21 -#define PragTyp_LOCKING_MODE 22 -#define PragTyp_PAGE_COUNT 23 -#define PragTyp_MMAP_SIZE 24 -#define PragTyp_PAGE_SIZE 25 -#define PragTyp_SECURE_DELETE 26 -#define PragTyp_SHRINK_MEMORY 27 -#define PragTyp_SOFT_HEAP_LIMIT 28 -#define PragTyp_SYNCHRONOUS 29 -#define PragTyp_TABLE_INFO 30 -#define PragTyp_TEMP_STORE 31 -#define PragTyp_TEMP_STORE_DIRECTORY 32 -#define PragTyp_THREADS 33 -#define PragTyp_WAL_AUTOCHECKPOINT 34 -#define PragTyp_WAL_CHECKPOINT 35 -#define PragTyp_ACTIVATE_EXTENSIONS 36 -#define PragTyp_HEXKEY 37 -#define PragTyp_KEY 38 -#define PragTyp_REKEY 39 -#define PragTyp_LOCK_STATUS 40 -#define PragTyp_PARSER_TRACE 41 -#define PragTyp_STATS 42 +#define PragTyp_ANALYZE_AS_NEEDED 0 +#define PragTyp_HEADER_VALUE 1 +#define PragTyp_AUTO_VACUUM 2 +#define PragTyp_FLAG 3 +#define PragTyp_BUSY_TIMEOUT 4 +#define PragTyp_CACHE_SIZE 5 +#define PragTyp_CACHE_SPILL 6 +#define PragTyp_CASE_SENSITIVE_LIKE 7 +#define PragTyp_COLLATION_LIST 8 +#define PragTyp_COMPILE_OPTIONS 9 +#define PragTyp_DATA_STORE_DIRECTORY 10 +#define PragTyp_DATABASE_LIST 11 +#define PragTyp_DEFAULT_CACHE_SIZE 12 +#define PragTyp_ENCODING 13 +#define PragTyp_FOREIGN_KEY_CHECK 14 +#define PragTyp_FOREIGN_KEY_LIST 15 +#define PragTyp_INCREMENTAL_VACUUM 16 +#define PragTyp_INDEX_INFO 17 +#define PragTyp_INDEX_LIST 18 +#define PragTyp_INTEGRITY_CHECK 19 +#define PragTyp_JOURNAL_MODE 20 +#define PragTyp_JOURNAL_SIZE_LIMIT 21 +#define PragTyp_LOCK_PROXY_FILE 22 +#define PragTyp_LOCKING_MODE 23 +#define PragTyp_PAGE_COUNT 24 +#define PragTyp_MMAP_SIZE 25 +#define PragTyp_PAGE_SIZE 26 +#define PragTyp_SECURE_DELETE 27 +#define PragTyp_SHRINK_MEMORY 28 +#define PragTyp_SOFT_HEAP_LIMIT 29 +#define PragTyp_SYNCHRONOUS 30 +#define PragTyp_TABLE_INFO 31 +#define PragTyp_TEMP_STORE 32 +#define PragTyp_TEMP_STORE_DIRECTORY 33 +#define PragTyp_THREADS 34 +#define PragTyp_WAL_AUTOCHECKPOINT 35 +#define PragTyp_WAL_CHECKPOINT 36 +#define PragTyp_ACTIVATE_EXTENSIONS 37 +#define PragTyp_HEXKEY 38 +#define PragTyp_KEY 39 +#define PragTyp_REKEY 40 +#define PragTyp_LOCK_STATUS 41 +#define PragTyp_PARSER_TRACE 42 +#define PragTyp_STATS 43 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -132,6 +133,11 @@ static const PragmaName aPragmaName[] = { /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif + {/* zName: */ "analyze_as_needed", + /* ePragTyp: */ PragTyp_ANALYZE_AS_NEEDED, + /* ePragFlg: */ PragFlg_NoColumns, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) {/* zName: */ "application_id", /* ePragTyp: */ PragTyp_HEADER_VALUE, @@ -605,4 +611,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, #endif }; -/* Number of pragmas: 59 on by default, 73 total. */ +/* Number of pragmas: 60 on by default, 74 total. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3c75f2ff6e..f590c85f93 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4028,7 +4028,7 @@ void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); char sqlite3AffinityType(const char*, u8*); -void sqlite3Analyze(Parse*, Token*, Token*); +void sqlite3Analyze(Parse*, Token*, Token*, int); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); int sqlite3FindDbName(sqlite3 *, const char *); diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index 005c4bc48e..2201ea1306 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -361,6 +361,9 @@ set pragma_def { NAME: threads FLAG: Result0 + + NAME: analyze_as_needed + FLAG: NoColumns } # Open the output file