]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Implementation of the analyze() SQL function is now mostly complete.
authordrh <>
Tue, 14 Apr 2026 19:36:33 +0000 (19:36 +0000)
committerdrh <>
Tue, 14 Apr 2026 19:36:33 +0000 (19:36 +0000)
FossilOrigin-Name: 1ca0386ab2df0d88ed52941469d459114f483ecf6b7e4691bcc32e909636cb7d

ext/misc/analyze.c
manifest
manifest.uuid

index 127d010aab106f1201b904f63c163c324a3cdda9..900a6203fa67f85a81974ca6e62ae25d58ed36b2 100644 (file)
@@ -358,16 +358,23 @@ static int analysisSubreport(
     analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
     analysisLine(p, "Bytes of payload", "%-11lld", payload);
     analysisPercent(p, 0, payload*100.0/(double)storage);
+    if( ovfl_cnt>0 ){
+      analysisLine(p, "Bytes of payload in overflow", "%-11lld", ovfl_payload);
+      analysisPercent(p, 0, ovfl_payload*100.0/(double)payload);
+    }
     total_unused = leaf_unused + int_unused + ovfl_unused;
     total_meta = storage - payload - total_unused;
-    analysisLine(p, "Bytes of metadata", "%lld", total_meta);
+    analysisLine(p, "Bytes of metadata", "%-11lld", total_meta);
     analysisPercent(p, 0, total_meta*100.0/(double)storage);
+    if( cnt==1 ){
+      analysisLine(p, "B-tree depth", "%lld\n", depth);
+    }
     if( nentry>0 ){
-      analysisLine(p, "Average payload per entry", "%g\n",
+      analysisLine(p, "Average payload per entry", "%.1f\n",
                    (double)payload/(double)nentry);
-      analysisLine(p, "Average unused bytes per entry", "%g\n",
+      analysisLine(p, "Average unused bytes per entry", "%.1f\n",
                    (double)total_unused/(double)nentry);
-      analysisLine(p, "Average metadata per entry", "%g\n",
+      analysisLine(p, "Average metadata per entry", "%.1f\n",
                    (double)total_meta/(double)nentry);
     }
     analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
@@ -379,10 +386,19 @@ static int analysisSubreport(
       analysisLine(p, "Index pages used", "%lld\n", int_pages);
     }
     analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
-    analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
+    if( ovfl_cnt ){
+      analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
+    }
     analysisLine(p, "Total pages used", "%lld\n", total_pages);
-     
-
+    if( int_pages>0 ){
+      analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
+    }
+    analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
+    if( ovfl_cnt ){
+      analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
+    }
+    analysisLine(p, "Unused bytes on all pages", "%-11lld", total_unused);
+    analysisPercent(p, 0, total_unused*100.0/(double)storage);
   }
   if( analysisStmtFinish(p, rc, pStmt) ){
     return rc;
@@ -615,7 +631,6 @@ static void analyzeFunc(
     analysisPercent(&s, 0, (n*100.0)/(double)nPage);
   }
   if( analysisStmtFinish(&s, rc, pStmt) ) return;
-  sqlite3_str_append(s.pOut, "\n", 1);
 
   rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
   if( rc ) return;
@@ -649,6 +664,8 @@ static void analyzeFunc(
       sqlite3_free(zWhere);
       if( rc ) break;
     }else{
+      sqlite3_stmt *pS2;
+      int rc2;
       char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
       char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
       rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
@@ -661,11 +678,35 @@ static void analyzeFunc(
       sqlite3_free(zTitle);
       sqlite3_free(zWhere);
       if( rc ) break;
-      zTitle = sqlite3_mprintf("All index of table %s", zUpper);
-      zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
-      rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
-      sqlite3_free(zTitle);
-      sqlite3_free(zWhere);
+      if( nIndex>1 ){
+        zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
+        zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
+        rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
+        sqlite3_free(zTitle);
+        sqlite3_free(zWhere);
+        if( rc ) break;
+      }
+      pS2 = analysisPrepare(&s,
+              "SELECT name, upper(name) FROM temp.%s"
+              " WHERE is_index AND tblname=%Q",
+              s.zSU, zName);
+      if( pS2==0 ){
+        rc = SQLITE_NOMEM;
+        break;
+      }
+      while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
+        const char *zU = (const char*)sqlite3_column_text(pS2, 1);
+        const char *zN = (const char*)sqlite3_column_text(pS2, 0);
+        zTitle = sqlite3_mprintf("Index %s", zU);
+        zWhere = sqlite3_mprintf("name=%Q", zN);
+        rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
+        sqlite3_free(zTitle);
+        sqlite3_free(zWhere);
+        if( rc ) break;
+      }
+      if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+      rc2 = sqlite3_finalize(pS2);
+      if( rc==SQLITE_OK && rc2!=SQLITE_OK ) rc = rc2;
       if( rc ) break;
     }
   }
@@ -744,7 +785,7 @@ static void analyzeFunc(
     sqlite3_finalize(pStmt);
     return;
   }
-  sqlite3_str_appendf(s.pOut,"\nCOMMIT;\n");
+  sqlite3_str_appendf(s.pOut,";\nCOMMIT;\n");
   sqlite3_finalize(pStmt);
 
   if( sqlite3_str_length(s.pOut) ){
index b28c44a30cace00648d3cb7e32ad6731b75cc5ad..9f702950b4981cc499f5b9b4b4f49a03a95204e1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Much,\sbut\snot\sall,\sof\sthe\sreport\sgeneration\sis\sadded.\s\sAn\sincremental\scheck-in.
-D 2026-04-14T19:02:40.997
+C Implementation\sof\sthe\sanalyze()\sSQL\sfunction\sis\snow\smostly\scomplete.
+D 2026-04-14T19:36:33.575
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -358,7 +358,7 @@ F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b6
 F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
 F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
 F ext/misc/amatch.c 8d237cc014b3736922c26a76a451050d244aa4980c47c531f368f817b1e77b49
-F ext/misc/analyze.c a08a09619c5e206ee403199f5299618bc8163972bcc2252d0e2e164e75b623c6
+F ext/misc/analyze.c 200aa4a378e54b710cd774d70a3a65d916972bcf695671eff306309cd37fa8da
 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
 F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
 F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
@@ -2199,8 +2199,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 037a0e586c4aa81a53aea164080e739f9d5b87197d04fdd68feb0ab5eb01020b
-R 70ce17d6d01e5469f673e51601f83039
+P 289fefc3edfeecb06dc11897d3ff24763fd9e25db44e369eeec29b9ed3de5ccc
+R 635177803a58986bff71c8ff6e3e87a1
 U drh
-Z c9e2ac614964bb80c0cde4c2ca0cf6c6
+Z cf63c806645e7784cf6fda78da65684e
 # Remove this line to create a well-formed Fossil manifest.
index 7f8a4fc5f3a53399a2a8523f0e6fcfe0c8053d00..fdf1e55aa48aa3cf74ffeff21c3da96f8ae16b3c 100644 (file)
@@ -1 +1 @@
-289fefc3edfeecb06dc11897d3ff24763fd9e25db44e369eeec29b9ed3de5ccc
+1ca0386ab2df0d88ed52941469d459114f483ecf6b7e4691bcc32e909636cb7d