Fossil SCM

Update the built-in SQLite to the latest version with the diskused() SQL function support. Add an option (accessible to Admin users only) to view the output of diskused() as the "Details" submenu on the /repo-tabsize page, if Fossil is linked against SQLite 3.54.0 or later.

drh 2026-05-30 13:54 UTC trunk
Commit 71439dc76ad2bbf466756dbb6409e9586e0e3bdf2d88debb8af803a8264c24a7
+244 -213
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,16 +5,16 @@
55
**
66
** ext/expert/sqlite3expert.c
77
** ext/expert/sqlite3expert.h
88
** ext/intck/sqlite3intck.c
99
** ext/intck/sqlite3intck.h
10
-** ext/misc/analyze.c
1110
** ext/misc/appendvfs.c
1211
** ext/misc/base64.c
1312
** ext/misc/base85.c
1413
** ext/misc/completion.c
1514
** ext/misc/decimal.c
15
+** ext/misc/diskused.c
1616
** ext/misc/fileio.c
1717
** ext/misc/ieee754.c
1818
** ext/misc/memtrace.c
1919
** ext/misc/pcachetrace.c
2020
** ext/misc/regexp.c
@@ -19478,11 +19478,11 @@
1947819478
sqlite3_vfs_unregister(pVfs);
1947919479
sqlite3_free(pVfs);
1948019480
}
1948119481
1948219482
/************************* End ext/misc/vfstrace.c ********************/
19483
-/************************* Begin ext/misc/analyze.c ******************/
19483
+/************************* Begin ext/misc/diskused.c ******************/
1948419484
/*
1948519485
** 2026-04-13
1948619486
**
1948719487
** The author disclaims copyright to this source code. In place of
1948819488
** a legal notice, here is a blessing:
@@ -19491,12 +19491,21 @@
1949119491
** May you find forgiveness for yourself and forgive others.
1949219492
** May you share freely, never taking more than you give.
1949319493
**
1949419494
******************************************************************************
1949519495
**
19496
-** Partial reimplement of the sqlite3_analyzer utility program as
19497
-** loadable SQL function.
19496
+** This extension implements an SQL function:
19497
+**
19498
+** diskused(X)
19499
+**
19500
+** Where X is the schema name (typically 'main'). The output is text
19501
+** that describes how much filesystem space the various tables and indexes
19502
+** of the database consume.
19503
+**
19504
+** This function is a replacement for the (now deprecated)
19505
+** "sqlite3_analyzer" utility program. This function is built
19506
+** into the CLI and is used to implement the ".diskused" command there.
1949819507
*/
1949919508
/* #include "sqlite3ext.h" */
1950019509
SQLITE_EXTENSION_INIT1
1950119510
#include <assert.h>
1950219511
#include <string.h>
@@ -19504,28 +19513,28 @@
1950419513
#include <math.h>
1950519514
1950619515
/*
1950719516
** State information for the analysis
1950819517
*/
19509
-typedef struct Analysis Analysis;
19510
-struct Analysis {
19518
+typedef struct DiskUsed DiskUsed;
19519
+struct DiskUsed {
1951119520
sqlite3 *db; /* Database connection */
1951219521
sqlite3_context *context; /* SQL function context */
1951319522
sqlite3_str *pOut; /* Write output here */
1951419523
char *zSU; /* Name of the temp.space_used table */
1951519524
const char *zSchema; /* Schema to be analyzed */
1951619525
};
1951719526
1951819527
/*
19519
-** Free all resources that the Analysis object references and
19520
-** reset the Analysis object.
19528
+** Free all resources that the DiskUsed object references and
19529
+** reset the DiskUsed object.
1952119530
**
19522
-** Call this routine multiple times on the same Analysis object
19531
+** Call this routine multiple times on the same DiskUsed object
1952319532
** is a harmless no-op, as long as the memory for the object itself
1952419533
** has not been freed.
1952519534
*/
19526
-static void analysisReset(Analysis *p){
19535
+static void diskusedReset(DiskUsed *p){
1952719536
if( p->zSU ){
1952819537
char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
1952919538
if( zSql ){
1953019539
sqlite3_exec(p->db, zSql, 0, 0, 0);
1953119540
sqlite3_free(zSql);
@@ -19538,11 +19547,11 @@
1953819547
1953919548
/*
1954019549
** Report an error using formatted text. If zFormat==NULL then report
1954119550
** an OOM error.
1954219551
*/
19543
-static void analysisError(Analysis *p, const char *zFormat, ...){
19552
+static void diskusedError(DiskUsed *p, const char *zFormat, ...){
1954419553
char *zErr;
1954519554
if( zFormat ){
1954619555
va_list ap;
1954719556
va_start(ap, zFormat);
1954819557
zErr = sqlite3_vmprintf(zFormat, ap);
@@ -19554,38 +19563,38 @@
1955419563
sqlite3_result_error_nomem(p->context);
1955519564
}else{
1955619565
sqlite3_result_error(p->context, zErr, -1);
1955719566
sqlite3_free(zErr);
1955819567
}
19559
- analysisReset(p);
19568
+ diskusedReset(p);
1956019569
}
1956119570
1956219571
/*
1956319572
** Prepare and return an SQL statement.
1956419573
*/
19565
-static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
19574
+static sqlite3_stmt *diskusedVPrep(DiskUsed *p, const char *zFmt, va_list ap){
1956619575
char *zSql;
1956719576
int rc;
1956819577
sqlite3_stmt *pStmt = 0;
1956919578
zSql = sqlite3_vmprintf(zFmt, ap);
19570
- if( zSql==0 ){ analysisError(p,0); return 0; }
19579
+ if( zSql==0 ){ diskusedError(p,0); return 0; }
1957119580
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
1957219581
if( rc ){
19573
- analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
19582
+ diskusedError(p, "SQL parse error: %s\nOriginal SQL: %s",
1957419583
sqlite3_errmsg(p->db), zSql);
1957519584
sqlite3_finalize(pStmt);
19576
- analysisReset(p);
19585
+ diskusedReset(p);
1957719586
pStmt = 0;
1957819587
}
1957919588
sqlite3_free(zSql);
1958019589
return pStmt;
1958119590
}
19582
-static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
19591
+static sqlite3_stmt *diskusedPrepare(DiskUsed *p, const char *zFormat, ...){
1958319592
va_list ap;
1958419593
sqlite3_stmt *pStmt = 0;
1958519594
va_start(ap, zFormat);
19586
- pStmt = analysisVPrep(p,zFormat,ap);
19595
+ pStmt = diskusedVPrep(p,zFormat,ap);
1958719596
va_end(ap);
1958819597
return pStmt;
1958919598
}
1959019599
1959119600
/*
@@ -19594,60 +19603,60 @@
1959419603
**
1959519604
** If rc is SQLITE_DONE or SQLITE_OK, then return false.
1959619605
**
1959719606
** The prepared statement is closed in either case.
1959819607
*/
19599
-static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
19608
+static int diskusedStmtFinish(DiskUsed *p, int rc, sqlite3_stmt *pStmt){
1960019609
if( rc==SQLITE_DONE ){
1960119610
rc = SQLITE_OK;
1960219611
}
1960319612
if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19604
- analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19613
+ diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
1960519614
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19606
- analysisReset(p);
19615
+ diskusedReset(p);
1960719616
}
1960819617
sqlite3_finalize(pStmt);
1960919618
return rc;
1961019619
}
1961119620
1961219621
/*
1961319622
** Run SQL. Return the number of errors.
1961419623
*/
19615
-static int analysisSql(Analysis *p, const char *zFormat, ...){
19624
+static int diskusedSql(DiskUsed *p, const char *zFormat, ...){
1961619625
va_list ap;
1961719626
int rc;
1961819627
sqlite3_stmt *pStmt = 0;
1961919628
va_start(ap, zFormat);
19620
- pStmt = analysisVPrep(p,zFormat,ap);
19629
+ pStmt = diskusedVPrep(p,zFormat,ap);
1962119630
va_end(ap);
1962219631
if( pStmt==0 ) return 1;
1962319632
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
1962419633
if( rc==SQLITE_DONE ){
1962519634
rc = SQLITE_OK;
1962619635
}else{
19627
- analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19636
+ diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
1962819637
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19629
- analysisReset(p);
19638
+ diskusedReset(p);
1963019639
}
1963119640
sqlite3_finalize(pStmt);
1963219641
return rc;
1963319642
}
1963419643
1963519644
/*
1963619645
** Run an SQL query that returns an integer. Write that integer
1963719646
** into *piRes. Return the number of errors.
1963819647
*/
19639
-static int analysisSqlInt(
19640
- Analysis *p,
19648
+static int diskusedSqlInt(
19649
+ DiskUsed *p,
1964119650
sqlite3_int64 *piRes,
1964219651
const char *zFormat, ...
1964319652
){
1964419653
va_list ap;
1964519654
int rc;
1964619655
sqlite3_stmt *pStmt = 0;
1964719656
va_start(ap, zFormat);
19648
- pStmt = analysisVPrep(p,zFormat,ap);
19657
+ pStmt = diskusedVPrep(p,zFormat,ap);
1964919658
va_end(ap);
1965019659
if( pStmt==0 ) return 1;
1965119660
rc = sqlite3_step(pStmt);
1965219661
if( rc==SQLITE_ROW ){
1965319662
*piRes = sqlite3_column_int64(pStmt, 0);
@@ -19655,14 +19664,14 @@
1965519664
}else if( rc==SQLITE_DONE ){
1965619665
rc = SQLITE_OK;
1965719666
}else{
1965819667
if( p->db ){
1965919668
/* p->db is NULL if there was some prior error */
19660
- analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19669
+ diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
1966119670
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
1966219671
}
19663
- analysisReset(p);
19672
+ diskusedReset(p);
1966419673
}
1966519674
sqlite3_finalize(pStmt);
1966619675
return rc;
1966719676
}
1966819677
@@ -19671,20 +19680,20 @@
1967119680
** by the format string. If the output is initially empty, begin
1967219681
** the title line with "/" so that it forms the beginning of a C-style
1967319682
** comment. Otherwise begin with a new-line. Always finish with a
1967419683
** newline.
1967519684
*/
19676
-static void analysisTitle(Analysis *p, const char *zFormat, ...){
19685
+static void diskusedTitle(DiskUsed *p, const char *zFormat, ...){
1967719686
char *zFirst;
1967819687
char *zTitle;
1967919688
size_t nTitle;
1968019689
va_list ap;
1968119690
va_start(ap, zFormat);
1968219691
zTitle = sqlite3_vmprintf(zFormat, ap);
1968319692
va_end(ap);
1968419693
if( zTitle==0 ){
19685
- analysisError(p, 0);
19694
+ diskusedError(p, 0);
1968619695
return;
1968719696
}
1968819697
zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
1968919698
nTitle = strlen(zTitle);
1969019699
if( nTitle>=75 ){
@@ -19699,12 +19708,12 @@
1969919708
/*
1970019709
** Add an output line that begins with the zDesc text extended out to
1970119710
** 50 columns with "." characters, and followed by whatever text is
1970219711
** described by zFormat.
1970319712
*/
19704
-static void analysisLine(
19705
- Analysis *p, /* Analysis context */
19713
+static void diskusedLine(
19714
+ DiskUsed *p, /* DiskUsed context */
1970619715
const char *zDesc, /* Description */
1970719716
const char *zFormat, /* Argument to the description */
1970819717
...
1970919718
){
1971019719
char *zTxt;
@@ -19712,14 +19721,14 @@
1971219721
va_list ap;
1971319722
va_start(ap, zFormat);
1971419723
zTxt = sqlite3_vmprintf(zFormat, ap);
1971519724
va_end(ap);
1971619725
if( zTxt==0 ){
19717
- analysisError(p, 0);
19726
+ diskusedError(p, 0);
1971819727
return;
1971919728
}
19720
- nDesc = strlen(zDesc);
19729
+ nDesc = zDesc ? strlen(zDesc) : 0;
1972119730
if( nDesc>=50 ){
1972219731
sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
1972319732
}else{
1972419733
int nExtra = 50 - (int)nDesc;
1972519734
sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
@@ -19729,11 +19738,11 @@
1972919738
/*
1973019739
** Write a percentage into the output. The number written should show
1973119740
** two or three significant digits, with the decimal point being the fourth
1973219741
** character.
1973319742
*/
19734
-static void analysisPercent(Analysis *p, double r){
19743
+static void diskusedPercent(DiskUsed *p, double r){
1973519744
char zNum[100];
1973619745
char *zDP;
1973719746
int nLeadingDigit;
1973819747
int sz;
1973919748
sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
@@ -19758,12 +19767,12 @@
1975819767
**
1975919768
** The title if the subreport is given by zTitle. zWhere is
1976019769
** a boolean expression that can go in the WHERE clause to select
1976119770
** the relevant rows of the s.zSU table.
1976219771
*/
19763
-static int analysisSubreport(
19764
- Analysis *p, /* Analysis context */
19772
+static int diskusedSubreport(
19773
+ DiskUsed *p, /* DiskUsed context */
1976519774
char *zTitle, /* Title for this subreport */
1976619775
char *zWhere, /* WHERE clause for this subreport */
1976719776
sqlite3_int64 pgsz, /* Database page size */
1976819777
sqlite3_int64 nPage /* Number of pages in entire database */
1976919778
){
@@ -19787,14 +19796,14 @@
1978719796
sqlite3_int64 total_unused; /* Total unused bytes */
1978819797
sqlite3_int64 total_meta; /* Total metadata */
1978919798
int rc;
1979019799
1979119800
if( zTitle==0 || zWhere==0 ){
19792
- analysisError(p, 0);
19801
+ diskusedError(p, 0);
1979319802
return SQLITE_NOMEM;
1979419803
}
19795
- pStmt = analysisPrepare(p,
19804
+ pStmt = diskusedPrepare(p,
1979619805
"SELECT\n"
1979719806
" sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
1979819807
" sum(payload),\n" /* 1 */
1979919808
" sum(ovfl_payload),\n" /* 2 */
1980019809
" max(mx_payload),\n" /* 3 */
@@ -19811,11 +19820,11 @@
1981119820
" FROM temp.%s WHERE %s",
1981219821
p->zSU, zWhere);
1981319822
if( pStmt==0 ) return 1;
1981419823
rc = sqlite3_step(pStmt);
1981519824
if( rc==SQLITE_ROW ){
19816
- analysisTitle(p, "%s", zTitle);
19825
+ diskusedTitle(p, "%s", zTitle);
1981719826
1981819827
nentry = sqlite3_column_int64(pStmt, 0);
1981919828
payload = sqlite3_column_int64(pStmt, 1);
1982019829
ovfl_payload = sqlite3_column_int64(pStmt, 2);
1982119830
mx_payload = sqlite3_column_int64(pStmt, 3);
@@ -19830,73 +19839,73 @@
1983019839
cnt = sqlite3_column_int64(pStmt, 12);
1983119840
int_cell = sqlite3_column_int64(pStmt, 13);
1983219841
rc = SQLITE_DONE;
1983319842
1983419843
total_pages = leaf_pages + int_pages + ovfl_pages;
19835
- analysisLine(p, "Percentage of total database", "%.3g%%\n",
19844
+ diskusedLine(p, "Percentage of total database", "%.3g%%\n",
1983619845
(total_pages*100.0)/(double)nPage);
19837
- analysisLine(p, "Number of entries", "%lld\n", nentry);
19846
+ diskusedLine(p, "Number of entries", "%lld\n", nentry);
1983819847
storage = total_pages*pgsz;
19839
- analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
19840
- analysisLine(p, "Bytes of payload", "%-11lld ", payload);
19841
- analysisPercent(p, payload*100.0/(double)storage);
19848
+ diskusedLine(p, "Bytes of storage consumed", "%lld\n", storage);
19849
+ diskusedLine(p, "Bytes of payload", "%-11lld ", payload);
19850
+ diskusedPercent(p, payload*100.0/(double)storage);
1984219851
if( ovfl_cnt>0 ){
19843
- analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19844
- analysisPercent(p, ovfl_payload*100.0/(double)payload);
19852
+ diskusedLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19853
+ diskusedPercent(p, ovfl_payload*100.0/(double)payload);
1984519854
}
1984619855
total_unused = leaf_unused + int_unused + ovfl_unused;
1984719856
total_meta = storage - payload - total_unused;
19848
- analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
19849
- analysisPercent(p, total_meta*100.0/(double)storage);
19857
+ diskusedLine(p, "Bytes of metadata","%-11lld ", total_meta);
19858
+ diskusedPercent(p, total_meta*100.0/(double)storage);
1985019859
if( cnt==1 ){
19851
- analysisLine(p, "B-tree depth", "%lld\n", depth);
19860
+ diskusedLine(p, "B-tree depth", "%lld\n", depth);
1985219861
if( int_cell>1 ){
19853
- analysisLine(p, "Average fanout", "%.1f\n",
19862
+ diskusedLine(p, "Average fanout", "%.1f\n",
1985419863
(double)(int_cell+int_pages)/(double)int_pages);
1985519864
}
1985619865
}
1985719866
if( nentry>0 ){
19858
- analysisLine(p, "Average payload per entry", "%.1f\n",
19867
+ diskusedLine(p, "Average payload per entry", "%.1f\n",
1985919868
(double)payload/(double)nentry);
19860
- analysisLine(p, "Average unused bytes per entry", "%.1f\n",
19869
+ diskusedLine(p, "Average unused bytes per entry", "%.1f\n",
1986119870
(double)total_unused/(double)nentry);
19862
- analysisLine(p, "Average metadata per entry", "%.1f\n",
19871
+ diskusedLine(p, "Average metadata per entry", "%.1f\n",
1986319872
(double)total_meta/(double)nentry);
1986419873
}
19865
- analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19866
- if( nentry>0 ){
19867
- analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19868
- analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
19869
- }
19870
- if( int_pages>0 ){
19871
- analysisLine(p, "Index pages used", "%lld\n", int_pages);
19872
- }
19873
- analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
19874
- if( ovfl_cnt ){
19875
- analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19876
- }
19877
- analysisLine(p, "Total pages used", "%lld\n", total_pages);
19878
- if( int_pages>0 ){
19879
- analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19880
- }
19881
- analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19882
- if( ovfl_cnt ){
19883
- analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19884
- }
19885
- analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19886
- analysisPercent(p, total_unused*100.0/(double)storage);
19887
- }
19888
- return analysisStmtFinish(p, rc, pStmt);
19889
-}
19890
-
19891
-/*
19892
-** SQL Function: analyze(SCHEMA)
19874
+ diskusedLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19875
+ if( nentry>0 ){
19876
+ diskusedLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19877
+ diskusedPercent(p, ovfl_cnt*100.0/(double)nentry);
19878
+ }
19879
+ if( int_pages>0 ){
19880
+ diskusedLine(p, "Index pages used", "%lld\n", int_pages);
19881
+ }
19882
+ diskusedLine(p, "Primary pages used", "%lld\n", leaf_pages);
19883
+ if( ovfl_cnt ){
19884
+ diskusedLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19885
+ }
19886
+ diskusedLine(p, "Total pages used", "%lld\n", total_pages);
19887
+ if( int_pages>0 ){
19888
+ diskusedLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19889
+ }
19890
+ diskusedLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19891
+ if( ovfl_cnt ){
19892
+ diskusedLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19893
+ }
19894
+ diskusedLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19895
+ diskusedPercent(p, total_unused*100.0/(double)storage);
19896
+ }
19897
+ return diskusedStmtFinish(p, rc, pStmt);
19898
+}
19899
+
19900
+/*
19901
+** SQL Function: diskused(SCHEMA)
1989319902
**
1989419903
** Analyze the database schema named in the argument. Return text
19895
-** containing the analysis.
19904
+** containing the space utilization stats.
1989619905
*/
19897
-static void analyzeFunc(
19906
+static void diskusedFunc(
1989819907
sqlite3_context *context,
1989919908
int argc,
1990019909
sqlite3_value **argv
1990119910
){
1990219911
int rc;
@@ -19907,47 +19916,47 @@
1990719916
sqlite3_int64 nPage;
1990819917
sqlite3_int64 nPageInUse;
1990919918
sqlite3_int64 nFreeList;
1991019919
sqlite3_int64 nIndex;
1991119920
sqlite3_int64 nWORowid;
19912
- Analysis s;
19921
+ DiskUsed s;
1991319922
sqlite3_uint64 r[2];
1991419923
1991519924
(void)argc;
1991619925
memset(&s, 0, sizeof(s));
1991719926
s.db = sqlite3_context_db_handle(context);
1991819927
s.context = context;
1991919928
s.pOut = sqlite3_str_new(0);
1992019929
if( sqlite3_str_errcode(s.pOut) ){
19921
- analysisError(&s, 0);
19930
+ diskusedError(&s, 0);
1992219931
return;
1992319932
}
1992419933
s.zSchema = (const char*)sqlite3_value_text(argv[0]);
1992519934
if( s.zSchema==0 ){
1992619935
s.zSchema = "main";
1992719936
}else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19928
- analysisReset(&s);
19937
+ diskusedReset(&s);
1992919938
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
1993019939
return;
1993119940
}
1993219941
ii = 0;
19933
- rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
19942
+ rc = diskusedSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
1993419943
" WHERE name=%Q COLLATE nocase",s.zSchema);
1993519944
if( rc || ii==0 ){
19936
- analysisReset(&s);
19945
+ diskusedReset(&s);
1993719946
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
1993819947
return;
1993919948
}
1994019949
sqlite3_randomness(sizeof(r), &r);
19941
- s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
19942
- if( s.zSU==0 ){ analysisError(&s, 0); return; }
19950
+ s.zSU = sqlite3_mprintf("diskused%016llx%016llx", r[0], r[1]);
19951
+ if( s.zSU==0 ){ diskusedError(&s, 0); return; }
1994319952
1994419953
/* The s.zSU table contains the data used for the analysis.
1994519954
** The table name contains 128-bits of randomness to avoid
1994619955
** collisions with preexisting tables in temp.
1994719956
*/
19948
- rc = analysisSql(&s,
19957
+ rc = diskusedSql(&s,
1994919958
"CREATE TABLE temp.%s(\n"
1995019959
" name text, -- A table or index\n"
1995119960
" tblname text, -- Table that owns name\n"
1995219961
" is_index boolean, -- TRUE if it is an index\n"
1995319962
" is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
@@ -19970,11 +19979,11 @@
1997019979
);
1997119980
if( rc ) return;
1997219981
1997319982
/* Populate the s.zSU table
1997419983
*/
19975
- rc = analysisSql(&s,
19984
+ rc = diskusedSql(&s,
1997619985
"WITH\n"
1997719986
" allidx(idxname) AS (\n"
1997819987
" SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
1997919988
" ),\n"
1998019989
" allobj(allname,tblname,isidx,isworowid) AS (\n"
@@ -20022,141 +20031,143 @@
2002220031
s.zSchema /* JOIN dbstat(%Q) */
2002320032
);
2002420033
if( rc ) return;
2002520034
2002620035
nPage = 0;
20027
- rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20036
+ rc = diskusedSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
2002820037
if( rc ) return;
2002920038
if( nPage<=0 ){
2003020039
/* Very brief reply for an empty database */
20031
- analysisReset(&s);
20040
+ diskusedReset(&s);
2003220041
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
2003320042
return;
2003420043
}
2003520044
2003620045
/* Begin generating the report */
20037
- analysisTitle(&s, "Database storage utilization report");
20046
+ diskusedTitle(&s, "Database storage utilization report");
2003820047
pgsz = 0;
20039
- rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20048
+ rc = diskusedSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
2004020049
if( rc ) return;
20041
- analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
20042
- analysisLine(&s, "Pages in the database", "%lld\n", nPage);
20050
+ diskusedLine(&s, "Page size in bytes","%lld\n",pgsz);
20051
+ diskusedLine(&s, "Pages in the database", "%lld\n", nPage);
2004320052
2004420053
nPageInUse = 0;
20045
- rc = analysisSqlInt(&s, &nPageInUse,
20054
+ rc = diskusedSqlInt(&s, &nPageInUse,
2004620055
"SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
2004720056
if( rc ) return;
20048
- analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20049
- analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
20057
+ diskusedLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20058
+ diskusedPercent(&s, (nPageInUse*100.0)/(double)nPage);
2005020059
2005120060
nFreeList = 0;
20052
- rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20061
+ rc = diskusedSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
2005320062
if( rc ) return;
20054
- analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20055
- analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
20063
+ diskusedLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20064
+ diskusedPercent(&s, (nFreeList*100.0)/(double)nPage);
2005620065
2005720066
ii = 0;
20058
- rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20067
+ rc = diskusedSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
2005920068
if( rc ) return;
2006020069
if( ii==0 || nPage<=1 ){
2006120070
ii = 0;
2006220071
}else{
2006320072
double rPtrsPerPage = pgsz/5;
2006420073
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
2006520074
ii = (sqlite3_int64)ceil(rAvPage);
2006620075
}
20067
- analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20068
- analysisPercent(&s, (ii*100.0)/(double)nPage);
20076
+ diskusedLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20077
+ diskusedPercent(&s, (ii*100.0)/(double)nPage);
2006920078
2007020079
ii = 0;
20071
- rc = analysisSqlInt(&s, &ii,
20080
+ rc = diskusedSqlInt(&s, &ii,
2007220081
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
2007320082
s.zSchema);
2007420083
if( rc ) return;
20075
- analysisLine(&s, "Number of tables", "%lld\n", ii);
20084
+ diskusedLine(&s, "Number of tables", "%lld\n", ii);
2007620085
nWORowid = 0;
20077
- rc = analysisSqlInt(&s, &nWORowid,
20086
+ rc = diskusedSqlInt(&s, &nWORowid,
2007820087
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
2007920088
s.zSchema);
2008020089
if( rc ) return;
2008120090
if( nWORowid>0 ){
20082
- analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20083
- analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
20091
+ diskusedLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20092
+ diskusedLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
2008420093
}
2008520094
nIndex = 0;
20086
- rc = analysisSqlInt(&s, &nIndex,
20095
+ rc = diskusedSqlInt(&s, &nIndex,
2008720096
"SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
2008820097
s.zSchema);
2008920098
if( rc ) return;
20090
- analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
20099
+ diskusedLine(&s, "Number of indexes", "%lld\n", nIndex);
2009120100
ii = 0;
20092
- rc = analysisSqlInt(&s, &ii,
20101
+ rc = diskusedSqlInt(&s, &ii,
2009320102
"SELECT count(*) FROM \"%w\".sqlite_schema"
2009420103
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
2009520104
s.zSchema);
2009620105
if( rc ) return;
20097
- analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20098
- analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
20099
- analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20106
+ diskusedLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20107
+ diskusedLine(&s, "Number of implied indexes", "%lld\n", ii);
20108
+ diskusedLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
2010020109
ii = 0;
20101
- rc = analysisSqlInt(&s, &ii,
20110
+ rc = diskusedSqlInt(&s, &ii,
2010220111
"SELECT sum(payload) FROM temp.%s"
2010320112
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
2010420113
s.zSU);
2010520114
if( rc ) return;
20106
- analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
20107
- analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
20115
+ diskusedLine(&s, "Bytes of payload", "%-11lld ", ii);
20116
+ diskusedPercent(&s, ii*100.0/(double)(pgsz*nPage));
2010820117
20109
- analysisTitle(&s, "Page counts for all tables with their indexes");
20110
- pStmt = analysisPrepare(&s,
20118
+ diskusedTitle(&s, "Page counts for all tables with their indexes");
20119
+ pStmt = diskusedPrepare(&s,
2011120120
"SELECT upper(tblname),\n"
2011220121
" sum(int_pages+leaf_pages+ovfl_pages)\n"
2011320122
" FROM temp.%s\n"
20123
+ " WHERE tblname IS NOT NULL\n"
20124
+ " GROUP BY 1\n"
20125
+ " ORDER BY 2 DESC, 1;",
20126
+ s.zSU);
20127
+ if( pStmt==0 ) return;
20128
+ while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20129
+ sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20130
+ diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20131
+ diskusedPercent(&s, (nn*100.0)/(double)nPage);
20132
+ }
20133
+ if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20134
+
20135
+ diskusedTitle(&s, "Page counts for all tables and indexes separately");
20136
+ pStmt = diskusedPrepare(&s,
20137
+ "SELECT upper(name),\n"
20138
+ " sum(int_pages+leaf_pages+ovfl_pages)\n"
20139
+ " FROM temp.%s\n"
20140
+ " WHERE name IS NOT NULL\n"
2011420141
" GROUP BY 1\n"
2011520142
" ORDER BY 2 DESC, 1;",
2011620143
s.zSU);
2011720144
if( pStmt==0 ) return;
2011820145
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
2011920146
sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20120
- analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20121
- analysisPercent(&s, (nn*100.0)/(double)nPage);
20122
- }
20123
- if( analysisStmtFinish(&s, rc, pStmt) ) return;
20124
-
20125
- analysisTitle(&s, "Page counts for all tables and indexes separately");
20126
- pStmt = analysisPrepare(&s,
20127
- "SELECT upper(name),\n"
20128
- " sum(int_pages+leaf_pages+ovfl_pages)\n"
20129
- " FROM temp.%s\n"
20130
- " GROUP BY 1\n"
20131
- " ORDER BY 2 DESC, 1;",
20132
- s.zSU);
20133
- if( pStmt==0 ) return;
20134
- while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20135
- sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20136
- analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20137
- analysisPercent(&s, (nn*100.0)/(double)nPage);
20138
- }
20139
- if( analysisStmtFinish(&s, rc, pStmt) ) return;
20140
-
20141
- rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
20147
+ diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20148
+ diskusedPercent(&s, (nn*100.0)/(double)nPage);
20149
+ }
20150
+ if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20151
+
20152
+ rc = diskusedSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
2014220153
if( rc ) return;
20143
- rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20154
+ rc = diskusedSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
2014420155
if( rc ) return;
2014520156
if( nWORowid>0 ){
20146
- rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20157
+ rc = diskusedSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
2014720158
pgsz, nPage);
2014820159
if( rc ) return;
20149
- rc = analysisSubreport(&s, "All rowid tables",
20160
+ rc = diskusedSubreport(&s, "All rowid tables",
2015020161
"NOT is_without_rowid AND NOT is_index",
2015120162
pgsz, nPage);
2015220163
if( rc ) return;
2015320164
}
20154
- rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20165
+ rc = diskusedSubreport(&s, "All indexes", "is_index", pgsz, nPage);
2015520166
if( rc ) return;
2015620167
20157
- pStmt = analysisPrepare(&s,
20168
+ pStmt = diskusedPrepare(&s,
2015820169
"SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
2015920170
" GROUP BY 1 ORDER BY 1",
2016020171
s.zSU);
2016120172
if( pStmt==0 ) return;
2016220173
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
@@ -20164,37 +20175,37 @@
2016420175
const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
2016520176
int nSubIndex = sqlite3_column_int(pStmt, 2);
2016620177
if( nSubIndex==0 ){
2016720178
char *zTitle = sqlite3_mprintf("Table %s", zUpper);
2016820179
char *zWhere = sqlite3_mprintf("name=%Q", zName);
20169
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20180
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2017020181
sqlite3_free(zTitle);
2017120182
sqlite3_free(zWhere);
2017220183
if( rc ) break;
2017320184
}else{
2017420185
sqlite3_stmt *pS2;
2017520186
char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
2017620187
char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20177
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20188
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2017820189
sqlite3_free(zTitle);
2017920190
sqlite3_free(zWhere);
2018020191
if( rc ) break;
2018120192
zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
2018220193
zWhere = sqlite3_mprintf("name=%Q", zName);
20183
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20194
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2018420195
sqlite3_free(zTitle);
2018520196
sqlite3_free(zWhere);
2018620197
if( rc ) break;
2018720198
if( nSubIndex>1 ){
2018820199
zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
2018920200
zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20190
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20201
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2019120202
sqlite3_free(zTitle);
2019220203
sqlite3_free(zWhere);
2019320204
if( rc ) break;
2019420205
}
20195
- pS2 = analysisPrepare(&s,
20206
+ pS2 = diskusedPrepare(&s,
2019620207
"SELECT name, upper(name) FROM temp.%s"
2019720208
" WHERE is_index AND tblname=%Q",
2019820209
s.zSU, zName);
2019920210
if( pS2==0 ){
2020020211
rc = SQLITE_NOMEM;
@@ -20203,25 +20214,25 @@
2020320214
while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
2020420215
const char *zU = (const char*)sqlite3_column_text(pS2, 1);
2020520216
const char *zN = (const char*)sqlite3_column_text(pS2, 0);
2020620217
zTitle = sqlite3_mprintf("Index %s", zU);
2020720218
zWhere = sqlite3_mprintf("name=%Q", zN);
20208
- rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20219
+ rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
2020920220
sqlite3_free(zTitle);
2021020221
sqlite3_free(zWhere);
2021120222
if( rc ) break;
2021220223
}
20213
- rc = analysisStmtFinish(&s, rc, pS2);
20224
+ rc = diskusedStmtFinish(&s, rc, pS2);
2021420225
if( rc ) break;
2021520226
}
2021620227
}
20217
- if( analysisStmtFinish(&s, rc, pStmt) ) return;
20228
+ if( diskusedStmtFinish(&s, rc, pStmt) ) return;
2021820229
2021920230
/* Append SQL statements that will recreate the raw data used for
2022020231
** the analysis.
2022120232
*/
20222
- analysisTitle(&s, "Raw data used to generate this report");
20233
+ diskusedTitle(&s, "Raw data used to generate this report");
2022320234
sqlite3_str_appendf(s.pOut,
2022420235
"The following SQL will create a table named \"space_used\" which\n"
2022520236
"contains most of the information used to generate the report above.\n"
2022620237
"*/\n"
2022720238
);
@@ -20247,11 +20258,11 @@
2024720258
" ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
2024820259
" int_entries int -- B-tree entries on internal pages\n"/* 17 */
2024920260
");\n"
2025020261
"INSERT INTO space_used VALUES\n"
2025120262
);
20252
- pStmt = analysisPrepare(&s,
20263
+ pStmt = diskusedPrepare(&s,
2025320264
"SELECT quote(name), quote(tblname),\n" /* 0..1 */
2025420265
" is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
2025520266
" depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
2025620267
" int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
2025720268
" leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
@@ -20282,11 +20293,11 @@
2028220293
sqlite3_column_int64(pStmt, 15),
2028320294
sqlite3_column_int64(pStmt, 16),
2028420295
sqlite3_column_int64(pStmt, 17));
2028520296
}
2028620297
if( rc!=SQLITE_DONE ){
20287
- analysisError(&s, "SQL run-time error: %s\nSQL: %s",
20298
+ diskusedError(&s, "SQL run-time error: %s\nSQL: %s",
2028820299
sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
2028920300
sqlite3_finalize(pStmt);
2029020301
return;
2029120302
}
2029220303
sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
@@ -20295,32 +20306,32 @@
2029520306
if( sqlite3_str_length(s.pOut) ){
2029620307
sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
2029720308
sqlite3_free);
2029820309
s.pOut = 0;
2029920310
}
20300
- analysisReset(&s);
20311
+ diskusedReset(&s);
2030120312
}
2030220313
2030320314
2030420315
#ifdef _WIN32
2030520316
2030620317
#endif
20307
-int sqlite3_analyze_init(
20318
+int sqlite3_diskused_init(
2030820319
sqlite3 *db,
2030920320
char **pzErrMsg,
2031020321
const sqlite3_api_routines *pApi
2031120322
){
2031220323
int rc = SQLITE_OK;
2031320324
SQLITE_EXTENSION_INIT2(pApi);
2031420325
(void)pzErrMsg; /* Unused parameter */
20315
- rc = sqlite3_create_function(db, "analyze", 1,
20326
+ rc = sqlite3_create_function(db, "diskused", 1,
2031620327
SQLITE_UTF8|SQLITE_INNOCUOUS,
20317
- 0, analyzeFunc, 0, 0);
20328
+ 0, diskusedFunc, 0, 0);
2031820329
return rc;
2031920330
}
2032020331
20321
-/************************* End ext/misc/analyze.c ********************/
20332
+/************************* End ext/misc/diskused.c ********************/
2032220333
2032320334
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
2032420335
#define SQLITE_SHELL_HAVE_RECOVER 1
2032520336
#else
2032620337
#define SQLITE_SHELL_HAVE_RECOVER 0
@@ -26321,10 +26332,47 @@
2632126332
if( *az ){
2632226333
memcpy(*az, zNew, n+1 );
2632326334
}
2632426335
}
2632526336
}
26337
+
26338
+/* Forward reference */
26339
+static int pickStr(const char *zArg, char **pzErr, ...);
26340
+
26341
+/*
26342
+** Change the limits on the display mode. Return 0 on
26343
+** success. Return non-zero if zArg is mis-formatted.
26344
+**
26345
+** Valid arguments:
26346
+**
26347
+** "on" Default limits
26348
+** "off" All limits turned off
26349
+** L,C Line and Characters limits set
26350
+** L,C,T Line, Character, and Title limits set
26351
+**
26352
+** Anything else returns non-zero
26353
+*/
26354
+static int modeSetLimit(ShellState *p, const char *zArg){
26355
+ int k = zArg==0 ? 1 : pickStr(zArg,0,"on","off","");
26356
+ if( k==0 ){
26357
+ p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
26358
+ p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
26359
+ p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
26360
+ }else if( k==1 ){
26361
+ p->mode.spec.nLineLimit = 0;
26362
+ p->mode.spec.nCharLimit = 0;
26363
+ p->mode.spec.nTitleLimit = 0;
26364
+ }else{
26365
+ int L, C, T = 0;
26366
+ int nNum = sscanf(zArg, "%d,%d,%d", &L, &C, &T);
26367
+ if( nNum<2 || L<0 || C<0 || T<0) return 1;
26368
+ p->mode.spec.nLineLimit = L;
26369
+ p->mode.spec.nCharLimit = C;
26370
+ if( nNum==3 ) p->mode.spec.nTitleLimit = T;
26371
+ }
26372
+ return 0;
26373
+}
2632626374
2632726375
/*
2632826376
** Change the mode to eMode
2632926377
*/
2633026378
static void modeChange(ShellState *p, unsigned char eMode){
@@ -26358,10 +26406,11 @@
2635826406
modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
2635926407
}else if( eMode==MODE_BATCH ){
2636026408
u8 mFlags = p->mode.mFlags;
2636126409
modeFree(&p->mode);
2636226410
modeChange(p, MODE_List);
26411
+ modeSetLimit(p, "off");
2636326412
p->mode.mFlags = mFlags;
2636426413
}else if( eMode==MODE_TTY ){
2636526414
u8 mFlags = p->mode.mFlags;
2636626415
modeFree(&p->mode);
2636726416
modeChange(p, MODE_QBox);
@@ -28446,12 +28495,12 @@
2844628495
".databases List names and files of attached databases",
2844728496
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
2844828497
#if SQLITE_SHELL_HAVE_RECOVER
2844928498
".dbinfo ?DB? Show status information about the database",
2845028499
#endif
28451
- ".dbstat ?SCHEMA? Report database space and size stats",
2845228500
".dbtotxt Hex dump of the database file",
28501
+ ".diskused ?SCHEMA? Report database space and size stats",
2845328502
".dump ?OBJECTS? Render database content as SQL",
2845428503
" Options:",
2845528504
" --data-only Output only INSERT statements",
2845628505
" --newlines Allow unescaped newline characters in output",
2845728506
" --nosys Omit system tables (ex: \"sqlite_stat1\")",
@@ -29461,11 +29510,11 @@
2946129510
sqlite3_base64_init(p->db, 0, 0);
2946229511
sqlite3_base85_init(p->db, 0, 0);
2946329512
sqlite3_regexp_init(p->db, 0, 0);
2946429513
sqlite3_ieee_init(p->db, 0, 0);
2946529514
sqlite3_series_init(p->db, 0, 0);
29466
- sqlite3_analyze_init(p->db, 0, 0);
29515
+ sqlite3_diskused_init(p->db, 0, 0);
2946729516
#ifndef SQLITE_SHELL_FIDDLE
2946829517
sqlite3_fileio_init(p->db, 0, 0);
2946929518
sqlite3_completion_init(p->db, 0, 0);
2947029519
#endif
2947129520
#ifdef SQLITE_HAVE_ZLIB
@@ -33123,30 +33172,14 @@
3312333172
}else if( optionMatch(z,"limits") ){
3312433173
if( (++i)>=nArg ){
3312533174
dotCmdError(p, i-1, "missing argument", 0);
3312633175
return 1;
3312733176
}
33128
- k = pickStr(azArg[i],0,"on","off","");
33129
- if( k==0 ){
33130
- p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
33131
- p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
33132
- p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
33133
- }else if( k==1 ){
33134
- p->mode.spec.nLineLimit = 0;
33135
- p->mode.spec.nCharLimit = 0;
33136
- p->mode.spec.nTitleLimit = 0;
33137
- }else{
33138
- int L, C, T = 0;
33139
- int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
33140
- if( nNum<2 || L<0 || C<0 || T<0){
33141
- dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
33142
- " and T are unsigned integers");
33143
- return 1;
33144
- }
33145
- p->mode.spec.nLineLimit = L;
33146
- p->mode.spec.nCharLimit = C;
33147
- if( nNum==3 ) p->mode.spec.nTitleLimit = T;
33177
+ if( modeSetLimit(p, azArg[i]) ){
33178
+ dotCmdError(p, i, "bad argument", "Should be \"on\" or \"off\" or "
33179
+ "\"L,C,T\" where L, C, and T are unsigned integers");
33180
+ return 1;
3314833181
}
3314933182
chng = 1;
3315033183
}else if( optionMatch(z,"list") ){
3315133184
int ii;
3315233185
cli_puts("available modes:", p->out);
@@ -34360,11 +34393,16 @@
3436034393
if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
3436134394
rc = shell_dbinfo_command(p, nArg, azArg);
3436234395
}else
3436334396
#endif /* SQLITE_SHELL_HAVE_RECOVER */
3436434397
34365
- if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
34398
+ if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34399
+ open_db(p, 0);
34400
+ rc = shell_dbtotxt_command(p, nArg, azArg);
34401
+ }else
34402
+
34403
+ if( c=='d' && n==8 && cli_strncmp(azArg[0], "diskused", n)==0 ){
3436634404
const char *zSchema = 0;
3436734405
int ii;
3436834406
char *zSql;
3436934407
open_db(p, 0);
3437034408
for(ii=1; ii<nArg; ii++){
@@ -34379,27 +34417,19 @@
3437934417
rc = 1;
3438034418
goto meta_command_exit;
3438134419
}
3438234420
zSchema = z;
3438334421
}
34384
- zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
34422
+ zSql = sqlite3_mprintf("SELECT diskused(%Q)", zSchema);
3438534423
shell_check_oom(zSql);
3438634424
modePush(p);
3438734425
modeChange(p, MODE_BATCH);
34388
- p->mode.spec.nLineLimit = 0;
34389
- p->mode.spec.nCharLimit = 0;
34390
- p->mode.spec.nTitleLimit = 0;
3439134426
shell_exec(p, zSql, 0);
3439234427
modePop(p);
3439334428
sqlite3_free(zSql);
3439434429
}else
3439534430
34396
- if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34397
- open_db(p, 0);
34398
- rc = shell_dbtotxt_command(p, nArg, azArg);
34399
- }else
34400
-
3440134431
if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
3440234432
char *zLike = 0;
3440334433
char *zSql;
3440434434
int i;
3440534435
int savedShellFlags = p->shellFlgs;
@@ -37755,17 +37785,17 @@
3775537785
" -- treat no subsequent arguments as options\n"
3775637786
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
3775737787
" -A ARGS... run \".archive ARGS\" and exit\n"
3775837788
#endif
3775937789
" -append append the database to the end of the file\n"
37760
- " -ascii set output mode to 'ascii'\n"
37790
+ " -ascii set '.mode ascii'\n"
3776137791
" -bail stop after hitting an error\n"
3776237792
" -batch force batch I/O\n"
37763
- " -box set output mode to 'box'\n"
37793
+ " -box set '.mode box'\n"
3776437794
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
37765
- " -column set output mode to 'column'\n"
37766
- " -csv set output mode to 'csv'\n"
37795
+ " -column set '.mode column'\n"
37796
+ " -csv set '.mode csv -limits off'\n"
3776737797
#if !defined(SQLITE_OMIT_DESERIALIZE)
3776837798
" -deserialize open the database using sqlite3_deserialize()\n"
3776937799
#endif
3777037800
" -echo print inputs before execution\n"
3777137801
" -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
@@ -37773,18 +37803,18 @@
3777337803
" -[no]header turn headers on or off\n"
3777437804
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
3777537805
" -heap SIZE Size of heap for memsys3 or memsys5\n"
3777637806
#endif
3777737807
" -help show this message\n"
37778
- " -html set output mode to HTML\n"
37808
+ " -html set '.mode html'\n"
3777937809
" -ifexists only open if database already exists\n"
3778037810
" -interactive force interactive I/O\n"
37781
- " -json set output mode to 'json'\n"
37782
- " -line set output mode to 'line'\n"
37783
- " -list set output mode to 'list'\n"
37811
+ " -json set '.mode json'\n"
37812
+ " -line set '.mode line'\n"
37813
+ " -list set '.mode list'\n"
3778437814
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
37785
- " -markdown set output mode to 'markdown'\n"
37815
+ " -markdown set '.mode markdown'\n"
3778637816
#if !defined(SQLITE_OMIT_DESERIALIZE)
3778737817
" -maxsize N maximum size for a --deserialize database\n"
3778837818
#endif
3778937819
" -memtrace trace all memory allocations and deallocations\n"
3779037820
" -mmap N default mmap size set to N\n"
@@ -37797,21 +37827,21 @@
3779737827
" -nonce STRING set the safe-mode escape nonce\n"
3779837828
" -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
3779937829
" -nullvalue TEXT set text string for NULL values. Default ''\n"
3780037830
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
3780137831
" -pcachetrace trace all page cache operations\n"
37802
- " -quote set output mode to 'quote'\n"
37832
+ " -quote set '.mode quote'\n"
3780337833
" -readonly open the database read-only\n"
3780437834
" -safe enable safe-mode\n"
3780537835
" -screenwidth N use N as the default screenwidth \n"
3780637836
" -separator SEP set output column separator. Default: '|'\n"
3780737837
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
3780837838
" -sorterref SIZE sorter references threshold size\n"
3780937839
#endif
3781037840
" -stats print memory stats before each finalize\n"
37811
- " -table set output mode to 'table'\n"
37812
- " -tabs set output mode to 'tabs'\n"
37841
+ " -table set '.mode table'\n"
37842
+ " -tabs set '.mode tabs'\n"
3781337843
" -unsafe-testing allow unsafe commands and modes for testing\n"
3781437844
" -version show SQLite version\n"
3781537845
" -vfs NAME use NAME as the default VFS\n"
3781637846
" -vfstrace enable tracing of all VFS calls\n"
3781737847
#ifdef SQLITE_HAVE_ZLIB
@@ -38409,10 +38439,11 @@
3840938439
modeChange(&data, MODE_Psql);
3841038440
}else if( cli_strcmp(z,"-box")==0 ){
3841138441
modeChange(&data, MODE_Box);
3841238442
}else if( cli_strcmp(z,"-csv")==0 ){
3841338443
modeChange(&data, MODE_Csv);
38444
+ modeSetLimit(&data, "off");
3841438445
}else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
3841538446
/* See similar code at tag-20250224-1 */
3841638447
const char *zEsc = argv[++i];
3841738448
int k;
3841838449
for(k=0; k<ArraySize(qrfEscNames); k++){
3841938450
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,16 +5,16 @@
5 **
6 ** ext/expert/sqlite3expert.c
7 ** ext/expert/sqlite3expert.h
8 ** ext/intck/sqlite3intck.c
9 ** ext/intck/sqlite3intck.h
10 ** ext/misc/analyze.c
11 ** ext/misc/appendvfs.c
12 ** ext/misc/base64.c
13 ** ext/misc/base85.c
14 ** ext/misc/completion.c
15 ** ext/misc/decimal.c
 
16 ** ext/misc/fileio.c
17 ** ext/misc/ieee754.c
18 ** ext/misc/memtrace.c
19 ** ext/misc/pcachetrace.c
20 ** ext/misc/regexp.c
@@ -19478,11 +19478,11 @@
19478 sqlite3_vfs_unregister(pVfs);
19479 sqlite3_free(pVfs);
19480 }
19481
19482 /************************* End ext/misc/vfstrace.c ********************/
19483 /************************* Begin ext/misc/analyze.c ******************/
19484 /*
19485 ** 2026-04-13
19486 **
19487 ** The author disclaims copyright to this source code. In place of
19488 ** a legal notice, here is a blessing:
@@ -19491,12 +19491,21 @@
19491 ** May you find forgiveness for yourself and forgive others.
19492 ** May you share freely, never taking more than you give.
19493 **
19494 ******************************************************************************
19495 **
19496 ** Partial reimplement of the sqlite3_analyzer utility program as
19497 ** loadable SQL function.
 
 
 
 
 
 
 
 
 
19498 */
19499 /* #include "sqlite3ext.h" */
19500 SQLITE_EXTENSION_INIT1
19501 #include <assert.h>
19502 #include <string.h>
@@ -19504,28 +19513,28 @@
19504 #include <math.h>
19505
19506 /*
19507 ** State information for the analysis
19508 */
19509 typedef struct Analysis Analysis;
19510 struct Analysis {
19511 sqlite3 *db; /* Database connection */
19512 sqlite3_context *context; /* SQL function context */
19513 sqlite3_str *pOut; /* Write output here */
19514 char *zSU; /* Name of the temp.space_used table */
19515 const char *zSchema; /* Schema to be analyzed */
19516 };
19517
19518 /*
19519 ** Free all resources that the Analysis object references and
19520 ** reset the Analysis object.
19521 **
19522 ** Call this routine multiple times on the same Analysis object
19523 ** is a harmless no-op, as long as the memory for the object itself
19524 ** has not been freed.
19525 */
19526 static void analysisReset(Analysis *p){
19527 if( p->zSU ){
19528 char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
19529 if( zSql ){
19530 sqlite3_exec(p->db, zSql, 0, 0, 0);
19531 sqlite3_free(zSql);
@@ -19538,11 +19547,11 @@
19538
19539 /*
19540 ** Report an error using formatted text. If zFormat==NULL then report
19541 ** an OOM error.
19542 */
19543 static void analysisError(Analysis *p, const char *zFormat, ...){
19544 char *zErr;
19545 if( zFormat ){
19546 va_list ap;
19547 va_start(ap, zFormat);
19548 zErr = sqlite3_vmprintf(zFormat, ap);
@@ -19554,38 +19563,38 @@
19554 sqlite3_result_error_nomem(p->context);
19555 }else{
19556 sqlite3_result_error(p->context, zErr, -1);
19557 sqlite3_free(zErr);
19558 }
19559 analysisReset(p);
19560 }
19561
19562 /*
19563 ** Prepare and return an SQL statement.
19564 */
19565 static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
19566 char *zSql;
19567 int rc;
19568 sqlite3_stmt *pStmt = 0;
19569 zSql = sqlite3_vmprintf(zFmt, ap);
19570 if( zSql==0 ){ analysisError(p,0); return 0; }
19571 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19572 if( rc ){
19573 analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
19574 sqlite3_errmsg(p->db), zSql);
19575 sqlite3_finalize(pStmt);
19576 analysisReset(p);
19577 pStmt = 0;
19578 }
19579 sqlite3_free(zSql);
19580 return pStmt;
19581 }
19582 static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
19583 va_list ap;
19584 sqlite3_stmt *pStmt = 0;
19585 va_start(ap, zFormat);
19586 pStmt = analysisVPrep(p,zFormat,ap);
19587 va_end(ap);
19588 return pStmt;
19589 }
19590
19591 /*
@@ -19594,60 +19603,60 @@
19594 **
19595 ** If rc is SQLITE_DONE or SQLITE_OK, then return false.
19596 **
19597 ** The prepared statement is closed in either case.
19598 */
19599 static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
19600 if( rc==SQLITE_DONE ){
19601 rc = SQLITE_OK;
19602 }
19603 if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19604 analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19605 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19606 analysisReset(p);
19607 }
19608 sqlite3_finalize(pStmt);
19609 return rc;
19610 }
19611
19612 /*
19613 ** Run SQL. Return the number of errors.
19614 */
19615 static int analysisSql(Analysis *p, const char *zFormat, ...){
19616 va_list ap;
19617 int rc;
19618 sqlite3_stmt *pStmt = 0;
19619 va_start(ap, zFormat);
19620 pStmt = analysisVPrep(p,zFormat,ap);
19621 va_end(ap);
19622 if( pStmt==0 ) return 1;
19623 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
19624 if( rc==SQLITE_DONE ){
19625 rc = SQLITE_OK;
19626 }else{
19627 analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19628 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19629 analysisReset(p);
19630 }
19631 sqlite3_finalize(pStmt);
19632 return rc;
19633 }
19634
19635 /*
19636 ** Run an SQL query that returns an integer. Write that integer
19637 ** into *piRes. Return the number of errors.
19638 */
19639 static int analysisSqlInt(
19640 Analysis *p,
19641 sqlite3_int64 *piRes,
19642 const char *zFormat, ...
19643 ){
19644 va_list ap;
19645 int rc;
19646 sqlite3_stmt *pStmt = 0;
19647 va_start(ap, zFormat);
19648 pStmt = analysisVPrep(p,zFormat,ap);
19649 va_end(ap);
19650 if( pStmt==0 ) return 1;
19651 rc = sqlite3_step(pStmt);
19652 if( rc==SQLITE_ROW ){
19653 *piRes = sqlite3_column_int64(pStmt, 0);
@@ -19655,14 +19664,14 @@
19655 }else if( rc==SQLITE_DONE ){
19656 rc = SQLITE_OK;
19657 }else{
19658 if( p->db ){
19659 /* p->db is NULL if there was some prior error */
19660 analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19661 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19662 }
19663 analysisReset(p);
19664 }
19665 sqlite3_finalize(pStmt);
19666 return rc;
19667 }
19668
@@ -19671,20 +19680,20 @@
19671 ** by the format string. If the output is initially empty, begin
19672 ** the title line with "/" so that it forms the beginning of a C-style
19673 ** comment. Otherwise begin with a new-line. Always finish with a
19674 ** newline.
19675 */
19676 static void analysisTitle(Analysis *p, const char *zFormat, ...){
19677 char *zFirst;
19678 char *zTitle;
19679 size_t nTitle;
19680 va_list ap;
19681 va_start(ap, zFormat);
19682 zTitle = sqlite3_vmprintf(zFormat, ap);
19683 va_end(ap);
19684 if( zTitle==0 ){
19685 analysisError(p, 0);
19686 return;
19687 }
19688 zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
19689 nTitle = strlen(zTitle);
19690 if( nTitle>=75 ){
@@ -19699,12 +19708,12 @@
19699 /*
19700 ** Add an output line that begins with the zDesc text extended out to
19701 ** 50 columns with "." characters, and followed by whatever text is
19702 ** described by zFormat.
19703 */
19704 static void analysisLine(
19705 Analysis *p, /* Analysis context */
19706 const char *zDesc, /* Description */
19707 const char *zFormat, /* Argument to the description */
19708 ...
19709 ){
19710 char *zTxt;
@@ -19712,14 +19721,14 @@
19712 va_list ap;
19713 va_start(ap, zFormat);
19714 zTxt = sqlite3_vmprintf(zFormat, ap);
19715 va_end(ap);
19716 if( zTxt==0 ){
19717 analysisError(p, 0);
19718 return;
19719 }
19720 nDesc = strlen(zDesc);
19721 if( nDesc>=50 ){
19722 sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
19723 }else{
19724 int nExtra = 50 - (int)nDesc;
19725 sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
@@ -19729,11 +19738,11 @@
19729 /*
19730 ** Write a percentage into the output. The number written should show
19731 ** two or three significant digits, with the decimal point being the fourth
19732 ** character.
19733 */
19734 static void analysisPercent(Analysis *p, double r){
19735 char zNum[100];
19736 char *zDP;
19737 int nLeadingDigit;
19738 int sz;
19739 sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
@@ -19758,12 +19767,12 @@
19758 **
19759 ** The title if the subreport is given by zTitle. zWhere is
19760 ** a boolean expression that can go in the WHERE clause to select
19761 ** the relevant rows of the s.zSU table.
19762 */
19763 static int analysisSubreport(
19764 Analysis *p, /* Analysis context */
19765 char *zTitle, /* Title for this subreport */
19766 char *zWhere, /* WHERE clause for this subreport */
19767 sqlite3_int64 pgsz, /* Database page size */
19768 sqlite3_int64 nPage /* Number of pages in entire database */
19769 ){
@@ -19787,14 +19796,14 @@
19787 sqlite3_int64 total_unused; /* Total unused bytes */
19788 sqlite3_int64 total_meta; /* Total metadata */
19789 int rc;
19790
19791 if( zTitle==0 || zWhere==0 ){
19792 analysisError(p, 0);
19793 return SQLITE_NOMEM;
19794 }
19795 pStmt = analysisPrepare(p,
19796 "SELECT\n"
19797 " sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
19798 " sum(payload),\n" /* 1 */
19799 " sum(ovfl_payload),\n" /* 2 */
19800 " max(mx_payload),\n" /* 3 */
@@ -19811,11 +19820,11 @@
19811 " FROM temp.%s WHERE %s",
19812 p->zSU, zWhere);
19813 if( pStmt==0 ) return 1;
19814 rc = sqlite3_step(pStmt);
19815 if( rc==SQLITE_ROW ){
19816 analysisTitle(p, "%s", zTitle);
19817
19818 nentry = sqlite3_column_int64(pStmt, 0);
19819 payload = sqlite3_column_int64(pStmt, 1);
19820 ovfl_payload = sqlite3_column_int64(pStmt, 2);
19821 mx_payload = sqlite3_column_int64(pStmt, 3);
@@ -19830,73 +19839,73 @@
19830 cnt = sqlite3_column_int64(pStmt, 12);
19831 int_cell = sqlite3_column_int64(pStmt, 13);
19832 rc = SQLITE_DONE;
19833
19834 total_pages = leaf_pages + int_pages + ovfl_pages;
19835 analysisLine(p, "Percentage of total database", "%.3g%%\n",
19836 (total_pages*100.0)/(double)nPage);
19837 analysisLine(p, "Number of entries", "%lld\n", nentry);
19838 storage = total_pages*pgsz;
19839 analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
19840 analysisLine(p, "Bytes of payload", "%-11lld ", payload);
19841 analysisPercent(p, payload*100.0/(double)storage);
19842 if( ovfl_cnt>0 ){
19843 analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19844 analysisPercent(p, ovfl_payload*100.0/(double)payload);
19845 }
19846 total_unused = leaf_unused + int_unused + ovfl_unused;
19847 total_meta = storage - payload - total_unused;
19848 analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
19849 analysisPercent(p, total_meta*100.0/(double)storage);
19850 if( cnt==1 ){
19851 analysisLine(p, "B-tree depth", "%lld\n", depth);
19852 if( int_cell>1 ){
19853 analysisLine(p, "Average fanout", "%.1f\n",
19854 (double)(int_cell+int_pages)/(double)int_pages);
19855 }
19856 }
19857 if( nentry>0 ){
19858 analysisLine(p, "Average payload per entry", "%.1f\n",
19859 (double)payload/(double)nentry);
19860 analysisLine(p, "Average unused bytes per entry", "%.1f\n",
19861 (double)total_unused/(double)nentry);
19862 analysisLine(p, "Average metadata per entry", "%.1f\n",
19863 (double)total_meta/(double)nentry);
19864 }
19865 analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19866 if( nentry>0 ){
19867 analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19868 analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
19869 }
19870 if( int_pages>0 ){
19871 analysisLine(p, "Index pages used", "%lld\n", int_pages);
19872 }
19873 analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
19874 if( ovfl_cnt ){
19875 analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19876 }
19877 analysisLine(p, "Total pages used", "%lld\n", total_pages);
19878 if( int_pages>0 ){
19879 analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19880 }
19881 analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19882 if( ovfl_cnt ){
19883 analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19884 }
19885 analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19886 analysisPercent(p, total_unused*100.0/(double)storage);
19887 }
19888 return analysisStmtFinish(p, rc, pStmt);
19889 }
19890
19891 /*
19892 ** SQL Function: analyze(SCHEMA)
19893 **
19894 ** Analyze the database schema named in the argument. Return text
19895 ** containing the analysis.
19896 */
19897 static void analyzeFunc(
19898 sqlite3_context *context,
19899 int argc,
19900 sqlite3_value **argv
19901 ){
19902 int rc;
@@ -19907,47 +19916,47 @@
19907 sqlite3_int64 nPage;
19908 sqlite3_int64 nPageInUse;
19909 sqlite3_int64 nFreeList;
19910 sqlite3_int64 nIndex;
19911 sqlite3_int64 nWORowid;
19912 Analysis s;
19913 sqlite3_uint64 r[2];
19914
19915 (void)argc;
19916 memset(&s, 0, sizeof(s));
19917 s.db = sqlite3_context_db_handle(context);
19918 s.context = context;
19919 s.pOut = sqlite3_str_new(0);
19920 if( sqlite3_str_errcode(s.pOut) ){
19921 analysisError(&s, 0);
19922 return;
19923 }
19924 s.zSchema = (const char*)sqlite3_value_text(argv[0]);
19925 if( s.zSchema==0 ){
19926 s.zSchema = "main";
19927 }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19928 analysisReset(&s);
19929 sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
19930 return;
19931 }
19932 ii = 0;
19933 rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
19934 " WHERE name=%Q COLLATE nocase",s.zSchema);
19935 if( rc || ii==0 ){
19936 analysisReset(&s);
19937 sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
19938 return;
19939 }
19940 sqlite3_randomness(sizeof(r), &r);
19941 s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
19942 if( s.zSU==0 ){ analysisError(&s, 0); return; }
19943
19944 /* The s.zSU table contains the data used for the analysis.
19945 ** The table name contains 128-bits of randomness to avoid
19946 ** collisions with preexisting tables in temp.
19947 */
19948 rc = analysisSql(&s,
19949 "CREATE TABLE temp.%s(\n"
19950 " name text, -- A table or index\n"
19951 " tblname text, -- Table that owns name\n"
19952 " is_index boolean, -- TRUE if it is an index\n"
19953 " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
@@ -19970,11 +19979,11 @@
19970 );
19971 if( rc ) return;
19972
19973 /* Populate the s.zSU table
19974 */
19975 rc = analysisSql(&s,
19976 "WITH\n"
19977 " allidx(idxname) AS (\n"
19978 " SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
19979 " ),\n"
19980 " allobj(allname,tblname,isidx,isworowid) AS (\n"
@@ -20022,141 +20031,143 @@
20022 s.zSchema /* JOIN dbstat(%Q) */
20023 );
20024 if( rc ) return;
20025
20026 nPage = 0;
20027 rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20028 if( rc ) return;
20029 if( nPage<=0 ){
20030 /* Very brief reply for an empty database */
20031 analysisReset(&s);
20032 sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
20033 return;
20034 }
20035
20036 /* Begin generating the report */
20037 analysisTitle(&s, "Database storage utilization report");
20038 pgsz = 0;
20039 rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20040 if( rc ) return;
20041 analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
20042 analysisLine(&s, "Pages in the database", "%lld\n", nPage);
20043
20044 nPageInUse = 0;
20045 rc = analysisSqlInt(&s, &nPageInUse,
20046 "SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
20047 if( rc ) return;
20048 analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20049 analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
20050
20051 nFreeList = 0;
20052 rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20053 if( rc ) return;
20054 analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20055 analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
20056
20057 ii = 0;
20058 rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20059 if( rc ) return;
20060 if( ii==0 || nPage<=1 ){
20061 ii = 0;
20062 }else{
20063 double rPtrsPerPage = pgsz/5;
20064 double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
20065 ii = (sqlite3_int64)ceil(rAvPage);
20066 }
20067 analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20068 analysisPercent(&s, (ii*100.0)/(double)nPage);
20069
20070 ii = 0;
20071 rc = analysisSqlInt(&s, &ii,
20072 "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
20073 s.zSchema);
20074 if( rc ) return;
20075 analysisLine(&s, "Number of tables", "%lld\n", ii);
20076 nWORowid = 0;
20077 rc = analysisSqlInt(&s, &nWORowid,
20078 "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
20079 s.zSchema);
20080 if( rc ) return;
20081 if( nWORowid>0 ){
20082 analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20083 analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
20084 }
20085 nIndex = 0;
20086 rc = analysisSqlInt(&s, &nIndex,
20087 "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
20088 s.zSchema);
20089 if( rc ) return;
20090 analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
20091 ii = 0;
20092 rc = analysisSqlInt(&s, &ii,
20093 "SELECT count(*) FROM \"%w\".sqlite_schema"
20094 " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
20095 s.zSchema);
20096 if( rc ) return;
20097 analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20098 analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
20099 analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20100 ii = 0;
20101 rc = analysisSqlInt(&s, &ii,
20102 "SELECT sum(payload) FROM temp.%s"
20103 " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
20104 s.zSU);
20105 if( rc ) return;
20106 analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
20107 analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
20108
20109 analysisTitle(&s, "Page counts for all tables with their indexes");
20110 pStmt = analysisPrepare(&s,
20111 "SELECT upper(tblname),\n"
20112 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20113 " FROM temp.%s\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20114 " GROUP BY 1\n"
20115 " ORDER BY 2 DESC, 1;",
20116 s.zSU);
20117 if( pStmt==0 ) return;
20118 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20119 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20120 analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20121 analysisPercent(&s, (nn*100.0)/(double)nPage);
20122 }
20123 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20124
20125 analysisTitle(&s, "Page counts for all tables and indexes separately");
20126 pStmt = analysisPrepare(&s,
20127 "SELECT upper(name),\n"
20128 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20129 " FROM temp.%s\n"
20130 " GROUP BY 1\n"
20131 " ORDER BY 2 DESC, 1;",
20132 s.zSU);
20133 if( pStmt==0 ) return;
20134 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20135 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20136 analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20137 analysisPercent(&s, (nn*100.0)/(double)nPage);
20138 }
20139 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20140
20141 rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
20142 if( rc ) return;
20143 rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20144 if( rc ) return;
20145 if( nWORowid>0 ){
20146 rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20147 pgsz, nPage);
20148 if( rc ) return;
20149 rc = analysisSubreport(&s, "All rowid tables",
20150 "NOT is_without_rowid AND NOT is_index",
20151 pgsz, nPage);
20152 if( rc ) return;
20153 }
20154 rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20155 if( rc ) return;
20156
20157 pStmt = analysisPrepare(&s,
20158 "SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
20159 " GROUP BY 1 ORDER BY 1",
20160 s.zSU);
20161 if( pStmt==0 ) return;
20162 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
@@ -20164,37 +20175,37 @@
20164 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
20165 int nSubIndex = sqlite3_column_int(pStmt, 2);
20166 if( nSubIndex==0 ){
20167 char *zTitle = sqlite3_mprintf("Table %s", zUpper);
20168 char *zWhere = sqlite3_mprintf("name=%Q", zName);
20169 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20170 sqlite3_free(zTitle);
20171 sqlite3_free(zWhere);
20172 if( rc ) break;
20173 }else{
20174 sqlite3_stmt *pS2;
20175 char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
20176 char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20177 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20178 sqlite3_free(zTitle);
20179 sqlite3_free(zWhere);
20180 if( rc ) break;
20181 zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
20182 zWhere = sqlite3_mprintf("name=%Q", zName);
20183 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20184 sqlite3_free(zTitle);
20185 sqlite3_free(zWhere);
20186 if( rc ) break;
20187 if( nSubIndex>1 ){
20188 zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
20189 zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20190 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20191 sqlite3_free(zTitle);
20192 sqlite3_free(zWhere);
20193 if( rc ) break;
20194 }
20195 pS2 = analysisPrepare(&s,
20196 "SELECT name, upper(name) FROM temp.%s"
20197 " WHERE is_index AND tblname=%Q",
20198 s.zSU, zName);
20199 if( pS2==0 ){
20200 rc = SQLITE_NOMEM;
@@ -20203,25 +20214,25 @@
20203 while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
20204 const char *zU = (const char*)sqlite3_column_text(pS2, 1);
20205 const char *zN = (const char*)sqlite3_column_text(pS2, 0);
20206 zTitle = sqlite3_mprintf("Index %s", zU);
20207 zWhere = sqlite3_mprintf("name=%Q", zN);
20208 rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
20209 sqlite3_free(zTitle);
20210 sqlite3_free(zWhere);
20211 if( rc ) break;
20212 }
20213 rc = analysisStmtFinish(&s, rc, pS2);
20214 if( rc ) break;
20215 }
20216 }
20217 if( analysisStmtFinish(&s, rc, pStmt) ) return;
20218
20219 /* Append SQL statements that will recreate the raw data used for
20220 ** the analysis.
20221 */
20222 analysisTitle(&s, "Raw data used to generate this report");
20223 sqlite3_str_appendf(s.pOut,
20224 "The following SQL will create a table named \"space_used\" which\n"
20225 "contains most of the information used to generate the report above.\n"
20226 "*/\n"
20227 );
@@ -20247,11 +20258,11 @@
20247 " ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
20248 " int_entries int -- B-tree entries on internal pages\n"/* 17 */
20249 ");\n"
20250 "INSERT INTO space_used VALUES\n"
20251 );
20252 pStmt = analysisPrepare(&s,
20253 "SELECT quote(name), quote(tblname),\n" /* 0..1 */
20254 " is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
20255 " depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
20256 " int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
20257 " leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
@@ -20282,11 +20293,11 @@
20282 sqlite3_column_int64(pStmt, 15),
20283 sqlite3_column_int64(pStmt, 16),
20284 sqlite3_column_int64(pStmt, 17));
20285 }
20286 if( rc!=SQLITE_DONE ){
20287 analysisError(&s, "SQL run-time error: %s\nSQL: %s",
20288 sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
20289 sqlite3_finalize(pStmt);
20290 return;
20291 }
20292 sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
@@ -20295,32 +20306,32 @@
20295 if( sqlite3_str_length(s.pOut) ){
20296 sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
20297 sqlite3_free);
20298 s.pOut = 0;
20299 }
20300 analysisReset(&s);
20301 }
20302
20303
20304 #ifdef _WIN32
20305
20306 #endif
20307 int sqlite3_analyze_init(
20308 sqlite3 *db,
20309 char **pzErrMsg,
20310 const sqlite3_api_routines *pApi
20311 ){
20312 int rc = SQLITE_OK;
20313 SQLITE_EXTENSION_INIT2(pApi);
20314 (void)pzErrMsg; /* Unused parameter */
20315 rc = sqlite3_create_function(db, "analyze", 1,
20316 SQLITE_UTF8|SQLITE_INNOCUOUS,
20317 0, analyzeFunc, 0, 0);
20318 return rc;
20319 }
20320
20321 /************************* End ext/misc/analyze.c ********************/
20322
20323 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
20324 #define SQLITE_SHELL_HAVE_RECOVER 1
20325 #else
20326 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -26321,10 +26332,47 @@
26321 if( *az ){
26322 memcpy(*az, zNew, n+1 );
26323 }
26324 }
26325 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26326
26327 /*
26328 ** Change the mode to eMode
26329 */
26330 static void modeChange(ShellState *p, unsigned char eMode){
@@ -26358,10 +26406,11 @@
26358 modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
26359 }else if( eMode==MODE_BATCH ){
26360 u8 mFlags = p->mode.mFlags;
26361 modeFree(&p->mode);
26362 modeChange(p, MODE_List);
 
26363 p->mode.mFlags = mFlags;
26364 }else if( eMode==MODE_TTY ){
26365 u8 mFlags = p->mode.mFlags;
26366 modeFree(&p->mode);
26367 modeChange(p, MODE_QBox);
@@ -28446,12 +28495,12 @@
28446 ".databases List names and files of attached databases",
28447 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
28448 #if SQLITE_SHELL_HAVE_RECOVER
28449 ".dbinfo ?DB? Show status information about the database",
28450 #endif
28451 ".dbstat ?SCHEMA? Report database space and size stats",
28452 ".dbtotxt Hex dump of the database file",
 
28453 ".dump ?OBJECTS? Render database content as SQL",
28454 " Options:",
28455 " --data-only Output only INSERT statements",
28456 " --newlines Allow unescaped newline characters in output",
28457 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
@@ -29461,11 +29510,11 @@
29461 sqlite3_base64_init(p->db, 0, 0);
29462 sqlite3_base85_init(p->db, 0, 0);
29463 sqlite3_regexp_init(p->db, 0, 0);
29464 sqlite3_ieee_init(p->db, 0, 0);
29465 sqlite3_series_init(p->db, 0, 0);
29466 sqlite3_analyze_init(p->db, 0, 0);
29467 #ifndef SQLITE_SHELL_FIDDLE
29468 sqlite3_fileio_init(p->db, 0, 0);
29469 sqlite3_completion_init(p->db, 0, 0);
29470 #endif
29471 #ifdef SQLITE_HAVE_ZLIB
@@ -33123,30 +33172,14 @@
33123 }else if( optionMatch(z,"limits") ){
33124 if( (++i)>=nArg ){
33125 dotCmdError(p, i-1, "missing argument", 0);
33126 return 1;
33127 }
33128 k = pickStr(azArg[i],0,"on","off","");
33129 if( k==0 ){
33130 p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
33131 p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
33132 p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
33133 }else if( k==1 ){
33134 p->mode.spec.nLineLimit = 0;
33135 p->mode.spec.nCharLimit = 0;
33136 p->mode.spec.nTitleLimit = 0;
33137 }else{
33138 int L, C, T = 0;
33139 int nNum = sscanf(azArg[i], "%d,%d,%d", &L, &C, &T);
33140 if( nNum<2 || L<0 || C<0 || T<0){
33141 dotCmdError(p, i, "bad argument", "Should be \"L,C,T\" where L, C"
33142 " and T are unsigned integers");
33143 return 1;
33144 }
33145 p->mode.spec.nLineLimit = L;
33146 p->mode.spec.nCharLimit = C;
33147 if( nNum==3 ) p->mode.spec.nTitleLimit = T;
33148 }
33149 chng = 1;
33150 }else if( optionMatch(z,"list") ){
33151 int ii;
33152 cli_puts("available modes:", p->out);
@@ -34360,11 +34393,16 @@
34360 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
34361 rc = shell_dbinfo_command(p, nArg, azArg);
34362 }else
34363 #endif /* SQLITE_SHELL_HAVE_RECOVER */
34364
34365 if( c=='d' && n==6 && cli_strncmp(azArg[0], "dbstat", n)==0 ){
 
 
 
 
 
34366 const char *zSchema = 0;
34367 int ii;
34368 char *zSql;
34369 open_db(p, 0);
34370 for(ii=1; ii<nArg; ii++){
@@ -34379,27 +34417,19 @@
34379 rc = 1;
34380 goto meta_command_exit;
34381 }
34382 zSchema = z;
34383 }
34384 zSql = sqlite3_mprintf("SELECT analyze(%Q)", zSchema);
34385 shell_check_oom(zSql);
34386 modePush(p);
34387 modeChange(p, MODE_BATCH);
34388 p->mode.spec.nLineLimit = 0;
34389 p->mode.spec.nCharLimit = 0;
34390 p->mode.spec.nTitleLimit = 0;
34391 shell_exec(p, zSql, 0);
34392 modePop(p);
34393 sqlite3_free(zSql);
34394 }else
34395
34396 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34397 open_db(p, 0);
34398 rc = shell_dbtotxt_command(p, nArg, azArg);
34399 }else
34400
34401 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
34402 char *zLike = 0;
34403 char *zSql;
34404 int i;
34405 int savedShellFlags = p->shellFlgs;
@@ -37755,17 +37785,17 @@
37755 " -- treat no subsequent arguments as options\n"
37756 #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
37757 " -A ARGS... run \".archive ARGS\" and exit\n"
37758 #endif
37759 " -append append the database to the end of the file\n"
37760 " -ascii set output mode to 'ascii'\n"
37761 " -bail stop after hitting an error\n"
37762 " -batch force batch I/O\n"
37763 " -box set output mode to 'box'\n"
37764 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
37765 " -column set output mode to 'column'\n"
37766 " -csv set output mode to 'csv'\n"
37767 #if !defined(SQLITE_OMIT_DESERIALIZE)
37768 " -deserialize open the database using sqlite3_deserialize()\n"
37769 #endif
37770 " -echo print inputs before execution\n"
37771 " -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
@@ -37773,18 +37803,18 @@
37773 " -[no]header turn headers on or off\n"
37774 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
37775 " -heap SIZE Size of heap for memsys3 or memsys5\n"
37776 #endif
37777 " -help show this message\n"
37778 " -html set output mode to HTML\n"
37779 " -ifexists only open if database already exists\n"
37780 " -interactive force interactive I/O\n"
37781 " -json set output mode to 'json'\n"
37782 " -line set output mode to 'line'\n"
37783 " -list set output mode to 'list'\n"
37784 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
37785 " -markdown set output mode to 'markdown'\n"
37786 #if !defined(SQLITE_OMIT_DESERIALIZE)
37787 " -maxsize N maximum size for a --deserialize database\n"
37788 #endif
37789 " -memtrace trace all memory allocations and deallocations\n"
37790 " -mmap N default mmap size set to N\n"
@@ -37797,21 +37827,21 @@
37797 " -nonce STRING set the safe-mode escape nonce\n"
37798 " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
37799 " -nullvalue TEXT set text string for NULL values. Default ''\n"
37800 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
37801 " -pcachetrace trace all page cache operations\n"
37802 " -quote set output mode to 'quote'\n"
37803 " -readonly open the database read-only\n"
37804 " -safe enable safe-mode\n"
37805 " -screenwidth N use N as the default screenwidth \n"
37806 " -separator SEP set output column separator. Default: '|'\n"
37807 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
37808 " -sorterref SIZE sorter references threshold size\n"
37809 #endif
37810 " -stats print memory stats before each finalize\n"
37811 " -table set output mode to 'table'\n"
37812 " -tabs set output mode to 'tabs'\n"
37813 " -unsafe-testing allow unsafe commands and modes for testing\n"
37814 " -version show SQLite version\n"
37815 " -vfs NAME use NAME as the default VFS\n"
37816 " -vfstrace enable tracing of all VFS calls\n"
37817 #ifdef SQLITE_HAVE_ZLIB
@@ -38409,10 +38439,11 @@
38409 modeChange(&data, MODE_Psql);
38410 }else if( cli_strcmp(z,"-box")==0 ){
38411 modeChange(&data, MODE_Box);
38412 }else if( cli_strcmp(z,"-csv")==0 ){
38413 modeChange(&data, MODE_Csv);
 
38414 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
38415 /* See similar code at tag-20250224-1 */
38416 const char *zEsc = argv[++i];
38417 int k;
38418 for(k=0; k<ArraySize(qrfEscNames); k++){
38419
--- extsrc/shell.c
+++ extsrc/shell.c
@@ -5,16 +5,16 @@
5 **
6 ** ext/expert/sqlite3expert.c
7 ** ext/expert/sqlite3expert.h
8 ** ext/intck/sqlite3intck.c
9 ** ext/intck/sqlite3intck.h
 
10 ** ext/misc/appendvfs.c
11 ** ext/misc/base64.c
12 ** ext/misc/base85.c
13 ** ext/misc/completion.c
14 ** ext/misc/decimal.c
15 ** ext/misc/diskused.c
16 ** ext/misc/fileio.c
17 ** ext/misc/ieee754.c
18 ** ext/misc/memtrace.c
19 ** ext/misc/pcachetrace.c
20 ** ext/misc/regexp.c
@@ -19478,11 +19478,11 @@
19478 sqlite3_vfs_unregister(pVfs);
19479 sqlite3_free(pVfs);
19480 }
19481
19482 /************************* End ext/misc/vfstrace.c ********************/
19483 /************************* Begin ext/misc/diskused.c ******************/
19484 /*
19485 ** 2026-04-13
19486 **
19487 ** The author disclaims copyright to this source code. In place of
19488 ** a legal notice, here is a blessing:
@@ -19491,12 +19491,21 @@
19491 ** May you find forgiveness for yourself and forgive others.
19492 ** May you share freely, never taking more than you give.
19493 **
19494 ******************************************************************************
19495 **
19496 ** This extension implements an SQL function:
19497 **
19498 ** diskused(X)
19499 **
19500 ** Where X is the schema name (typically 'main'). The output is text
19501 ** that describes how much filesystem space the various tables and indexes
19502 ** of the database consume.
19503 **
19504 ** This function is a replacement for the (now deprecated)
19505 ** "sqlite3_analyzer" utility program. This function is built
19506 ** into the CLI and is used to implement the ".diskused" command there.
19507 */
19508 /* #include "sqlite3ext.h" */
19509 SQLITE_EXTENSION_INIT1
19510 #include <assert.h>
19511 #include <string.h>
@@ -19504,28 +19513,28 @@
19513 #include <math.h>
19514
19515 /*
19516 ** State information for the analysis
19517 */
19518 typedef struct DiskUsed DiskUsed;
19519 struct DiskUsed {
19520 sqlite3 *db; /* Database connection */
19521 sqlite3_context *context; /* SQL function context */
19522 sqlite3_str *pOut; /* Write output here */
19523 char *zSU; /* Name of the temp.space_used table */
19524 const char *zSchema; /* Schema to be analyzed */
19525 };
19526
19527 /*
19528 ** Free all resources that the DiskUsed object references and
19529 ** reset the DiskUsed object.
19530 **
19531 ** Call this routine multiple times on the same DiskUsed object
19532 ** is a harmless no-op, as long as the memory for the object itself
19533 ** has not been freed.
19534 */
19535 static void diskusedReset(DiskUsed *p){
19536 if( p->zSU ){
19537 char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
19538 if( zSql ){
19539 sqlite3_exec(p->db, zSql, 0, 0, 0);
19540 sqlite3_free(zSql);
@@ -19538,11 +19547,11 @@
19547
19548 /*
19549 ** Report an error using formatted text. If zFormat==NULL then report
19550 ** an OOM error.
19551 */
19552 static void diskusedError(DiskUsed *p, const char *zFormat, ...){
19553 char *zErr;
19554 if( zFormat ){
19555 va_list ap;
19556 va_start(ap, zFormat);
19557 zErr = sqlite3_vmprintf(zFormat, ap);
@@ -19554,38 +19563,38 @@
19563 sqlite3_result_error_nomem(p->context);
19564 }else{
19565 sqlite3_result_error(p->context, zErr, -1);
19566 sqlite3_free(zErr);
19567 }
19568 diskusedReset(p);
19569 }
19570
19571 /*
19572 ** Prepare and return an SQL statement.
19573 */
19574 static sqlite3_stmt *diskusedVPrep(DiskUsed *p, const char *zFmt, va_list ap){
19575 char *zSql;
19576 int rc;
19577 sqlite3_stmt *pStmt = 0;
19578 zSql = sqlite3_vmprintf(zFmt, ap);
19579 if( zSql==0 ){ diskusedError(p,0); return 0; }
19580 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19581 if( rc ){
19582 diskusedError(p, "SQL parse error: %s\nOriginal SQL: %s",
19583 sqlite3_errmsg(p->db), zSql);
19584 sqlite3_finalize(pStmt);
19585 diskusedReset(p);
19586 pStmt = 0;
19587 }
19588 sqlite3_free(zSql);
19589 return pStmt;
19590 }
19591 static sqlite3_stmt *diskusedPrepare(DiskUsed *p, const char *zFormat, ...){
19592 va_list ap;
19593 sqlite3_stmt *pStmt = 0;
19594 va_start(ap, zFormat);
19595 pStmt = diskusedVPrep(p,zFormat,ap);
19596 va_end(ap);
19597 return pStmt;
19598 }
19599
19600 /*
@@ -19594,60 +19603,60 @@
19603 **
19604 ** If rc is SQLITE_DONE or SQLITE_OK, then return false.
19605 **
19606 ** The prepared statement is closed in either case.
19607 */
19608 static int diskusedStmtFinish(DiskUsed *p, int rc, sqlite3_stmt *pStmt){
19609 if( rc==SQLITE_DONE ){
19610 rc = SQLITE_OK;
19611 }
19612 if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
19613 diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19614 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19615 diskusedReset(p);
19616 }
19617 sqlite3_finalize(pStmt);
19618 return rc;
19619 }
19620
19621 /*
19622 ** Run SQL. Return the number of errors.
19623 */
19624 static int diskusedSql(DiskUsed *p, const char *zFormat, ...){
19625 va_list ap;
19626 int rc;
19627 sqlite3_stmt *pStmt = 0;
19628 va_start(ap, zFormat);
19629 pStmt = diskusedVPrep(p,zFormat,ap);
19630 va_end(ap);
19631 if( pStmt==0 ) return 1;
19632 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
19633 if( rc==SQLITE_DONE ){
19634 rc = SQLITE_OK;
19635 }else{
19636 diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19637 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19638 diskusedReset(p);
19639 }
19640 sqlite3_finalize(pStmt);
19641 return rc;
19642 }
19643
19644 /*
19645 ** Run an SQL query that returns an integer. Write that integer
19646 ** into *piRes. Return the number of errors.
19647 */
19648 static int diskusedSqlInt(
19649 DiskUsed *p,
19650 sqlite3_int64 *piRes,
19651 const char *zFormat, ...
19652 ){
19653 va_list ap;
19654 int rc;
19655 sqlite3_stmt *pStmt = 0;
19656 va_start(ap, zFormat);
19657 pStmt = diskusedVPrep(p,zFormat,ap);
19658 va_end(ap);
19659 if( pStmt==0 ) return 1;
19660 rc = sqlite3_step(pStmt);
19661 if( rc==SQLITE_ROW ){
19662 *piRes = sqlite3_column_int64(pStmt, 0);
@@ -19655,14 +19664,14 @@
19664 }else if( rc==SQLITE_DONE ){
19665 rc = SQLITE_OK;
19666 }else{
19667 if( p->db ){
19668 /* p->db is NULL if there was some prior error */
19669 diskusedError(p, "SQL run-time error: %s\nOriginal SQL: %s",
19670 sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
19671 }
19672 diskusedReset(p);
19673 }
19674 sqlite3_finalize(pStmt);
19675 return rc;
19676 }
19677
@@ -19671,20 +19680,20 @@
19680 ** by the format string. If the output is initially empty, begin
19681 ** the title line with "/" so that it forms the beginning of a C-style
19682 ** comment. Otherwise begin with a new-line. Always finish with a
19683 ** newline.
19684 */
19685 static void diskusedTitle(DiskUsed *p, const char *zFormat, ...){
19686 char *zFirst;
19687 char *zTitle;
19688 size_t nTitle;
19689 va_list ap;
19690 va_start(ap, zFormat);
19691 zTitle = sqlite3_vmprintf(zFormat, ap);
19692 va_end(ap);
19693 if( zTitle==0 ){
19694 diskusedError(p, 0);
19695 return;
19696 }
19697 zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
19698 nTitle = strlen(zTitle);
19699 if( nTitle>=75 ){
@@ -19699,12 +19708,12 @@
19708 /*
19709 ** Add an output line that begins with the zDesc text extended out to
19710 ** 50 columns with "." characters, and followed by whatever text is
19711 ** described by zFormat.
19712 */
19713 static void diskusedLine(
19714 DiskUsed *p, /* DiskUsed context */
19715 const char *zDesc, /* Description */
19716 const char *zFormat, /* Argument to the description */
19717 ...
19718 ){
19719 char *zTxt;
@@ -19712,14 +19721,14 @@
19721 va_list ap;
19722 va_start(ap, zFormat);
19723 zTxt = sqlite3_vmprintf(zFormat, ap);
19724 va_end(ap);
19725 if( zTxt==0 ){
19726 diskusedError(p, 0);
19727 return;
19728 }
19729 nDesc = zDesc ? strlen(zDesc) : 0;
19730 if( nDesc>=50 ){
19731 sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
19732 }else{
19733 int nExtra = 50 - (int)nDesc;
19734 sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
@@ -19729,11 +19738,11 @@
19738 /*
19739 ** Write a percentage into the output. The number written should show
19740 ** two or three significant digits, with the decimal point being the fourth
19741 ** character.
19742 */
19743 static void diskusedPercent(DiskUsed *p, double r){
19744 char zNum[100];
19745 char *zDP;
19746 int nLeadingDigit;
19747 int sz;
19748 sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
@@ -19758,12 +19767,12 @@
19767 **
19768 ** The title if the subreport is given by zTitle. zWhere is
19769 ** a boolean expression that can go in the WHERE clause to select
19770 ** the relevant rows of the s.zSU table.
19771 */
19772 static int diskusedSubreport(
19773 DiskUsed *p, /* DiskUsed context */
19774 char *zTitle, /* Title for this subreport */
19775 char *zWhere, /* WHERE clause for this subreport */
19776 sqlite3_int64 pgsz, /* Database page size */
19777 sqlite3_int64 nPage /* Number of pages in entire database */
19778 ){
@@ -19787,14 +19796,14 @@
19796 sqlite3_int64 total_unused; /* Total unused bytes */
19797 sqlite3_int64 total_meta; /* Total metadata */
19798 int rc;
19799
19800 if( zTitle==0 || zWhere==0 ){
19801 diskusedError(p, 0);
19802 return SQLITE_NOMEM;
19803 }
19804 pStmt = diskusedPrepare(p,
19805 "SELECT\n"
19806 " sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
19807 " sum(payload),\n" /* 1 */
19808 " sum(ovfl_payload),\n" /* 2 */
19809 " max(mx_payload),\n" /* 3 */
@@ -19811,11 +19820,11 @@
19820 " FROM temp.%s WHERE %s",
19821 p->zSU, zWhere);
19822 if( pStmt==0 ) return 1;
19823 rc = sqlite3_step(pStmt);
19824 if( rc==SQLITE_ROW ){
19825 diskusedTitle(p, "%s", zTitle);
19826
19827 nentry = sqlite3_column_int64(pStmt, 0);
19828 payload = sqlite3_column_int64(pStmt, 1);
19829 ovfl_payload = sqlite3_column_int64(pStmt, 2);
19830 mx_payload = sqlite3_column_int64(pStmt, 3);
@@ -19830,73 +19839,73 @@
19839 cnt = sqlite3_column_int64(pStmt, 12);
19840 int_cell = sqlite3_column_int64(pStmt, 13);
19841 rc = SQLITE_DONE;
19842
19843 total_pages = leaf_pages + int_pages + ovfl_pages;
19844 diskusedLine(p, "Percentage of total database", "%.3g%%\n",
19845 (total_pages*100.0)/(double)nPage);
19846 diskusedLine(p, "Number of entries", "%lld\n", nentry);
19847 storage = total_pages*pgsz;
19848 diskusedLine(p, "Bytes of storage consumed", "%lld\n", storage);
19849 diskusedLine(p, "Bytes of payload", "%-11lld ", payload);
19850 diskusedPercent(p, payload*100.0/(double)storage);
19851 if( ovfl_cnt>0 ){
19852 diskusedLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
19853 diskusedPercent(p, ovfl_payload*100.0/(double)payload);
19854 }
19855 total_unused = leaf_unused + int_unused + ovfl_unused;
19856 total_meta = storage - payload - total_unused;
19857 diskusedLine(p, "Bytes of metadata","%-11lld ", total_meta);
19858 diskusedPercent(p, total_meta*100.0/(double)storage);
19859 if( cnt==1 ){
19860 diskusedLine(p, "B-tree depth", "%lld\n", depth);
19861 if( int_cell>1 ){
19862 diskusedLine(p, "Average fanout", "%.1f\n",
19863 (double)(int_cell+int_pages)/(double)int_pages);
19864 }
19865 }
19866 if( nentry>0 ){
19867 diskusedLine(p, "Average payload per entry", "%.1f\n",
19868 (double)payload/(double)nentry);
19869 diskusedLine(p, "Average unused bytes per entry", "%.1f\n",
19870 (double)total_unused/(double)nentry);
19871 diskusedLine(p, "Average metadata per entry", "%.1f\n",
19872 (double)total_meta/(double)nentry);
19873 }
19874 diskusedLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
19875 if( nentry>0 ){
19876 diskusedLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
19877 diskusedPercent(p, ovfl_cnt*100.0/(double)nentry);
19878 }
19879 if( int_pages>0 ){
19880 diskusedLine(p, "Index pages used", "%lld\n", int_pages);
19881 }
19882 diskusedLine(p, "Primary pages used", "%lld\n", leaf_pages);
19883 if( ovfl_cnt ){
19884 diskusedLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
19885 }
19886 diskusedLine(p, "Total pages used", "%lld\n", total_pages);
19887 if( int_pages>0 ){
19888 diskusedLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
19889 }
19890 diskusedLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
19891 if( ovfl_cnt ){
19892 diskusedLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
19893 }
19894 diskusedLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
19895 diskusedPercent(p, total_unused*100.0/(double)storage);
19896 }
19897 return diskusedStmtFinish(p, rc, pStmt);
19898 }
19899
19900 /*
19901 ** SQL Function: diskused(SCHEMA)
19902 **
19903 ** Analyze the database schema named in the argument. Return text
19904 ** containing the space utilization stats.
19905 */
19906 static void diskusedFunc(
19907 sqlite3_context *context,
19908 int argc,
19909 sqlite3_value **argv
19910 ){
19911 int rc;
@@ -19907,47 +19916,47 @@
19916 sqlite3_int64 nPage;
19917 sqlite3_int64 nPageInUse;
19918 sqlite3_int64 nFreeList;
19919 sqlite3_int64 nIndex;
19920 sqlite3_int64 nWORowid;
19921 DiskUsed s;
19922 sqlite3_uint64 r[2];
19923
19924 (void)argc;
19925 memset(&s, 0, sizeof(s));
19926 s.db = sqlite3_context_db_handle(context);
19927 s.context = context;
19928 s.pOut = sqlite3_str_new(0);
19929 if( sqlite3_str_errcode(s.pOut) ){
19930 diskusedError(&s, 0);
19931 return;
19932 }
19933 s.zSchema = (const char*)sqlite3_value_text(argv[0]);
19934 if( s.zSchema==0 ){
19935 s.zSchema = "main";
19936 }else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
19937 diskusedReset(&s);
19938 sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
19939 return;
19940 }
19941 ii = 0;
19942 rc = diskusedSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
19943 " WHERE name=%Q COLLATE nocase",s.zSchema);
19944 if( rc || ii==0 ){
19945 diskusedReset(&s);
19946 sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
19947 return;
19948 }
19949 sqlite3_randomness(sizeof(r), &r);
19950 s.zSU = sqlite3_mprintf("diskused%016llx%016llx", r[0], r[1]);
19951 if( s.zSU==0 ){ diskusedError(&s, 0); return; }
19952
19953 /* The s.zSU table contains the data used for the analysis.
19954 ** The table name contains 128-bits of randomness to avoid
19955 ** collisions with preexisting tables in temp.
19956 */
19957 rc = diskusedSql(&s,
19958 "CREATE TABLE temp.%s(\n"
19959 " name text, -- A table or index\n"
19960 " tblname text, -- Table that owns name\n"
19961 " is_index boolean, -- TRUE if it is an index\n"
19962 " is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
@@ -19970,11 +19979,11 @@
19979 );
19980 if( rc ) return;
19981
19982 /* Populate the s.zSU table
19983 */
19984 rc = diskusedSql(&s,
19985 "WITH\n"
19986 " allidx(idxname) AS (\n"
19987 " SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
19988 " ),\n"
19989 " allobj(allname,tblname,isidx,isworowid) AS (\n"
@@ -20022,141 +20031,143 @@
20031 s.zSchema /* JOIN dbstat(%Q) */
20032 );
20033 if( rc ) return;
20034
20035 nPage = 0;
20036 rc = diskusedSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
20037 if( rc ) return;
20038 if( nPage<=0 ){
20039 /* Very brief reply for an empty database */
20040 diskusedReset(&s);
20041 sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
20042 return;
20043 }
20044
20045 /* Begin generating the report */
20046 diskusedTitle(&s, "Database storage utilization report");
20047 pgsz = 0;
20048 rc = diskusedSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
20049 if( rc ) return;
20050 diskusedLine(&s, "Page size in bytes","%lld\n",pgsz);
20051 diskusedLine(&s, "Pages in the database", "%lld\n", nPage);
20052
20053 nPageInUse = 0;
20054 rc = diskusedSqlInt(&s, &nPageInUse,
20055 "SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
20056 if( rc ) return;
20057 diskusedLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
20058 diskusedPercent(&s, (nPageInUse*100.0)/(double)nPage);
20059
20060 nFreeList = 0;
20061 rc = diskusedSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
20062 if( rc ) return;
20063 diskusedLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
20064 diskusedPercent(&s, (nFreeList*100.0)/(double)nPage);
20065
20066 ii = 0;
20067 rc = diskusedSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
20068 if( rc ) return;
20069 if( ii==0 || nPage<=1 ){
20070 ii = 0;
20071 }else{
20072 double rPtrsPerPage = pgsz/5;
20073 double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
20074 ii = (sqlite3_int64)ceil(rAvPage);
20075 }
20076 diskusedLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
20077 diskusedPercent(&s, (ii*100.0)/(double)nPage);
20078
20079 ii = 0;
20080 rc = diskusedSqlInt(&s, &ii,
20081 "SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
20082 s.zSchema);
20083 if( rc ) return;
20084 diskusedLine(&s, "Number of tables", "%lld\n", ii);
20085 nWORowid = 0;
20086 rc = diskusedSqlInt(&s, &nWORowid,
20087 "SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
20088 s.zSchema);
20089 if( rc ) return;
20090 if( nWORowid>0 ){
20091 diskusedLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
20092 diskusedLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
20093 }
20094 nIndex = 0;
20095 rc = diskusedSqlInt(&s, &nIndex,
20096 "SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
20097 s.zSchema);
20098 if( rc ) return;
20099 diskusedLine(&s, "Number of indexes", "%lld\n", nIndex);
20100 ii = 0;
20101 rc = diskusedSqlInt(&s, &ii,
20102 "SELECT count(*) FROM \"%w\".sqlite_schema"
20103 " WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
20104 s.zSchema);
20105 if( rc ) return;
20106 diskusedLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
20107 diskusedLine(&s, "Number of implied indexes", "%lld\n", ii);
20108 diskusedLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
20109 ii = 0;
20110 rc = diskusedSqlInt(&s, &ii,
20111 "SELECT sum(payload) FROM temp.%s"
20112 " WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
20113 s.zSU);
20114 if( rc ) return;
20115 diskusedLine(&s, "Bytes of payload", "%-11lld ", ii);
20116 diskusedPercent(&s, ii*100.0/(double)(pgsz*nPage));
20117
20118 diskusedTitle(&s, "Page counts for all tables with their indexes");
20119 pStmt = diskusedPrepare(&s,
20120 "SELECT upper(tblname),\n"
20121 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20122 " FROM temp.%s\n"
20123 " WHERE tblname IS NOT NULL\n"
20124 " GROUP BY 1\n"
20125 " ORDER BY 2 DESC, 1;",
20126 s.zSU);
20127 if( pStmt==0 ) return;
20128 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20129 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20130 diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20131 diskusedPercent(&s, (nn*100.0)/(double)nPage);
20132 }
20133 if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20134
20135 diskusedTitle(&s, "Page counts for all tables and indexes separately");
20136 pStmt = diskusedPrepare(&s,
20137 "SELECT upper(name),\n"
20138 " sum(int_pages+leaf_pages+ovfl_pages)\n"
20139 " FROM temp.%s\n"
20140 " WHERE name IS NOT NULL\n"
20141 " GROUP BY 1\n"
20142 " ORDER BY 2 DESC, 1;",
20143 s.zSU);
20144 if( pStmt==0 ) return;
20145 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
20146 sqlite3_int64 nn = sqlite3_column_int64(pStmt,1);
20147 diskusedLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
20148 diskusedPercent(&s, (nn*100.0)/(double)nPage);
20149 }
20150 if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20151
20152 rc = diskusedSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20153 if( rc ) return;
20154 rc = diskusedSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
20155 if( rc ) return;
20156 if( nWORowid>0 ){
20157 rc = diskusedSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
20158 pgsz, nPage);
20159 if( rc ) return;
20160 rc = diskusedSubreport(&s, "All rowid tables",
20161 "NOT is_without_rowid AND NOT is_index",
20162 pgsz, nPage);
20163 if( rc ) return;
20164 }
20165 rc = diskusedSubreport(&s, "All indexes", "is_index", pgsz, nPage);
20166 if( rc ) return;
20167
20168 pStmt = diskusedPrepare(&s,
20169 "SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
20170 " GROUP BY 1 ORDER BY 1",
20171 s.zSU);
20172 if( pStmt==0 ) return;
20173 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
@@ -20164,37 +20175,37 @@
20175 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
20176 int nSubIndex = sqlite3_column_int(pStmt, 2);
20177 if( nSubIndex==0 ){
20178 char *zTitle = sqlite3_mprintf("Table %s", zUpper);
20179 char *zWhere = sqlite3_mprintf("name=%Q", zName);
20180 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20181 sqlite3_free(zTitle);
20182 sqlite3_free(zWhere);
20183 if( rc ) break;
20184 }else{
20185 sqlite3_stmt *pS2;
20186 char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
20187 char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
20188 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20189 sqlite3_free(zTitle);
20190 sqlite3_free(zWhere);
20191 if( rc ) break;
20192 zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
20193 zWhere = sqlite3_mprintf("name=%Q", zName);
20194 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20195 sqlite3_free(zTitle);
20196 sqlite3_free(zWhere);
20197 if( rc ) break;
20198 if( nSubIndex>1 ){
20199 zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
20200 zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
20201 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20202 sqlite3_free(zTitle);
20203 sqlite3_free(zWhere);
20204 if( rc ) break;
20205 }
20206 pS2 = diskusedPrepare(&s,
20207 "SELECT name, upper(name) FROM temp.%s"
20208 " WHERE is_index AND tblname=%Q",
20209 s.zSU, zName);
20210 if( pS2==0 ){
20211 rc = SQLITE_NOMEM;
@@ -20203,25 +20214,25 @@
20214 while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
20215 const char *zU = (const char*)sqlite3_column_text(pS2, 1);
20216 const char *zN = (const char*)sqlite3_column_text(pS2, 0);
20217 zTitle = sqlite3_mprintf("Index %s", zU);
20218 zWhere = sqlite3_mprintf("name=%Q", zN);
20219 rc = diskusedSubreport(&s, zTitle, zWhere, pgsz, nPage);
20220 sqlite3_free(zTitle);
20221 sqlite3_free(zWhere);
20222 if( rc ) break;
20223 }
20224 rc = diskusedStmtFinish(&s, rc, pS2);
20225 if( rc ) break;
20226 }
20227 }
20228 if( diskusedStmtFinish(&s, rc, pStmt) ) return;
20229
20230 /* Append SQL statements that will recreate the raw data used for
20231 ** the analysis.
20232 */
20233 diskusedTitle(&s, "Raw data used to generate this report");
20234 sqlite3_str_appendf(s.pOut,
20235 "The following SQL will create a table named \"space_used\" which\n"
20236 "contains most of the information used to generate the report above.\n"
20237 "*/\n"
20238 );
@@ -20247,11 +20258,11 @@
20258 " ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
20259 " int_entries int -- B-tree entries on internal pages\n"/* 17 */
20260 ");\n"
20261 "INSERT INTO space_used VALUES\n"
20262 );
20263 pStmt = diskusedPrepare(&s,
20264 "SELECT quote(name), quote(tblname),\n" /* 0..1 */
20265 " is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
20266 " depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
20267 " int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
20268 " leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
@@ -20282,11 +20293,11 @@
20293 sqlite3_column_int64(pStmt, 15),
20294 sqlite3_column_int64(pStmt, 16),
20295 sqlite3_column_int64(pStmt, 17));
20296 }
20297 if( rc!=SQLITE_DONE ){
20298 diskusedError(&s, "SQL run-time error: %s\nSQL: %s",
20299 sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
20300 sqlite3_finalize(pStmt);
20301 return;
20302 }
20303 sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
@@ -20295,32 +20306,32 @@
20306 if( sqlite3_str_length(s.pOut) ){
20307 sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
20308 sqlite3_free);
20309 s.pOut = 0;
20310 }
20311 diskusedReset(&s);
20312 }
20313
20314
20315 #ifdef _WIN32
20316
20317 #endif
20318 int sqlite3_diskused_init(
20319 sqlite3 *db,
20320 char **pzErrMsg,
20321 const sqlite3_api_routines *pApi
20322 ){
20323 int rc = SQLITE_OK;
20324 SQLITE_EXTENSION_INIT2(pApi);
20325 (void)pzErrMsg; /* Unused parameter */
20326 rc = sqlite3_create_function(db, "diskused", 1,
20327 SQLITE_UTF8|SQLITE_INNOCUOUS,
20328 0, diskusedFunc, 0, 0);
20329 return rc;
20330 }
20331
20332 /************************* End ext/misc/diskused.c ********************/
20333
20334 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
20335 #define SQLITE_SHELL_HAVE_RECOVER 1
20336 #else
20337 #define SQLITE_SHELL_HAVE_RECOVER 0
@@ -26321,10 +26332,47 @@
26332 if( *az ){
26333 memcpy(*az, zNew, n+1 );
26334 }
26335 }
26336 }
26337
26338 /* Forward reference */
26339 static int pickStr(const char *zArg, char **pzErr, ...);
26340
26341 /*
26342 ** Change the limits on the display mode. Return 0 on
26343 ** success. Return non-zero if zArg is mis-formatted.
26344 **
26345 ** Valid arguments:
26346 **
26347 ** "on" Default limits
26348 ** "off" All limits turned off
26349 ** L,C Line and Characters limits set
26350 ** L,C,T Line, Character, and Title limits set
26351 **
26352 ** Anything else returns non-zero
26353 */
26354 static int modeSetLimit(ShellState *p, const char *zArg){
26355 int k = zArg==0 ? 1 : pickStr(zArg,0,"on","off","");
26356 if( k==0 ){
26357 p->mode.spec.nLineLimit = DFLT_LINE_LIMIT;
26358 p->mode.spec.nCharLimit = DFLT_CHAR_LIMIT;
26359 p->mode.spec.nTitleLimit = DFLT_TITLE_LIMIT;
26360 }else if( k==1 ){
26361 p->mode.spec.nLineLimit = 0;
26362 p->mode.spec.nCharLimit = 0;
26363 p->mode.spec.nTitleLimit = 0;
26364 }else{
26365 int L, C, T = 0;
26366 int nNum = sscanf(zArg, "%d,%d,%d", &L, &C, &T);
26367 if( nNum<2 || L<0 || C<0 || T<0) return 1;
26368 p->mode.spec.nLineLimit = L;
26369 p->mode.spec.nCharLimit = C;
26370 if( nNum==3 ) p->mode.spec.nTitleLimit = T;
26371 }
26372 return 0;
26373 }
26374
26375 /*
26376 ** Change the mode to eMode
26377 */
26378 static void modeChange(ShellState *p, unsigned char eMode){
@@ -26358,10 +26406,11 @@
26406 modeDup(&p->mode, &p->aSavedModes[eMode-MODE_USER].mode);
26407 }else if( eMode==MODE_BATCH ){
26408 u8 mFlags = p->mode.mFlags;
26409 modeFree(&p->mode);
26410 modeChange(p, MODE_List);
26411 modeSetLimit(p, "off");
26412 p->mode.mFlags = mFlags;
26413 }else if( eMode==MODE_TTY ){
26414 u8 mFlags = p->mode.mFlags;
26415 modeFree(&p->mode);
26416 modeChange(p, MODE_QBox);
@@ -28446,12 +28495,12 @@
28495 ".databases List names and files of attached databases",
28496 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
28497 #if SQLITE_SHELL_HAVE_RECOVER
28498 ".dbinfo ?DB? Show status information about the database",
28499 #endif
 
28500 ".dbtotxt Hex dump of the database file",
28501 ".diskused ?SCHEMA? Report database space and size stats",
28502 ".dump ?OBJECTS? Render database content as SQL",
28503 " Options:",
28504 " --data-only Output only INSERT statements",
28505 " --newlines Allow unescaped newline characters in output",
28506 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
@@ -29461,11 +29510,11 @@
29510 sqlite3_base64_init(p->db, 0, 0);
29511 sqlite3_base85_init(p->db, 0, 0);
29512 sqlite3_regexp_init(p->db, 0, 0);
29513 sqlite3_ieee_init(p->db, 0, 0);
29514 sqlite3_series_init(p->db, 0, 0);
29515 sqlite3_diskused_init(p->db, 0, 0);
29516 #ifndef SQLITE_SHELL_FIDDLE
29517 sqlite3_fileio_init(p->db, 0, 0);
29518 sqlite3_completion_init(p->db, 0, 0);
29519 #endif
29520 #ifdef SQLITE_HAVE_ZLIB
@@ -33123,30 +33172,14 @@
33172 }else if( optionMatch(z,"limits") ){
33173 if( (++i)>=nArg ){
33174 dotCmdError(p, i-1, "missing argument", 0);
33175 return 1;
33176 }
33177 if( modeSetLimit(p, azArg[i]) ){
33178 dotCmdError(p, i, "bad argument", "Should be \"on\" or \"off\" or "
33179 "\"L,C,T\" where L, C, and T are unsigned integers");
33180 return 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33181 }
33182 chng = 1;
33183 }else if( optionMatch(z,"list") ){
33184 int ii;
33185 cli_puts("available modes:", p->out);
@@ -34360,11 +34393,16 @@
34393 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
34394 rc = shell_dbinfo_command(p, nArg, azArg);
34395 }else
34396 #endif /* SQLITE_SHELL_HAVE_RECOVER */
34397
34398 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbtotxt", n)==0 ){
34399 open_db(p, 0);
34400 rc = shell_dbtotxt_command(p, nArg, azArg);
34401 }else
34402
34403 if( c=='d' && n==8 && cli_strncmp(azArg[0], "diskused", n)==0 ){
34404 const char *zSchema = 0;
34405 int ii;
34406 char *zSql;
34407 open_db(p, 0);
34408 for(ii=1; ii<nArg; ii++){
@@ -34379,27 +34417,19 @@
34417 rc = 1;
34418 goto meta_command_exit;
34419 }
34420 zSchema = z;
34421 }
34422 zSql = sqlite3_mprintf("SELECT diskused(%Q)", zSchema);
34423 shell_check_oom(zSql);
34424 modePush(p);
34425 modeChange(p, MODE_BATCH);
 
 
 
34426 shell_exec(p, zSql, 0);
34427 modePop(p);
34428 sqlite3_free(zSql);
34429 }else
34430
 
 
 
 
 
34431 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
34432 char *zLike = 0;
34433 char *zSql;
34434 int i;
34435 int savedShellFlags = p->shellFlgs;
@@ -37755,17 +37785,17 @@
37785 " -- treat no subsequent arguments as options\n"
37786 #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
37787 " -A ARGS... run \".archive ARGS\" and exit\n"
37788 #endif
37789 " -append append the database to the end of the file\n"
37790 " -ascii set '.mode ascii'\n"
37791 " -bail stop after hitting an error\n"
37792 " -batch force batch I/O\n"
37793 " -box set '.mode box'\n"
37794 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
37795 " -column set '.mode column'\n"
37796 " -csv set '.mode csv -limits off'\n"
37797 #if !defined(SQLITE_OMIT_DESERIALIZE)
37798 " -deserialize open the database using sqlite3_deserialize()\n"
37799 #endif
37800 " -echo print inputs before execution\n"
37801 " -escape T ctrl-char escape; T is one of: symbol, ascii, off\n"
@@ -37773,18 +37803,18 @@
37803 " -[no]header turn headers on or off\n"
37804 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
37805 " -heap SIZE Size of heap for memsys3 or memsys5\n"
37806 #endif
37807 " -help show this message\n"
37808 " -html set '.mode html'\n"
37809 " -ifexists only open if database already exists\n"
37810 " -interactive force interactive I/O\n"
37811 " -json set '.mode json'\n"
37812 " -line set '.mode line'\n"
37813 " -list set '.mode list'\n"
37814 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
37815 " -markdown set '.mode markdown'\n"
37816 #if !defined(SQLITE_OMIT_DESERIALIZE)
37817 " -maxsize N maximum size for a --deserialize database\n"
37818 #endif
37819 " -memtrace trace all memory allocations and deallocations\n"
37820 " -mmap N default mmap size set to N\n"
@@ -37797,21 +37827,21 @@
37827 " -nonce STRING set the safe-mode escape nonce\n"
37828 " -no-rowid-in-view Disable rowid-in-view using sqlite3_config()\n"
37829 " -nullvalue TEXT set text string for NULL values. Default ''\n"
37830 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
37831 " -pcachetrace trace all page cache operations\n"
37832 " -quote set '.mode quote'\n"
37833 " -readonly open the database read-only\n"
37834 " -safe enable safe-mode\n"
37835 " -screenwidth N use N as the default screenwidth \n"
37836 " -separator SEP set output column separator. Default: '|'\n"
37837 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
37838 " -sorterref SIZE sorter references threshold size\n"
37839 #endif
37840 " -stats print memory stats before each finalize\n"
37841 " -table set '.mode table'\n"
37842 " -tabs set '.mode tabs'\n"
37843 " -unsafe-testing allow unsafe commands and modes for testing\n"
37844 " -version show SQLite version\n"
37845 " -vfs NAME use NAME as the default VFS\n"
37846 " -vfstrace enable tracing of all VFS calls\n"
37847 #ifdef SQLITE_HAVE_ZLIB
@@ -38409,10 +38439,11 @@
38439 modeChange(&data, MODE_Psql);
38440 }else if( cli_strcmp(z,"-box")==0 ){
38441 modeChange(&data, MODE_Box);
38442 }else if( cli_strcmp(z,"-csv")==0 ){
38443 modeChange(&data, MODE_Csv);
38444 modeSetLimit(&data, "off");
38445 }else if( cli_strcmp(z,"-escape")==0 && i+1<argc ){
38446 /* See similar code at tag-20250224-1 */
38447 const char *zEsc = argv[++i];
38448 int k;
38449 for(k=0; k<ArraySize(qrfEscNames); k++){
38450
+12 -7
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
1616
** if you want a wrapper to interface SQLite with your choice of programming
1717
** language. The code for the "sqlite3" command-line shell is also in a
1818
** separate file. This file contains only code for the core SQLite library.
1919
**
2020
** The content in this amalgamation comes from Fossil check-in
21
-** 87c37dab7e53d1bd891f3fed624963b35ab1 with changes in files:
21
+** 2c605bfb1562d7a3609ad6ffd7446def12f1 with changes in files:
2222
**
2323
**
2424
*/
2525
#ifndef SQLITE_AMALGAMATION
2626
#define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467467
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468468
** [sqlite_version()] and [sqlite_source_id()].
469469
*/
470470
#define SQLITE_VERSION "3.54.0"
471471
#define SQLITE_VERSION_NUMBER 3054000
472
-#define SQLITE_SOURCE_ID "2026-05-28 11:29:05 87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10"
472
+#define SQLITE_SOURCE_ID "2026-05-30 13:23:25 2c605bfb1562d7a3609ad6ffd7446def12f1ac7084e41b9c6723e998c156501d"
473473
#define SQLITE_SCM_BRANCH "trunk"
474474
#define SQLITE_SCM_TAGS ""
475
-#define SQLITE_SCM_DATETIME "2026-05-28T11:29:05.704Z"
475
+#define SQLITE_SCM_DATETIME "2026-05-30T13:23:25.636Z"
476476
477477
/*
478478
** CAPI3REF: Run-Time Library Version Numbers
479479
** KEYWORDS: sqlite3_version sqlite3_sourceid
480480
**
@@ -212576,11 +212576,11 @@
212576212576
case SQLITE_NULL: {
212577212577
jsonAppendRawNZ(p, "null", 4);
212578212578
break;
212579212579
}
212580212580
case SQLITE_FLOAT: {
212581
- jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
212581
+ jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
212582212582
break;
212583212583
}
212584212584
case SQLITE_INTEGER: {
212585212585
const char *z = (const char*)sqlite3_value_text(pValue);
212586212586
u32 n = (u32)sqlite3_value_bytes(pValue);
@@ -217674,11 +217674,11 @@
217674217674
u8 nDim; /* Number of dimensions */
217675217675
u8 nDim2; /* Twice the number of dimensions */
217676217676
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
217677217677
u8 nBytesPerCell; /* Bytes consumed per cell */
217678217678
u8 inWrTrans; /* True if inside write transaction */
217679
- u8 nAux; /* # of auxiliary columns in %_rowid */
217679
+ u16 nAux; /* # of auxiliary columns in %_rowid */
217680217680
#ifdef SQLITE_ENABLE_GEOPOLY
217681217681
u8 nAuxNotNull; /* Number of initial not-null aux columns */
217682217682
#endif
217683217683
#ifdef SQLITE_DEBUG
217684217684
u8 bCorrupt; /* Shadow table corruption detected */
@@ -221152,11 +221152,11 @@
221152221152
"Too few columns for an rtree table", /* 2 */
221153221153
"Too many columns for an rtree table", /* 3 */
221154221154
"Auxiliary rtree columns must be last" /* 4 */
221155221155
};
221156221156
221157
- assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
221157
+ assert( RTREE_MAX_AUX_COLUMN<256 );
221158221158
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
221159221159
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
221160221160
return SQLITE_ERROR;
221161221161
}
221162221162
@@ -223070,10 +223070,15 @@
223070223070
sqlite3_int64 nName; /* Length of string argv[2] */
223071223071
sqlite3_str *pSql;
223072223072
char *zSql;
223073223073
int ii;
223074223074
(void)pAux;
223075
+
223076
+ if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
223077
+ *pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
223078
+ return SQLITE_ERROR;
223079
+ }
223075223080
223076223081
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
223077223082
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
223078223083
223079223084
/* Allocate the sqlite3_vtab structure */
@@ -263035,11 +263040,11 @@
263035263040
int nArg, /* Number of args */
263036263041
sqlite3_value **apUnused /* Function arguments */
263037263042
){
263038263043
assert( nArg==0 );
263039263044
UNUSED_PARAM2(nArg, apUnused);
263040
- sqlite3_result_text(pCtx, "fts5: 2026-05-28 11:29:05 87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10", -1, SQLITE_TRANSIENT);
263045
+ sqlite3_result_text(pCtx, "fts5: 2026-05-30 10:24:03 7487a1c59d3aaea9f8b2569dca76bbccf21948b1e7bd8a1d841e04382db696f4", -1, SQLITE_TRANSIENT);
263041263046
}
263042263047
263043263048
/*
263044263049
** Implementation of fts5_locale(LOCALE, TEXT) function.
263045263050
**
263046263051
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** 87c37dab7e53d1bd891f3fed624963b35ab1 with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468 ** [sqlite_version()] and [sqlite_source_id()].
469 */
470 #define SQLITE_VERSION "3.54.0"
471 #define SQLITE_VERSION_NUMBER 3054000
472 #define SQLITE_SOURCE_ID "2026-05-28 11:29:05 87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2026-05-28T11:29:05.704Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -212576,11 +212576,11 @@
212576 case SQLITE_NULL: {
212577 jsonAppendRawNZ(p, "null", 4);
212578 break;
212579 }
212580 case SQLITE_FLOAT: {
212581 jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
212582 break;
212583 }
212584 case SQLITE_INTEGER: {
212585 const char *z = (const char*)sqlite3_value_text(pValue);
212586 u32 n = (u32)sqlite3_value_bytes(pValue);
@@ -217674,11 +217674,11 @@
217674 u8 nDim; /* Number of dimensions */
217675 u8 nDim2; /* Twice the number of dimensions */
217676 u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
217677 u8 nBytesPerCell; /* Bytes consumed per cell */
217678 u8 inWrTrans; /* True if inside write transaction */
217679 u8 nAux; /* # of auxiliary columns in %_rowid */
217680 #ifdef SQLITE_ENABLE_GEOPOLY
217681 u8 nAuxNotNull; /* Number of initial not-null aux columns */
217682 #endif
217683 #ifdef SQLITE_DEBUG
217684 u8 bCorrupt; /* Shadow table corruption detected */
@@ -221152,11 +221152,11 @@
221152 "Too few columns for an rtree table", /* 2 */
221153 "Too many columns for an rtree table", /* 3 */
221154 "Auxiliary rtree columns must be last" /* 4 */
221155 };
221156
221157 assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
221158 if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
221159 *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
221160 return SQLITE_ERROR;
221161 }
221162
@@ -223070,10 +223070,15 @@
223070 sqlite3_int64 nName; /* Length of string argv[2] */
223071 sqlite3_str *pSql;
223072 char *zSql;
223073 int ii;
223074 (void)pAux;
 
 
 
 
 
223075
223076 sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
223077 sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
223078
223079 /* Allocate the sqlite3_vtab structure */
@@ -263035,11 +263040,11 @@
263035 int nArg, /* Number of args */
263036 sqlite3_value **apUnused /* Function arguments */
263037 ){
263038 assert( nArg==0 );
263039 UNUSED_PARAM2(nArg, apUnused);
263040 sqlite3_result_text(pCtx, "fts5: 2026-05-28 11:29:05 87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10", -1, SQLITE_TRANSIENT);
263041 }
263042
263043 /*
263044 ** Implementation of fts5_locale(LOCALE, TEXT) function.
263045 **
263046
--- extsrc/sqlite3.c
+++ extsrc/sqlite3.c
@@ -16,11 +16,11 @@
16 ** if you want a wrapper to interface SQLite with your choice of programming
17 ** language. The code for the "sqlite3" command-line shell is also in a
18 ** separate file. This file contains only code for the core SQLite library.
19 **
20 ** The content in this amalgamation comes from Fossil check-in
21 ** 2c605bfb1562d7a3609ad6ffd7446def12f1 with changes in files:
22 **
23 **
24 */
25 #ifndef SQLITE_AMALGAMATION
26 #define SQLITE_CORE 1
@@ -467,14 +467,14 @@
467 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468 ** [sqlite_version()] and [sqlite_source_id()].
469 */
470 #define SQLITE_VERSION "3.54.0"
471 #define SQLITE_VERSION_NUMBER 3054000
472 #define SQLITE_SOURCE_ID "2026-05-30 13:23:25 2c605bfb1562d7a3609ad6ffd7446def12f1ac7084e41b9c6723e998c156501d"
473 #define SQLITE_SCM_BRANCH "trunk"
474 #define SQLITE_SCM_TAGS ""
475 #define SQLITE_SCM_DATETIME "2026-05-30T13:23:25.636Z"
476
477 /*
478 ** CAPI3REF: Run-Time Library Version Numbers
479 ** KEYWORDS: sqlite3_version sqlite3_sourceid
480 **
@@ -212576,11 +212576,11 @@
212576 case SQLITE_NULL: {
212577 jsonAppendRawNZ(p, "null", 4);
212578 break;
212579 }
212580 case SQLITE_FLOAT: {
212581 jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
212582 break;
212583 }
212584 case SQLITE_INTEGER: {
212585 const char *z = (const char*)sqlite3_value_text(pValue);
212586 u32 n = (u32)sqlite3_value_bytes(pValue);
@@ -217674,11 +217674,11 @@
217674 u8 nDim; /* Number of dimensions */
217675 u8 nDim2; /* Twice the number of dimensions */
217676 u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
217677 u8 nBytesPerCell; /* Bytes consumed per cell */
217678 u8 inWrTrans; /* True if inside write transaction */
217679 u16 nAux; /* # of auxiliary columns in %_rowid */
217680 #ifdef SQLITE_ENABLE_GEOPOLY
217681 u8 nAuxNotNull; /* Number of initial not-null aux columns */
217682 #endif
217683 #ifdef SQLITE_DEBUG
217684 u8 bCorrupt; /* Shadow table corruption detected */
@@ -221152,11 +221152,11 @@
221152 "Too few columns for an rtree table", /* 2 */
221153 "Too many columns for an rtree table", /* 3 */
221154 "Auxiliary rtree columns must be last" /* 4 */
221155 };
221156
221157 assert( RTREE_MAX_AUX_COLUMN<256 );
221158 if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
221159 *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
221160 return SQLITE_ERROR;
221161 }
221162
@@ -223070,10 +223070,15 @@
223070 sqlite3_int64 nName; /* Length of string argv[2] */
223071 sqlite3_str *pSql;
223072 char *zSql;
223073 int ii;
223074 (void)pAux;
223075
223076 if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
223077 *pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
223078 return SQLITE_ERROR;
223079 }
223080
223081 sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
223082 sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
223083
223084 /* Allocate the sqlite3_vtab structure */
@@ -263035,11 +263040,11 @@
263040 int nArg, /* Number of args */
263041 sqlite3_value **apUnused /* Function arguments */
263042 ){
263043 assert( nArg==0 );
263044 UNUSED_PARAM2(nArg, apUnused);
263045 sqlite3_result_text(pCtx, "fts5: 2026-05-30 10:24:03 7487a1c59d3aaea9f8b2569dca76bbccf21948b1e7bd8a1d841e04382db696f4", -1, SQLITE_TRANSIENT);
263046 }
263047
263048 /*
263049 ** Implementation of fts5_locale(LOCALE, TEXT) function.
263050 **
263051
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,14 +146,14 @@
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149149
#define SQLITE_VERSION "3.54.0"
150150
#define SQLITE_VERSION_NUMBER 3054000
151
-#define SQLITE_SOURCE_ID "2026-05-28 11:29:05 87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10"
151
+#define SQLITE_SOURCE_ID "2026-05-30 13:23:25 2c605bfb1562d7a3609ad6ffd7446def12f1ac7084e41b9c6723e998c156501d"
152152
#define SQLITE_SCM_BRANCH "trunk"
153153
#define SQLITE_SCM_TAGS ""
154
-#define SQLITE_SCM_DATETIME "2026-05-28T11:29:05.704Z"
154
+#define SQLITE_SCM_DATETIME "2026-05-30T13:23:25.636Z"
155155
156156
/*
157157
** CAPI3REF: Run-Time Library Version Numbers
158158
** KEYWORDS: sqlite3_version sqlite3_sourceid
159159
**
160160
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,14 +146,14 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.54.0"
150 #define SQLITE_VERSION_NUMBER 3054000
151 #define SQLITE_SOURCE_ID "2026-05-28 11:29:05 87c37dab7e53d1bd891f3fed624963b35ab15a785706d0964b5d07ab70421c10"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2026-05-28T11:29:05.704Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
160
--- extsrc/sqlite3.h
+++ extsrc/sqlite3.h
@@ -146,14 +146,14 @@
146 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147 ** [sqlite_version()] and [sqlite_source_id()].
148 */
149 #define SQLITE_VERSION "3.54.0"
150 #define SQLITE_VERSION_NUMBER 3054000
151 #define SQLITE_SOURCE_ID "2026-05-30 13:23:25 2c605bfb1562d7a3609ad6ffd7446def12f1ac7084e41b9c6723e998c156501d"
152 #define SQLITE_SCM_BRANCH "trunk"
153 #define SQLITE_SCM_TAGS ""
154 #define SQLITE_SCM_DATETIME "2026-05-30T13:23:25.636Z"
155
156 /*
157 ** CAPI3REF: Run-Time Library Version Numbers
158 ** KEYWORDS: sqlite3_version sqlite3_sourceid
159 **
160
+34
--- src/stat.c
+++ src/stat.c
@@ -872,21 +872,55 @@
872872
** Show relative sizes of tables in the repository database.
873873
*/
874874
void repo_tabsize_page(void){
875875
int nPageFree;
876876
sqlite3_int64 fsize;
877
+ int bDetail = 0;
877878
char zBuf[100];
878879
879880
login_check_credentials();
880881
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
881882
cgi_check_for_malice();
883
+#if defined(SQLITE_VERSION_NUMBER) && SQLITE_VERSION_NUMBER>=3054000
884
+ if( g.perm.Admin && (bDetail = atoi(PD("detail","0")))!=0 ){
885
+ extern int sqlite3_diskused_init(
886
+ sqlite3*,
887
+ char**,
888
+ const sqlite3_api_routines*
889
+ );
890
+ sqlite3_diskused_init(g.db,0,0);
891
+ }
892
+#endif
882893
style_set_current_feature("stat");
883894
style_header("Repository Table Sizes");
884895
style_adunit_config(ADUNIT_RIGHT_OK);
885896
style_submenu_element("Stat", "stat");
897
+ if( bDetail ){
898
+ const char *zFName;
899
+ Stmt q;
900
+ zFName = sqlite3_db_filename(g.db, "repository");
901
+ @ <h1>%h(zFName)</h1>
902
+ db_prepare(&q, "SELECT diskused('repository')");
903
+ if( db_step(&q)==SQLITE_ROW ){
904
+ @ <pre>%h(db_column_text(&q,0))</pre>
905
+ }
906
+ db_finalize(&q);
907
+ if( g.localOpen ){
908
+ zFName = sqlite3_db_filename(g.db, "localdb");
909
+ @ <h1>%h(zFName)</h1>
910
+ db_prepare(&q, "SELECT diskused('localdb')");
911
+ if( db_step(&q)==SQLITE_ROW ){
912
+ @ <pre>%h(db_column_text(&q,0))</pre>
913
+ }
914
+ db_finalize(&q);
915
+ }
916
+ style_finish_page();
917
+ return;
918
+ }
886919
if( g.perm.Admin ){
887920
style_submenu_element("Schema", "repo_schema");
921
+ style_submenu_element("Details", "repo-tabsize?detail=1");
888922
}
889923
db_multi_exec(
890924
"CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;"
891925
"INSERT INTO trans(name,tabname)"
892926
" SELECT name, tbl_name FROM repository.sqlite_schema;"
893927
--- src/stat.c
+++ src/stat.c
@@ -872,21 +872,55 @@
872 ** Show relative sizes of tables in the repository database.
873 */
874 void repo_tabsize_page(void){
875 int nPageFree;
876 sqlite3_int64 fsize;
 
877 char zBuf[100];
878
879 login_check_credentials();
880 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
881 cgi_check_for_malice();
 
 
 
 
 
 
 
 
 
 
882 style_set_current_feature("stat");
883 style_header("Repository Table Sizes");
884 style_adunit_config(ADUNIT_RIGHT_OK);
885 style_submenu_element("Stat", "stat");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
886 if( g.perm.Admin ){
887 style_submenu_element("Schema", "repo_schema");
 
888 }
889 db_multi_exec(
890 "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;"
891 "INSERT INTO trans(name,tabname)"
892 " SELECT name, tbl_name FROM repository.sqlite_schema;"
893
--- src/stat.c
+++ src/stat.c
@@ -872,21 +872,55 @@
872 ** Show relative sizes of tables in the repository database.
873 */
874 void repo_tabsize_page(void){
875 int nPageFree;
876 sqlite3_int64 fsize;
877 int bDetail = 0;
878 char zBuf[100];
879
880 login_check_credentials();
881 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
882 cgi_check_for_malice();
883 #if defined(SQLITE_VERSION_NUMBER) && SQLITE_VERSION_NUMBER>=3054000
884 if( g.perm.Admin && (bDetail = atoi(PD("detail","0")))!=0 ){
885 extern int sqlite3_diskused_init(
886 sqlite3*,
887 char**,
888 const sqlite3_api_routines*
889 );
890 sqlite3_diskused_init(g.db,0,0);
891 }
892 #endif
893 style_set_current_feature("stat");
894 style_header("Repository Table Sizes");
895 style_adunit_config(ADUNIT_RIGHT_OK);
896 style_submenu_element("Stat", "stat");
897 if( bDetail ){
898 const char *zFName;
899 Stmt q;
900 zFName = sqlite3_db_filename(g.db, "repository");
901 @ <h1>%h(zFName)</h1>
902 db_prepare(&q, "SELECT diskused('repository')");
903 if( db_step(&q)==SQLITE_ROW ){
904 @ <pre>%h(db_column_text(&q,0))</pre>
905 }
906 db_finalize(&q);
907 if( g.localOpen ){
908 zFName = sqlite3_db_filename(g.db, "localdb");
909 @ <h1>%h(zFName)</h1>
910 db_prepare(&q, "SELECT diskused('localdb')");
911 if( db_step(&q)==SQLITE_ROW ){
912 @ <pre>%h(db_column_text(&q,0))</pre>
913 }
914 db_finalize(&q);
915 }
916 style_finish_page();
917 return;
918 }
919 if( g.perm.Admin ){
920 style_submenu_element("Schema", "repo_schema");
921 style_submenu_element("Details", "repo-tabsize?detail=1");
922 }
923 db_multi_exec(
924 "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;"
925 "INSERT INTO trans(name,tabname)"
926 " SELECT name, tbl_name FROM repository.sqlite_schema;"
927

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button