]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the "PRAGMA analyze_as_needed" command.
authordrh <drh@noemail.net>
Fri, 17 Feb 2017 16:26:34 +0000 (16:26 +0000)
committerdrh <drh@noemail.net>
Fri, 17 Feb 2017 16:26:34 +0000 (16:26 +0000)
FossilOrigin-Name: e93db2373127d31d33ec46ef918fa9386bb664a6

manifest
manifest.uuid
src/analyze.c
src/parse.y
src/pragma.c
src/pragma.h
src/sqliteInt.h
tool/mkpragmatab.tcl

index 360ecf790372468da8d0b01757037910d6b34f7b..9d27e603a6db82b140ad98735090803d0ad04392 100644 (file)
--- 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
index 114224182522808eb8597f400b8d5d1b45b17a43..f532ee84ddc304bd5000984735cbcede3c5d457b 100644 (file)
@@ -1 +1 @@
-fb2b8ae8310e4ea4b42354bbf36c3084a9d5c6d7
\ No newline at end of file
+e93db2373127d31d33ec46ef918fa9386bb664a6
\ No newline at end of file
index 3ecf469cd38a3837a733a6484d3a1266853dc3e0..34de7fc7449e400ccf15fc9ae014cdeea762311b 100644 (file)
@@ -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; i<db->nDb; 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);
+  }
 }
 
 /*
index 9cada2a1be46731d055a770d87c9912112f556a3..ff03c128ace465d372dee460eb98878df2117355 100644 (file)
@@ -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 ... ////////////////////////////////
index f28ff9d13c86ee33ea810c96ee0fbb3e33591fe4..789751958c06b541df4a36e0cb4407e4ca37fcd7 100644 (file)
@@ -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
index 1592bbd2d54da4d30e77b49876d7775700ab3984..ba107ec07eb74099cdfb3fbbe1564071f8f526bb 100644 (file)
@@ -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. */
index 3c75f2ff6e7a15dcb5ca30530a2527ad8c93138f..f590c85f930f587e80c89624af439de6162d0fe5 100644 (file)
@@ -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 *);
index 005c4bc48eaac2763edf65dabb713fbae1a8dc21..2201ea130646aa7137a82765768b0ea0617cd7b4 100644 (file)
@@ -361,6 +361,9 @@ set pragma_def {
 
   NAME: threads
   FLAG: Result0
+
+  NAME: analyze_as_needed
+  FLAG: NoColumns
 }
 
 # Open the output file