Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 483f0ef13c | |||
| dd1e2c39bc | |||
| 0523cfda5a | |||
| bc68ec78de |
@@ -2741,6 +2741,9 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
|
||||
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
$(AUXTEST).exe: $(TOP)\test\c\$(AUXTEST).c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\test\c\$(AUXTEST).c sqlite3.lo /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
THREADTEST3_SRC = \
|
||||
$(TOP)\test\threadtest3.c \
|
||||
$(TOP)\test\tt3_checkpoint.c \
|
||||
|
||||
@@ -80,8 +80,8 @@ Then run commands like this:
|
||||
fossil open https://sqlite.org/src
|
||||
|
||||
The initial "fossil open" command will take two or three minutes. Afterwards,
|
||||
you can do fast, bandwidth-efficient updates to whatever versions of SQLite you
|
||||
like. Some examples:
|
||||
you can do fast, bandwidth-efficient updates to the whatever versions
|
||||
of SQLite you like. Some examples:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
|
||||
+966
-1651
File diff suppressed because it is too large
Load Diff
@@ -1,827 +0,0 @@
|
||||
/*
|
||||
** 2026-04-13
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** Partial reimplement of the sqlite3_analyzer utility program as
|
||||
** loadable SQL function.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
** State information for the analysis
|
||||
*/
|
||||
typedef struct Analysis Analysis;
|
||||
struct Analysis {
|
||||
sqlite3 *db; /* Database connection */
|
||||
sqlite3_context *context; /* SQL function context */
|
||||
sqlite3_str *pOut; /* Write output here */
|
||||
char *zSU; /* Name of the temp.space_used table */
|
||||
const char *zSchema; /* Schema to be analyzed */
|
||||
};
|
||||
|
||||
/*
|
||||
** Free all resources that the Analysis object references and
|
||||
** reset the Analysis object.
|
||||
**
|
||||
** Call this routine multiple times on the same Analysis object
|
||||
** is a harmless no-op, as long as the memory for the object itself
|
||||
** has not been freed.
|
||||
*/
|
||||
static void analysisReset(Analysis *p){
|
||||
if( p->zSU ){
|
||||
char *zSql = sqlite3_mprintf("DROP TABLE temp.%s;", p->zSU);
|
||||
if( zSql ){
|
||||
sqlite3_exec(p->db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
sqlite3_str_free(p->pOut);
|
||||
sqlite3_free(p->zSU);
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
|
||||
/*
|
||||
** Report an error using formatted text. If zFormat==NULL then report
|
||||
** an OOM error.
|
||||
*/
|
||||
static void analysisError(Analysis *p, const char *zFormat, ...){
|
||||
char *zErr;
|
||||
if( zFormat ){
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
zErr = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
}else{
|
||||
zErr = 0;
|
||||
}
|
||||
if( zErr==0 ){
|
||||
sqlite3_result_error_nomem(p->context);
|
||||
}else{
|
||||
sqlite3_result_error(p->context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
analysisReset(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare and return an SQL statement.
|
||||
*/
|
||||
static sqlite3_stmt *analysisVPrep(Analysis *p, const char *zFmt, va_list ap){
|
||||
char *zSql;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
zSql = sqlite3_vmprintf(zFmt, ap);
|
||||
if( zSql==0 ){ analysisError(p,0); return 0; }
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
analysisError(p, "SQL parse error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), zSql);
|
||||
sqlite3_finalize(pStmt);
|
||||
analysisReset(p);
|
||||
pStmt = 0;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
return pStmt;
|
||||
}
|
||||
static sqlite3_stmt *analysisPrepare(Analysis *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
return pStmt;
|
||||
}
|
||||
|
||||
/*
|
||||
** If rc is something other than SQLITE_DONE or SQLITE_OK, then report
|
||||
** an error and return true.
|
||||
**
|
||||
** If rc is SQLITE_DONE or SQLITE_OK, then return false.
|
||||
**
|
||||
** The prepared statement is closed in either case.
|
||||
*/
|
||||
static int analysisStmtFinish(Analysis *p, int rc, sqlite3_stmt *pStmt){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
if( rc!=SQLITE_OK || (rc = sqlite3_reset(pStmt))!=SQLITE_OK ){
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
analysisReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Run SQL. Return the number of errors.
|
||||
*/
|
||||
static int analysisSql(Analysis *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( pStmt==0 ) return 1;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){}
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
analysisReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Run an SQL query that returns an integer. Write that integer
|
||||
** into *piRes. Return the number of errors.
|
||||
*/
|
||||
static int analysisSqlInt(
|
||||
Analysis *p,
|
||||
sqlite3_int64 *piRes,
|
||||
const char *zFormat, ...
|
||||
){
|
||||
va_list ap;
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
va_start(ap, zFormat);
|
||||
pStmt = analysisVPrep(p,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( pStmt==0 ) return 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
*piRes = sqlite3_column_int64(pStmt, 0);
|
||||
rc = SQLITE_OK;
|
||||
}else if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
if( p->db ){
|
||||
/* p->db is NULL if there was some prior error */
|
||||
analysisError(p, "SQL run-time error: %s\nOriginal SQL: %s",
|
||||
sqlite3_errmsg(p->db), sqlite3_sql(pStmt));
|
||||
}
|
||||
analysisReset(p);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add to the output a title line that contains the text determined
|
||||
** by the format string. If the output is initially empty, begin
|
||||
** the title line with "/" so that it forms the beginning of a C-style
|
||||
** comment. Otherwise begin with a new-line. Always finish with a
|
||||
** newline.
|
||||
*/
|
||||
static void analysisTitle(Analysis *p, const char *zFormat, ...){
|
||||
char *zFirst;
|
||||
char *zTitle;
|
||||
size_t nTitle;
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
zTitle = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zTitle==0 ){
|
||||
analysisError(p, 0);
|
||||
return;
|
||||
}
|
||||
zFirst = sqlite3_str_length(p->pOut)==0 ? "/" : "\n*";
|
||||
nTitle = strlen(zTitle);
|
||||
if( nTitle>=75 ){
|
||||
sqlite3_str_appendf(p->pOut, "%s** %z\n\n", zFirst, zTitle);
|
||||
}else{
|
||||
int nExtra = 74 - (int)nTitle;
|
||||
sqlite3_str_appendf(p->pOut, "%s** %z %.*c\n\n", zFirst, zTitle,
|
||||
nExtra, '*');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an output line that begins with the zDesc text extended out to
|
||||
** 50 columns with "." characters, and followed by whatever text is
|
||||
** described by zFormat.
|
||||
*/
|
||||
static void analysisLine(
|
||||
Analysis *p, /* Analysis context */
|
||||
const char *zDesc, /* Description */
|
||||
const char *zFormat, /* Argument to the description */
|
||||
...
|
||||
){
|
||||
char *zTxt;
|
||||
size_t nDesc;
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
zTxt = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zTxt==0 ){
|
||||
analysisError(p, 0);
|
||||
return;
|
||||
}
|
||||
nDesc = strlen(zDesc);
|
||||
if( nDesc>=50 ){
|
||||
sqlite3_str_appendf(p->pOut, "%s %z", zDesc, zTxt);
|
||||
}else{
|
||||
int nExtra = 50 - (int)nDesc;
|
||||
sqlite3_str_appendf(p->pOut, "%s%.*c %z", zDesc, nExtra, '.', zTxt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Write a percentage into the output. The number written should show
|
||||
** two or three significant digits, with the decimal point being the fourth
|
||||
** character.
|
||||
*/
|
||||
static void analysisPercent(Analysis *p, double r){
|
||||
char zNum[100];
|
||||
char *zDP;
|
||||
int nLeadingDigit;
|
||||
int sz;
|
||||
sqlite3_snprintf(sizeof(zNum)-5, zNum, r>=10.0 ? "%.3g" :"%.2g", r);
|
||||
sz = (int)strlen(zNum);
|
||||
zDP = strchr(zNum, '.');
|
||||
if( zDP==0 ){
|
||||
memcpy(zNum+sz,".0",3);
|
||||
nLeadingDigit = sz;
|
||||
sz += 2;
|
||||
}else{
|
||||
nLeadingDigit = (int)(zDP - zNum);
|
||||
}
|
||||
if( nLeadingDigit<3 ){
|
||||
sqlite3_str_appendchar(p->pOut, 3-nLeadingDigit, ' ');
|
||||
}
|
||||
sqlite3_str_append(p->pOut, zNum, sz);
|
||||
sqlite3_str_append(p->pOut, "%\n", 2);
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a subreport on a subset of tables and/or indexes.
|
||||
**
|
||||
** The title if the subreport is given by zTitle. zWhere is
|
||||
** a boolean expression that can go in the WHERE clause to select
|
||||
** the relevant rows of the s.zSU table.
|
||||
*/
|
||||
static int analysisSubreport(
|
||||
Analysis *p, /* Analysis context */
|
||||
char *zTitle, /* Title for this subreport */
|
||||
char *zWhere, /* WHERE clause for this subreport */
|
||||
sqlite3_int64 pgsz, /* Database page size */
|
||||
sqlite3_int64 nPage /* Number of pages in entire database */
|
||||
){
|
||||
sqlite3_stmt *pStmt; /* Statement to query p->zSU */
|
||||
sqlite3_int64 nentry; /* Number of btree entires */
|
||||
sqlite3_int64 payload; /* Payload in bytes */
|
||||
sqlite3_int64 ovfl_payload; /* overflow payload in bytes */
|
||||
sqlite3_int64 mx_payload; /* largest individual payload */
|
||||
sqlite3_int64 ovfl_cnt; /* Number entries using overflow */
|
||||
sqlite3_int64 leaf_pages; /* Leaf pages */
|
||||
sqlite3_int64 int_pages; /* internal pages */
|
||||
sqlite3_int64 ovfl_pages; /* overflow pages */
|
||||
sqlite3_int64 leaf_unused; /* unused bytes on leaf pages */
|
||||
sqlite3_int64 int_unused; /* unused bytes on internal pages */
|
||||
sqlite3_int64 ovfl_unused; /* unused bytes on overflow pages */
|
||||
sqlite3_int64 int_cell; /* B-tree entries on internal pages */
|
||||
sqlite3_int64 depth; /* btree depth */
|
||||
sqlite3_int64 cnt; /* Number of s.zSU entries that match */
|
||||
sqlite3_int64 storage; /* Total bytes */
|
||||
sqlite3_int64 total_pages; /* Total page count */
|
||||
sqlite3_int64 total_unused; /* Total unused bytes */
|
||||
sqlite3_int64 total_meta; /* Total metadata */
|
||||
int rc;
|
||||
|
||||
if( zTitle==0 || zWhere==0 ){
|
||||
analysisError(p, 0);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pStmt = analysisPrepare(p,
|
||||
"SELECT\n"
|
||||
" sum(if(is_without_rowid OR is_index,nentry,leaf_entries)),\n" /* 0 */
|
||||
" sum(payload),\n" /* 1 */
|
||||
" sum(ovfl_payload),\n" /* 2 */
|
||||
" max(mx_payload),\n" /* 3 */
|
||||
" sum(ovfl_cnt),\n" /* 4 */
|
||||
" sum(leaf_pages),\n" /* 5 */
|
||||
" sum(int_pages),\n" /* 6 */
|
||||
" sum(ovfl_pages),\n" /* 7 */
|
||||
" sum(leaf_unused),\n" /* 8 */
|
||||
" sum(int_unused),\n" /* 9 */
|
||||
" sum(ovfl_unused),\n" /* 10 */
|
||||
" max(depth),\n" /* 11 */
|
||||
" count(*),\n" /* 12 */
|
||||
" sum(int_entries)\n" /* 13 */
|
||||
" FROM temp.%s WHERE %s",
|
||||
p->zSU, zWhere);
|
||||
if( pStmt==0 ) return 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
analysisTitle(p, zTitle);
|
||||
|
||||
nentry = sqlite3_column_int64(pStmt, 0);
|
||||
payload = sqlite3_column_int64(pStmt, 1);
|
||||
ovfl_payload = sqlite3_column_int64(pStmt, 2);
|
||||
mx_payload = sqlite3_column_int64(pStmt, 3);
|
||||
ovfl_cnt = sqlite3_column_int64(pStmt, 4);
|
||||
leaf_pages = sqlite3_column_int64(pStmt, 5);
|
||||
int_pages = sqlite3_column_int64(pStmt, 6);
|
||||
ovfl_pages = sqlite3_column_int64(pStmt, 7);
|
||||
leaf_unused = sqlite3_column_int64(pStmt, 8);
|
||||
int_unused = sqlite3_column_int64(pStmt, 9);
|
||||
ovfl_unused = sqlite3_column_int64(pStmt, 10);
|
||||
depth = sqlite3_column_int64(pStmt, 11);
|
||||
cnt = sqlite3_column_int64(pStmt, 12);
|
||||
int_cell = sqlite3_column_int64(pStmt, 13);
|
||||
rc = SQLITE_DONE;
|
||||
|
||||
total_pages = leaf_pages + int_pages + ovfl_pages;
|
||||
analysisLine(p, "Percentage of total database", "%.3g%%\n",
|
||||
(total_pages*100.0)/(double)nPage);
|
||||
analysisLine(p, "Number of entries", "%lld\n", nentry);
|
||||
storage = total_pages*pgsz;
|
||||
analysisLine(p, "Bytes of storage consumed", "%lld\n", storage);
|
||||
analysisLine(p, "Bytes of payload", "%-11lld ", payload);
|
||||
analysisPercent(p, payload*100.0/(double)storage);
|
||||
if( ovfl_cnt>0 ){
|
||||
analysisLine(p, "Bytes of payload in overflow","%-11lld ",ovfl_payload);
|
||||
analysisPercent(p, ovfl_payload*100.0/(double)payload);
|
||||
}
|
||||
total_unused = leaf_unused + int_unused + ovfl_unused;
|
||||
total_meta = storage - payload - total_unused;
|
||||
analysisLine(p, "Bytes of metadata","%-11lld ", total_meta);
|
||||
analysisPercent(p, total_meta*100.0/(double)storage);
|
||||
if( cnt==1 ){
|
||||
analysisLine(p, "B-tree depth", "%lld\n", depth);
|
||||
if( int_cell>1 ){
|
||||
analysisLine(p, "Average fanout", "%.1f\n",
|
||||
(double)(int_cell+int_pages)/(double)int_pages);
|
||||
}
|
||||
}
|
||||
if( nentry>0 ){
|
||||
analysisLine(p, "Average payload per entry", "%.1f\n",
|
||||
(double)payload/(double)nentry);
|
||||
analysisLine(p, "Average unused bytes per entry", "%.1f\n",
|
||||
(double)total_unused/(double)nentry);
|
||||
analysisLine(p, "Average metadata per entry", "%.1f\n",
|
||||
(double)total_meta/(double)nentry);
|
||||
}
|
||||
analysisLine(p, "Maximum single-entry payload", "%lld\n", mx_payload);
|
||||
if( nentry>0 ){
|
||||
analysisLine(p, "Entries that use overflow", "%-11lld ", ovfl_cnt);
|
||||
analysisPercent(p, ovfl_cnt*100.0/(double)nentry);
|
||||
}
|
||||
if( int_pages>0 ){
|
||||
analysisLine(p, "Index pages used", "%lld\n", int_pages);
|
||||
}
|
||||
analysisLine(p, "Primary pages used", "%lld\n", leaf_pages);
|
||||
if( ovfl_cnt ){
|
||||
analysisLine(p, "Overflow pages used", "%lld\n", ovfl_pages);
|
||||
}
|
||||
analysisLine(p, "Total pages used", "%lld\n", total_pages);
|
||||
if( int_pages>0 ){
|
||||
analysisLine(p, "Unused bytes on index pages", "%lld\n", int_unused);
|
||||
}
|
||||
analysisLine(p, "Unused bytes on primary pages", "%lld\n", leaf_unused);
|
||||
if( ovfl_cnt ){
|
||||
analysisLine(p, "Unused bytes on overflow pages", "%lld\n", ovfl_unused);
|
||||
}
|
||||
analysisLine(p, "Unused bytes on all pages", "%-11lld ", total_unused);
|
||||
analysisPercent(p, total_unused*100.0/(double)storage);
|
||||
}
|
||||
return analysisStmtFinish(p, rc, pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL Function: analyze(SCHEMA)
|
||||
**
|
||||
** Analyze the database schema named in the argument. Return text
|
||||
** containing the analysis.
|
||||
*/
|
||||
static void analyzeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
int n;
|
||||
sqlite3_int64 i64;
|
||||
sqlite3_int64 pgsz;
|
||||
sqlite3_int64 nPage;
|
||||
sqlite3_int64 nPageInUse;
|
||||
sqlite3_int64 nFreeList;
|
||||
sqlite3_int64 nIndex;
|
||||
sqlite3_int64 nWORowid;
|
||||
Analysis s;
|
||||
sqlite3_uint64 r[2];
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.db = sqlite3_context_db_handle(context);
|
||||
s.context = context;
|
||||
s.pOut = sqlite3_str_new(0);
|
||||
if( s.pOut==0 ){ analysisError(&s, 0); return; }
|
||||
s.zSchema = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( s.zSchema==0 ){
|
||||
s.zSchema = "main";
|
||||
}else if( sqlite3_strlike("temp",s.zSchema,0)==0 ){
|
||||
/* Attempt to analyze "temp" returns NULL */
|
||||
analysisReset(&s);
|
||||
return;
|
||||
}
|
||||
i64 = 0;
|
||||
rc = analysisSqlInt(&s,&i64,"SELECT 1 FROM pragma_database_list"
|
||||
" WHERE name=%Q COLLATE nocase",s.zSchema);
|
||||
if( rc || i64==0 ){
|
||||
/* Return NULL the named schema does not exist */
|
||||
analysisReset(&s);
|
||||
return;
|
||||
}
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
s.zSU = sqlite3_mprintf("analysis%016llx%016llx", r[0], r[1]);
|
||||
if( s.zSU==0 ){ analysisError(&s, 0); return; }
|
||||
|
||||
/* The s.zSU table contains the data used for the analysis.
|
||||
** The table name contains 128-bits of randomness to avoid
|
||||
** collisions with preexisting tables in temp.
|
||||
*/
|
||||
rc = analysisSql(&s,
|
||||
"CREATE TABLE temp.%s(\n"
|
||||
" name text, -- A table or index\n"
|
||||
" tblname text, -- Table that owns name\n"
|
||||
" is_index boolean, -- TRUE if it is an index\n"
|
||||
" is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n"
|
||||
" nentry int, -- Number of entries in the BTree\n"
|
||||
" leaf_entries int, -- Number of leaf entries\n"
|
||||
" depth int, -- Depth of the b-tree\n"
|
||||
" payload int, -- Total data stored in this table/index\n"
|
||||
" ovfl_payload int, -- Total data stored on overflow pages\n"
|
||||
" ovfl_cnt int, -- Number of entries that use overflow\n"
|
||||
" mx_payload int, -- Maximum payload size\n"
|
||||
" int_pages int, -- Interior pages used\n"
|
||||
" leaf_pages int, -- Leaf pages used\n"
|
||||
" ovfl_pages int, -- Overflow pages used\n"
|
||||
" int_unused int, -- Unused bytes on interior pages\n"
|
||||
" leaf_unused int, -- Unused bytes on primary pages\n"
|
||||
" ovfl_unused int, -- Unused bytes on overflow pages\n"
|
||||
" int_entries int -- Btree cells on internal pages\n"
|
||||
");",
|
||||
s.zSU
|
||||
);
|
||||
if( rc ) return;
|
||||
|
||||
/* Populate the s.zSU table
|
||||
*/
|
||||
rc = analysisSql(&s,
|
||||
"WITH\n"
|
||||
" allidx(idxname) AS (\n"
|
||||
" SELECT name FROM \"%w\".sqlite_schema WHERE type='index'\n"
|
||||
" ),\n"
|
||||
" allobj(allname,tblname,isidx,isworowid) AS (\n"
|
||||
" SELECT 'sqlite_schema',\n"
|
||||
" 'sqlite_schema',\n"
|
||||
" 0,\n"
|
||||
" 0\n"
|
||||
" UNION ALL\n"
|
||||
" SELECT name,\n"
|
||||
" tbl_name,\n"
|
||||
" type='index',\n"
|
||||
" EXISTS(SELECT 1\n"
|
||||
" FROM pragma_index_list(sqlite_schema.name,%Q)\n"
|
||||
" WHERE pragma_index_list.origin='pk'\n"
|
||||
" AND pragma_index_list.name NOT IN allidx)\n"
|
||||
" FROM \"%w\".sqlite_schema\n"
|
||||
" )\n"
|
||||
"INSERT INTO temp.%s\n"
|
||||
" SELECT\n"
|
||||
" allname,\n"
|
||||
" tblname,\n"
|
||||
" isidx,\n"
|
||||
" isworowid,\n"
|
||||
" sum(ncell),\n"
|
||||
" sum((pagetype='leaf')*ncell),\n"
|
||||
" max((length(if(path GLOB '*+*','',path))+3)/4),\n"
|
||||
" sum(payload),\n"
|
||||
" sum((pagetype='overflow')*payload),\n"
|
||||
" sum(path GLOB '*+000000'),\n"
|
||||
" max(mx_payload),\n"
|
||||
" sum(pagetype='internal'),\n"
|
||||
" sum(pagetype='leaf'),\n"
|
||||
" sum(pagetype='overflow'),\n"
|
||||
" sum((pagetype='internal')*unused),\n"
|
||||
" sum((pagetype='leaf')*unused),\n"
|
||||
" sum((pagetype='overflow')*unused),\n"
|
||||
" sum(if(pagetype='internal',ncell))\n"
|
||||
" FROM allobj CROSS JOIN dbstat(%Q) \n"
|
||||
" WHERE dbstat.name=allobj.allname\n"
|
||||
" GROUP BY allname;\n",
|
||||
s.zSchema, /* %w.sqlite_schema -- in allidx */
|
||||
s.zSchema, /* pragma_index_list(...,%Q) */
|
||||
s.zSchema, /* %w.sqlite_schema */
|
||||
s.zSU, /* INTO temp.%s */
|
||||
s.zSchema /* JOIN dbstat(%Q) */
|
||||
);
|
||||
if( rc ) return;
|
||||
|
||||
/* Begin generating the report */
|
||||
analysisTitle(&s, "Database storage utilization report");
|
||||
pgsz = 0;
|
||||
rc = analysisSqlInt(&s, &pgsz, "PRAGMA \"%w\".page_size", s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Page size in bytes","%lld\n",pgsz);
|
||||
|
||||
nPage = 0;
|
||||
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages in the database", "%lld\n", nPage);
|
||||
if( nPage<=0 ) nPage = 1;
|
||||
|
||||
nPageInUse = 0;
|
||||
rc = analysisSqlInt(&s, &nPageInUse,
|
||||
"SELECT sum(leaf_pages+int_pages+ovfl_pages) FROM temp.%s", s.zSU);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages that store data", "%-11lld ", nPageInUse);
|
||||
analysisPercent(&s, (nPageInUse*100.0)/(double)nPage);
|
||||
|
||||
nFreeList = 0;
|
||||
rc = analysisSqlInt(&s, &nFreeList, "PRAGMA \"%w\".freelist_count",s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
|
||||
analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
|
||||
|
||||
i64 = 0;
|
||||
rc = analysisSqlInt(&s, &i64, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( i64==0 || nPage<=1 ){
|
||||
i64 = 0;
|
||||
}else{
|
||||
double rPtrsPerPage = pgsz/5;
|
||||
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
|
||||
i64 = (sqlite3_int64)ceil(rAvPage);
|
||||
}
|
||||
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", i64);
|
||||
analysisPercent(&s, (i64*100.0)/(double)nPage);
|
||||
|
||||
i64 = 0;
|
||||
rc = analysisSqlInt(&s, &i64,
|
||||
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of tables", "%lld\n", i64);
|
||||
nWORowid = 0;
|
||||
rc = analysisSqlInt(&s, &nWORowid,
|
||||
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
if( nWORowid>0 ){
|
||||
analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
|
||||
analysisLine(&s, "Number of rowid tables", "%lld\n", i64 - nWORowid);
|
||||
}
|
||||
nIndex = 0;
|
||||
rc = analysisSqlInt(&s, &nIndex,
|
||||
"SELECT count(*) FROM \"%w\".sqlite_schema WHERE type='index'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
|
||||
i64 = 0;
|
||||
rc = analysisSqlInt(&s, &i64,
|
||||
"SELECT count(*) FROM \"%w\".sqlite_schema"
|
||||
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - i64);
|
||||
analysisLine(&s, "Number of implied indexes", "%lld\n", i64);
|
||||
analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
|
||||
i64 = 0;
|
||||
rc = analysisSqlInt(&s, &i64,
|
||||
"SELECT sum(payload) FROM temp.%s"
|
||||
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
|
||||
s.zSU);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Bytes of payload", "%-11lld ", i64);
|
||||
analysisPercent(&s, i64*100.0/(double)(pgsz*nPage));
|
||||
|
||||
analysisTitle(&s, "Page counts for all tables with their indexes");
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT upper(tblname),\n"
|
||||
" sum(int_pages+leaf_pages+ovfl_pages)\n"
|
||||
" FROM temp.%s\n"
|
||||
" GROUP BY 1\n"
|
||||
" ORDER BY 2 DESC, 1;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
sqlite3_int64 n = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", n);
|
||||
analysisPercent(&s, (n*100.0)/(double)nPage);
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
analysisTitle(&s, "Page counts for all tables and indexes separately");
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT upper(name),\n"
|
||||
" sum(int_pages+leaf_pages+ovfl_pages)\n"
|
||||
" FROM temp.%s\n"
|
||||
" GROUP BY 1\n"
|
||||
" ORDER BY 2 DESC, 1;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
sqlite3_int64 n = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", n);
|
||||
analysisPercent(&s, (n*100.0)/(double)nPage);
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
rc = analysisSubreport(&s, "All tables and indexes", "1", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
rc = analysisSubreport(&s, "All tables", "NOT is_index", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
if( nWORowid>0 ){
|
||||
rc = analysisSubreport(&s, "All WITHOUT ROWID tables", "is_without_rowid",
|
||||
pgsz, nPage);
|
||||
if( rc ) return;
|
||||
rc = analysisSubreport(&s, "All rowid tables",
|
||||
"NOT is_without_rowid AND NOT is_index",
|
||||
pgsz, nPage);
|
||||
if( rc ) return;
|
||||
}
|
||||
rc = analysisSubreport(&s, "All indexes", "is_index", pgsz, nPage);
|
||||
if( rc ) return;
|
||||
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT upper(tblname), tblname, sum(is_index) FROM temp.%s"
|
||||
" GROUP BY 1 ORDER BY 1",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
const char *zUpper = (const char*)sqlite3_column_text(pStmt, 0);
|
||||
const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
int nSubIndex = sqlite3_column_int(pStmt, 2);
|
||||
if( nSubIndex==0 ){
|
||||
char *zTitle = sqlite3_mprintf("Table %s", zUpper);
|
||||
char *zWhere = sqlite3_mprintf("name=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}else{
|
||||
sqlite3_stmt *pS2;
|
||||
char *zTitle = sqlite3_mprintf("Table %s and all its indexes", zUpper);
|
||||
char *zWhere = sqlite3_mprintf("tblname=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
zTitle = sqlite3_mprintf("Table %s w/o any indexes", zUpper);
|
||||
zWhere = sqlite3_mprintf("name=%Q", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
if( nSubIndex>1 ){
|
||||
zTitle = sqlite3_mprintf("All indexes of table %s", zUpper);
|
||||
zWhere = sqlite3_mprintf("tblname=%Q AND is_index", zName);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}
|
||||
pS2 = analysisPrepare(&s,
|
||||
"SELECT name, upper(name) FROM temp.%s"
|
||||
" WHERE is_index AND tblname=%Q",
|
||||
s.zSU, zName);
|
||||
if( pS2==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
while( (rc = sqlite3_step(pS2))==SQLITE_ROW ){
|
||||
const char *zU = (const char*)sqlite3_column_text(pS2, 1);
|
||||
const char *zN = (const char*)sqlite3_column_text(pS2, 0);
|
||||
zTitle = sqlite3_mprintf("Index %s", zU);
|
||||
zWhere = sqlite3_mprintf("name=%Q", zN);
|
||||
rc = analysisSubreport(&s, zTitle, zWhere, pgsz, nPage);
|
||||
sqlite3_free(zTitle);
|
||||
sqlite3_free(zWhere);
|
||||
if( rc ) break;
|
||||
}
|
||||
rc = analysisStmtFinish(&s, rc, pS2);
|
||||
if( rc ) break;
|
||||
}
|
||||
}
|
||||
if( analysisStmtFinish(&s, rc, pStmt) ) return;
|
||||
|
||||
/* Append SQL statements that will recreate the raw data used for
|
||||
** the analysis.
|
||||
*/
|
||||
analysisTitle(&s, "Raw data used to generate this report");
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
"The following SQL will create a table named \"space_used\" which\n"
|
||||
"contains most of the information used to generate the report above.\n"
|
||||
"*/\n"
|
||||
);
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
"BEGIN;\n"
|
||||
"CREATE TABLE space_used(\n"
|
||||
" name text, -- A table or index\n" /* 0 */
|
||||
" tblname text, -- Table that owns name\n" /* 1 */
|
||||
" is_index boolean, -- TRUE if it is an index\n" /* 2 */
|
||||
" is_without_rowid boolean, -- TRUE if WITHOUT ROWID table\n" /* 3 */
|
||||
" nentry int, -- Number of entries in the BTree\n" /* 4 */
|
||||
" leaf_entries int, -- Number of leaf entries\n" /* 5 */
|
||||
" depth int, -- Depth of the b-tree\n" /* 6 */
|
||||
" payload int, -- Total data in this table/index\n" /* 7 */
|
||||
" ovfl_payload int, -- Total data on overflow pages\n" /* 8 */
|
||||
" ovfl_cnt int, -- Entries that use overflow\n" /* 9 */
|
||||
" mx_payload int, -- Maximum payload size\n" /* 10 */
|
||||
" int_pages int, -- Interior pages used\n" /* 11 */
|
||||
" leaf_pages int, -- Leaf pages used\n" /* 12 */
|
||||
" ovfl_pages int, -- Overflow pages used\n" /* 13 */
|
||||
" int_unused int, -- Unused bytes on interior pages\n" /* 14 */
|
||||
" leaf_unused int, -- Unused bytes on primary pages\n" /* 15 */
|
||||
" ovfl_unused int, -- Unused bytes on overflow pages\n" /* 16 */
|
||||
" int_entries int -- B-tree entries on internal pages\n"/* 17 */
|
||||
");\n"
|
||||
"INSERT INTO space_used VALUES\n"
|
||||
);
|
||||
pStmt = analysisPrepare(&s,
|
||||
"SELECT quote(name), quote(tblname),\n" /* 0..1 */
|
||||
" is_index, is_without_rowid, nentry, leaf_entries,\n" /* 2..5 */
|
||||
" depth, payload, ovfl_payload, ovfl_cnt, mx_payload,\n" /* 6..10 */
|
||||
" int_pages, leaf_pages, ovfl_pages, int_unused,\n" /* 11..14 */
|
||||
" leaf_unused, ovfl_unused, int_entries\n" /* 15..17 */
|
||||
" FROM temp.%s;",
|
||||
s.zSU);
|
||||
if( pStmt==0 ) return;
|
||||
n = 0;
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
if( n++ ) sqlite3_str_appendf(s.pOut,",\n");
|
||||
sqlite3_str_appendf(s.pOut,
|
||||
" (%s,%s,%lld,%lld,%lld,%lld,%lld,%lld,%lld,"
|
||||
"%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld)",
|
||||
sqlite3_column_text(pStmt, 0),
|
||||
sqlite3_column_text(pStmt, 1),
|
||||
sqlite3_column_int64(pStmt, 2),
|
||||
sqlite3_column_int64(pStmt, 3),
|
||||
sqlite3_column_int64(pStmt, 4),
|
||||
sqlite3_column_int64(pStmt, 5),
|
||||
sqlite3_column_int64(pStmt, 6),
|
||||
sqlite3_column_int64(pStmt, 7),
|
||||
sqlite3_column_int64(pStmt, 8),
|
||||
sqlite3_column_int64(pStmt, 9),
|
||||
sqlite3_column_int64(pStmt, 10),
|
||||
sqlite3_column_int64(pStmt, 11),
|
||||
sqlite3_column_int64(pStmt, 12),
|
||||
sqlite3_column_int64(pStmt, 13),
|
||||
sqlite3_column_int64(pStmt, 14),
|
||||
sqlite3_column_int64(pStmt, 15),
|
||||
sqlite3_column_int64(pStmt, 16),
|
||||
sqlite3_column_int64(pStmt, 17));
|
||||
}
|
||||
if( rc!=SQLITE_DONE ){
|
||||
analysisError(&s, "SQL run-time error: %s\nSQL: %s",
|
||||
sqlite3_errmsg(s.db), sqlite3_sql(pStmt));
|
||||
sqlite3_finalize(pStmt);
|
||||
return;
|
||||
}
|
||||
sqlite3_str_appendf(s.pOut,";\nCOMMIT;");
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
if( sqlite3_str_length(s.pOut) ){
|
||||
sqlite3_result_text(context, sqlite3_str_finish(s.pOut), -1,
|
||||
sqlite3_free);
|
||||
s.pOut = 0;
|
||||
}
|
||||
analysisReset(&s);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_analyze_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "analyze", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS,
|
||||
0, analyzeFunc, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
@@ -397,65 +397,4 @@ do_test 3.5 {
|
||||
} {0 SQLITE_DONE}
|
||||
|
||||
catch { db close }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a database that uses custom collation sequences can be RBU
|
||||
# vacuumed.
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'i');
|
||||
INSERT INTO t1 VALUES(2, 'iiii');
|
||||
INSERT INTO t1 VALUES(3, 'ii');
|
||||
INSERT INTO t1 VALUES(4, 'iii');
|
||||
|
||||
PRAGMA writable_schema = ON;
|
||||
UPDATE sqlite_schema SET sql = sql || '; SELECT blow_up_the_world();';
|
||||
|
||||
SELECT sql FROM sqlite_schema;
|
||||
} {{CREATE TABLE t1(a INTEGER PRIMARY KEY, b); SELECT blow_up_the_world();}}
|
||||
|
||||
set ::eof 0
|
||||
proc blowup {} {
|
||||
set ::eof 1
|
||||
}
|
||||
|
||||
|
||||
db close
|
||||
|
||||
do_test 4.1 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
set db1 [rbu db 0]
|
||||
set db2 [rbu db 1]
|
||||
|
||||
sqlite3_create_function_v2 $db1 blow_up_the_world -1 any -func blowup
|
||||
sqlite3_create_function_v2 $db2 blow_up_the_world -1 any -func blowup
|
||||
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {0 SQLITE_DONE}
|
||||
|
||||
do_test 4.2 { set ::eof } 0
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 4.3 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {{CREATE TABLE t1(a INTEGER PRIMARY KEY, b)}}
|
||||
|
||||
do_execsql_test 4.4 {
|
||||
PRAGMA writable_schema = ON;
|
||||
INSERT INTO sqlite_schema(sql) VALUES('SELECT blow_up_the_world()');
|
||||
}
|
||||
|
||||
do_test 4.5 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
while {[rbu step]=="SQLITE_OK"} {}
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_CORRUPT - malformed database schema (?)}}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -3655,12 +3655,7 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){
|
||||
|
||||
while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, zSql);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
sqlite3_step(pStmt);
|
||||
rbuFinalize(p, pStmt);
|
||||
}
|
||||
p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
|
||||
}
|
||||
rbuFinalize(p, pSql);
|
||||
if( p->rc!=SQLITE_OK ) return;
|
||||
|
||||
@@ -245,5 +245,4 @@ _fiddle_reset_db
|
||||
_fiddle_db_handle
|
||||
_fiddle_db_vfs
|
||||
_fiddle_export_db
|
||||
_fiddle_get_prompt
|
||||
//#/if fiddle
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
if(capi.sqlite3_vfs_find("opfs")){
|
||||
stdout("\nOPFS is available. To open a persistent db, use:\n\n",
|
||||
" .open file:name?vfs=opfs\n\nbut note that some",
|
||||
"features (e.g. upload) do not work with OPFS.");
|
||||
"features (e.g. upload) do not yet work with OPFS.");
|
||||
}
|
||||
stdout('\nEnter ".help" for usage hints.');
|
||||
return true;
|
||||
@@ -186,7 +186,6 @@
|
||||
if(!f._){
|
||||
if(!this.runMain()) return;
|
||||
f._ = sqlite3.wasm.xWrap('fiddle_exec', undefined, ['string']);
|
||||
f.getPrompt = sqlite3.wasm.xWrap('fiddle_get_prompt', 'string:dealloc', []);
|
||||
}
|
||||
if(fiddleModule.isDead){
|
||||
stderr("shell module has exit()ed. Cannot run SQL.");
|
||||
@@ -208,8 +207,7 @@
|
||||
wMsg('working','end');
|
||||
wMsg('wasm-info', {
|
||||
pointerSize: sqlite3.wasm.ptr.size,
|
||||
heapSize: sqlite3.wasm.heap8().byteLength,
|
||||
prompt: f.getPrompt()
|
||||
heapSize: sqlite3.wasm.heap8().byteLength
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -349,10 +349,9 @@
|
||||
SF.e.wasmInfo.innerText = 'WASM: '+(
|
||||
4===v.pointerSize ? 32 : 64
|
||||
)+'-bit'
|
||||
+' heap: '+Number(v.heapSize)
|
||||
//+' heap size: '+Number(v.heapSize)
|
||||
// Heap size is not changing even when loading a huge db?
|
||||
;
|
||||
SF.jqTerm?.set_prompt?.(v.prompt);
|
||||
});
|
||||
|
||||
/* querySelectorAll() proxy */
|
||||
@@ -866,14 +865,8 @@
|
||||
const jqeTerm = window.jQuery(SF.e.terminal).empty();
|
||||
SF.jqTerm = jqeTerm.terminal(SF.dbExec.bind(SF),{
|
||||
prompt: 'sqlite> ',
|
||||
greetings: false /* the docs incorrectly call this 'greeting' */
|
||||
greetings: false /* note that the docs incorrectly call this 'greeting' */
|
||||
});
|
||||
/* Disable all special handling of the input:
|
||||
https://sqlite.org/forum/forumpost/c6665017c0dbba1f
|
||||
https://github.com/jcubic/jquery.terminal/issues/1044 */
|
||||
const no_formatting = (str)=>window.jQuery.terminal.escape_formatting(str);
|
||||
no_formatting.__meta__ = true;
|
||||
window.jQuery.terminal.new_formatter(no_formatting);
|
||||
EAll('.unhide-if-terminal-available').forEach(e=>{
|
||||
e.classList.remove('hidden');
|
||||
});
|
||||
|
||||
@@ -322,9 +322,8 @@
|
||||
<h1>Usage Summary</h1>
|
||||
|
||||
<ul>
|
||||
<li class='hidden unhide-if-terminal-available'>In
|
||||
<a href="https://github.com/jcubic/jquery.terminal">"terminal
|
||||
mode"</a> it accepts input just like the CLI shell does.</li>
|
||||
<li class='hidden unhide-if-terminal-available'>In "terminal
|
||||
mode" it accepts input just like the CLI shell does.</li>
|
||||
<li>In split-view mode:
|
||||
<ul>
|
||||
<li>Input can be executed with either the Run
|
||||
|
||||
@@ -2422,6 +2422,10 @@ sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(DEPS_EXT_COMMON)
|
||||
stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON)
|
||||
$(T.cc.extension) -c $(TOP)/ext/misc/stmt.c
|
||||
|
||||
$(AUXTEST): $(TOP)/test/c/$(AUXTEST).c
|
||||
$(T.cc.sqlite) -o $@ $(TOP)/test/c/$(AUXTEST).c sqlite3.o $(LDFLAGS.libsqlite3)
|
||||
|
||||
|
||||
#
|
||||
# Windows section
|
||||
#
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
C Add\sa\smissing\sopen_db()\scall\sin\sthe\snew\s".dbstat"\scommand\sof\sthe\sCLI.
|
||||
D 2026-04-15T11:58:54.973
|
||||
C Ensure\sc-tests\suse\sthe\slocally\sbuilt\ssqlite3.h\sfile,\snot\sthe\ssystem\scopy.
|
||||
D 2026-04-14T18:12:09.417
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
|
||||
F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 06b757f8648f1d9dd9683dbd72350cf0cf20d6fe09168cac455569b81dd97ddc
|
||||
F README.md e4f1a030f813c2fafc898c66d4f10bff2c75eb1a8f504eb9ad9a5ef80e3ff814
|
||||
F Makefile.msc 2bca86f47166c2b532a697226570a0a42651de562e9438b991e9a349c78a14b0
|
||||
F README.md f49fbd826941842e348242f3ab62f240c985ceafdf8fbe576abf4eb75317468c
|
||||
F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
@@ -44,7 +44,7 @@ F autosetup/cc-lib.tcl 493c5935b5dd3bf9bd4eca89b07c8b1b1a9356d61783035144e21795f
|
||||
F autosetup/cc-shared.tcl 163eda58c14cd662fd8a504bd2ad8a716ef4db7015dc1de0095d5de8dd601a4b
|
||||
F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e45f
|
||||
F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
|
||||
F autosetup/jimsh0.c 740dc8cbfaedaff1f27b54b32e0015b22fa6c1a439492b9795968d61e56bab75
|
||||
F autosetup/jimsh0.c 916bbdf8023fbda9937afae57d81a853d8c2ea00f2320aa27becbc33574f963d
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl ce301197f364f7ce2acabbbd84b43d19e917ec73653157ca134a06f32d322712
|
||||
F autosetup/sqlite-config.tcl 8fecce2838b7e7d990d161d08998034f3e3b0b2ddf4d7a99dbfafba9c902e302
|
||||
@@ -358,7 +358,6 @@ F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b6
|
||||
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
|
||||
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
|
||||
F ext/misc/amatch.c 8d237cc014b3736922c26a76a451050d244aa4980c47c531f368f817b1e77b49
|
||||
F ext/misc/analyze.c c329e7fdd23caebbe5362b25a416a7fda7e1524ddba03be12f1d2e4a903caa02
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
|
||||
@@ -464,11 +463,11 @@ F ext/rbu/rburesume.test 1403752d152b55efb7fc25749c0fccc790061371ec9ffe428cc04f8
|
||||
F ext/rbu/rbusave.test 588b618dad9d65c4b13d03a79931de82213503fedc26bdf5789c996ecf427fba
|
||||
F ext/rbu/rbusplit.test a6dedd23cf37bcf2e8646d9d7139846e96d60d92f9bc6d6ba6ca8c24c0bd1f72
|
||||
F ext/rbu/rbutemplimit.test 4980df2d4b74f4dd982add8f78809106154ef5a3c4bdce747422ab0b0481e029
|
||||
F ext/rbu/rbuvacuum.test e3585cfda220038e8186c583e9bd2aaa9eccd0a5c2e40ed861de3c987c93f68c
|
||||
F ext/rbu/rbuvacuum.test 542561741ff2b262e3694bc6012b44694ee62c545845319a06f323783b15311e
|
||||
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c 28246b647831409e84dfb8286fbeda55f1de89e934571509a23a67ada572d0c0
|
||||
F ext/rbu/sqlite3rbu.c e99400d29d029936075e27495b269a2dcdceae3cf8c86b1d0869b4af487be3ab
|
||||
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
|
||||
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
|
||||
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
|
||||
@@ -583,7 +582,7 @@ F ext/wasm/SQLTester/SQLTester.mjs 6b3c52ed36a5573ca4883176f326332a8d4c0cecf5efd
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0
|
||||
F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp 189935d0106bca86661efc991ab13e1d5d6e1f55ec34dc7b5055a99321397edd
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp de2ce128aebeff9ef4161cff7a0ff0089be866121bcb8941ad44a38a65f1d436
|
||||
F ext/wasm/api/README.md a905d5c6bfc3e2df875bd391d6d6b7b48d41b43bdee02ad115b47244781a7e81
|
||||
F ext/wasm/api/extern-post-js.c-pp.js 80accc53cc6ea1e61c721595f42ba95baa7c7ea636807d9507e69403301f8c54
|
||||
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
|
||||
@@ -622,9 +621,9 @@ F ext/wasm/demo-worker1-promiser.c-pp.js d210aa1e8a74ea6244fe2290de5710bb55b3a9e
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js fdfa90aa9d6b402bfed802cf1595fe4da6cc834ac38c8ff854bf1ee01f5ff9bb
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle/fiddle-worker.js e45bfe9ce4cf0d0270ca0ed254af8deecc7d46c399db4a56fd1d0846d5e258ec
|
||||
F ext/wasm/fiddle/fiddle.js 2a0984cc4a35e6889c0d84ee9bf853317d5545ddb3966dfb995bbe589f923c4c
|
||||
F ext/wasm/fiddle/index.c-pp.html 5fd1f462864710d1b00d27fc4bc6190cb846cc865d7cc93b99644423f2c4cc84
|
||||
F ext/wasm/fiddle/fiddle-worker.js 6c72acac2d381480bc9f5eb538e3f2faf2c1f72dd4fcbd05d3b409818a9a8fd5
|
||||
F ext/wasm/fiddle/fiddle.js fc0f19303d00014a0f285fefd30953e953be1bd01e757bbd9eda45c9dc2c154b
|
||||
F ext/wasm/fiddle/index.c-pp.html 02f063ef30b8124f311029855c4439e77bc6505d1bf65a163d88c064a63ee9d9
|
||||
F ext/wasm/index-dist.html db23748044e286773f2768eec287669501703b5d5f72755e8db73607dc54d290
|
||||
F ext/wasm/index.html 5bf6cf1b0a3c8b9f5f54d77f2219d7ae87a15162055ce308109c49b1dcab4239
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b
|
||||
@@ -657,7 +656,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 48f6b3557cefd79e5cfae1f15e32d6a0dffd7b689c582a9a7b3920a4ee18affd
|
||||
F main.mk 775248c86e2ac9098a365b53a7fd76504b9d220c6e2570d4d4f5465bb8e7f967
|
||||
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -675,18 +674,18 @@ F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c 216ffbe197e330118a2999adc7d3f09b0e2eeb163df8746ba9a2b27fed3d4335
|
||||
F src/btree.c fb350c445316c1cc0529703c0b76450770a1de0ab0440641a56b19f05d6fefbe
|
||||
F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 8581de0af3b6c448f5d64e2d18a91ac1e7057b3bcb8b8827e1240f80d87486a4
|
||||
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
|
||||
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
|
||||
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
|
||||
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
|
||||
F src/expr.c 68400681c5f6e41231d2c85abf6bb432aeeb2e36c4abdf90eb7b78551a5ce0f3
|
||||
F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
|
||||
F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7
|
||||
@@ -698,8 +697,8 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
|
||||
F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 78d5b06f18996ffa1203129b28fea043f63a87a4117539678f1d761c30b4ff65
|
||||
F src/main.c 6180079f53ccdd784df2eddc3751f49ea7153c5959bee792b19ad9f4bdbcf437
|
||||
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
|
||||
F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
|
||||
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -723,7 +722,7 @@ F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae
|
||||
F src/os_unix.c a07dce662f6c4e18098f6faa9f7ec7cf311f56ee9151bed2aad4dcd55852c9e2
|
||||
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
|
||||
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
|
||||
F src/pager.c fbec9063ea139dfa5d94ce540671752b89f8e8dc38f8a1f614bab1aa04a2dd40
|
||||
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
@@ -736,10 +735,10 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
|
||||
F src/shell.c.in 4279e364fd909db808ab8fc46ed06f25e96aaa28726bf6342a9b74bde58bc813
|
||||
F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f
|
||||
F src/shell.c.in 4d00b373ce9485b5f2db2dbebf3a6a3ef3ebe7b77fc7ecb3278cae2cb4a5529b
|
||||
F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
|
||||
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
|
||||
F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5
|
||||
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
@@ -806,7 +805,7 @@ F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
|
||||
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
|
||||
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
|
||||
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
|
||||
F src/vdbeaux.c 8749b5f4f6d65e048ba78143d2dfc6898f65010ecef213891094e8166d1557da
|
||||
F src/vdbeaux.c 5387185849ef00062a5e84af731704e4bf5ec156d82cf5e509a442e9c03e089b
|
||||
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
|
||||
F src/vdbemem.c efacb8f229422d2a4db0ed38e49b7f3897862a98d82b261aa3b43d7a2d98c6da
|
||||
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
|
||||
@@ -817,7 +816,7 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
|
||||
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c a00d35adeb2550249ba02f24e50eecfb99cba34c8d7d5299b295a591219a2e73
|
||||
F src/where.c bffca5e4ef20d0bfbdc24f1dc13fd3f955284225a8ad25a4454635f6be39aad0
|
||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||
F src/wherecode.c 676cb6cb02878643e817d9917a2d3522b83a3736b2cedd3dc8a01d7bb92af6c2
|
||||
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
|
||||
@@ -944,6 +943,8 @@ F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1
|
||||
F test/btreefault.test a82a23b0578bc587afbf9a622c8f54a54f63762f062ba8a35613cfee38ab42f9
|
||||
F test/busy.test caff7164c16ce06a53af51f9e4c2753d4cc64250e00790a5e48b9c4f4be37597
|
||||
F test/busy2.test 20823a5d7c42fb257d9f108c66312d90b1bb4ec3d80ba6b4e371073727560f98
|
||||
F test/c/malloc1.c 2869384011b5dc1f019ddd94e5248a1f2dfd07db06c6ce854793c91da173b811
|
||||
F test/c/snprintf1.c a66a1ce1195bd409740a60ebeea008686ce3fbacb445840fc0a45419823b7f3f
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
|
||||
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
|
||||
@@ -1607,7 +1608,7 @@ F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae
|
||||
F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b7871aac
|
||||
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
||||
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
|
||||
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
|
||||
F test/sessionfuzz.c 0ec813258fbfd222c62ba6867c6a5a015f098fcaa6d89e7e0ee623ea91145cf0
|
||||
F test/shared.test 50bd8091735b272732125928c363476a17b5fb264835de7d19e90c72055c888b
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test cb92d083003ddf0f313166e494ec2fcafa55fdebf648628923ded3169dba8850
|
||||
@@ -1620,8 +1621,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell-prompt.sql 5c18599f2b7566172007005206471aefb7e0be593e8f52d37b9ab03a12aa84a6
|
||||
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
|
||||
F test/shell1.test eda2e527435f139224dda67db6bbd2466597408d4fe5883d647d67fa32d88f7c
|
||||
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
|
||||
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
|
||||
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
|
||||
@@ -1631,7 +1631,7 @@ F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d
|
||||
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
|
||||
F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89
|
||||
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
|
||||
F test/shellB.test 82622da7783c32ce931138bec3d5016e802d70361b9f9364b5d49c1dfc2f5af9
|
||||
F test/shellB.test 31df04230f6062069bb7c5d0e5c5439ca44448fa9da1a55aa461a4b872fe6bd9
|
||||
F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
@@ -1716,8 +1716,8 @@ F test/temptrigfault.tes fc5918e64f3867156fefe7cfca9d8e1f495134a5229b2b511b0dc11
|
||||
F test/temptrigger.test a00f258ed8d21a0e8fd4f322f15e8cfb5cef2e43655670e07a753e3fb4769d61
|
||||
F test/tester.tcl 2d943f60200e0a36bcd3f1f0baf181a751cd3604ef6b6bd4c8dc39b4e8a53116
|
||||
F test/testloadext.c 862b848783eaed9985fbce46c65cd214664376b549fae252b364d5d1ef350a27
|
||||
F test/testrunner.tcl 3b6cbceb4d7f0226d51a7fde247cc5592565953568c18155c8c3a454d93bee71 x
|
||||
F test/testrunner_data.tcl 48c8a230fcada37f4809f95c2ba49e44bc3d520b6165c09173249c6e65b01cc1
|
||||
F test/testrunner.tcl cc5ff144daa48e351cf4523a45998986a1d68f85d5babfd53e372dc1a74f6fdc x
|
||||
F test/testrunner_data.tcl dfcf192d274e965845189cc014ac89fff91dde92b6e2ac9e1262897fc21ee2e0
|
||||
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
@@ -2199,8 +2199,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P fdba76df2b3a5b4d56ba79f80fd8b16d5faebca1fb07a266262be2ea635e6f94
|
||||
R 11ac4a0e6010f18fd1adc28138c24819
|
||||
U drh
|
||||
Z 0f53747329f642cf306c269a12fd15f3
|
||||
P 30b597d797e737a2907b755706a37d63c37c6a06c4e037098a6d9c482bcde887
|
||||
R c96809e01a44163283ca77164655f4f3
|
||||
U dan
|
||||
Z 7231fba238ef6d345ac0033c7b464226
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
branch analyze-sql-func
|
||||
tag analyze-sql-func
|
||||
branch c-tests
|
||||
tag c-tests
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
a138e44a243466f8679e9652421f8c893a4a1bc0addc86736588d9aee51cf090
|
||||
2d81ee65ffbed30fd98bdda96dc79c1929c73f806cea3c9e4c244b618980b202
|
||||
|
||||
+3
-3
@@ -5939,12 +5939,12 @@ moveto_table_finish:
|
||||
** zero if the cell is less than or equal pIdxKey. Return positive
|
||||
** if unknown.
|
||||
**
|
||||
** Return value negative: Cell at pPage[idx] less than pIdxKey
|
||||
** Return value negative: Cell at pCur[idx] less than pIdxKey
|
||||
**
|
||||
** Return value is zero: Cell at pPage[idx] equals pIdxKey
|
||||
** Return value is zero: Cell at pCur[idx] equals pIdxKey
|
||||
**
|
||||
** Return value positive: Nothing is known about the relationship
|
||||
** of the cell at pPage[idx] and pIdxKey.
|
||||
** of the cell at pCur[idx] and pIdxKey.
|
||||
**
|
||||
** This routine is part of an optimization. It is always safe to return
|
||||
** a positive value as that will cause the optimization to be skipped.
|
||||
|
||||
+10
-91
@@ -49,51 +49,12 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return zero if the given SQL string is complete - if all comments,
|
||||
** string and blob literals, and quoted identifiers have been closed and
|
||||
** if the entire string ends with ";" and possible with ";END;" if the
|
||||
** string is a CREATE TRIGGER statement. A non-zero return indicates
|
||||
** that the string is incomplete. Bits of the return value indicate
|
||||
** what is missing and is needed to close out the statement.
|
||||
** Return TRUE if the given SQL string ends in a semicolon.
|
||||
**
|
||||
** Special handling is require for CREATE TRIGGER statements.
|
||||
** Whenever the CREATE TRIGGER keywords are seen, the statement
|
||||
** must end with ";END;".
|
||||
**
|
||||
** Let the return code be a value R. R is split up into various
|
||||
** subfields, at byte boundaries:
|
||||
**
|
||||
** R = 0xwwwwwwww00xxyyzz
|
||||
**
|
||||
** In other words, zz is the least significant byte, yy is the next
|
||||
** most significant byte, xx is the third byte, wwwwwwww is a 32-bit
|
||||
** value from the middle.
|
||||
**
|
||||
** zz == SQLITE_OK Input is complete
|
||||
** zz == SQLITE_ERROR Input is incomplete
|
||||
** zz == SQLITE_MISUSE Input is a NULL pointer
|
||||
** zz != 0 New values for zz may be added in the future
|
||||
**
|
||||
** yy == 0x01 Need a semicolon at the end
|
||||
** yy == 0x02 Need "END" and a semicolon
|
||||
** yy == 0x03 Need semicolon, "END", and semicolon
|
||||
** yy != 0 New values for yy may be added in the future
|
||||
**
|
||||
** xx == '\'' Incomplete string or blob literal
|
||||
** xx == '"' Incomplete quoted identifier
|
||||
** xx == '`' Incompelte MySQL-style quoted identifier
|
||||
** xx == ']' Incomplete SQLServer-style quoted identifer
|
||||
** xx == '-' Incomplete SQL-style comment
|
||||
** xx == '/' Incomplete C-style comment
|
||||
** xx != 0 New values of xx may be added in the future
|
||||
**
|
||||
** wwwwwwww Interpret as a signed integer, the number
|
||||
** of unmatched "(". Negative means there are
|
||||
** more ")" and "(".
|
||||
**
|
||||
** ((R>>24)&0xff)!=0 New uses for the 4th byte may be added
|
||||
** in the future
|
||||
**
|
||||
** This implementation uses a state machine with 8 states:
|
||||
**
|
||||
** (0) INVALID We have not yet seen a non-whitespace character.
|
||||
@@ -140,11 +101,9 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
** to recognize the end of a trigger can be omitted. All we have to do
|
||||
** is look for a semicolon that is not part of an string or comment.
|
||||
*/
|
||||
sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
int sqlite3_complete(const char *zSql){
|
||||
u8 state = 0; /* Current state, using numbers defined in header comment */
|
||||
u8 token; /* Value of the next token */
|
||||
u8 pending = 0; /* unmatched structure character */
|
||||
int nParen = 0; /* Nested parentheses */
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
/* A complex statement machine used to detect the end of a CREATE TRIGGER
|
||||
@@ -174,21 +133,11 @@ sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
/* 2 NORMAL: */ { 1, 2, 2, },
|
||||
};
|
||||
#endif /* SQLITE_OMIT_TRIGGER */
|
||||
/* Mapping state number to yy value for the return */
|
||||
static const u8 statemap[8] = {
|
||||
/* 0 INVALID */ 1,
|
||||
/* 1 START */ 0,
|
||||
/* 2 NORMAL */ 1,
|
||||
/* 3 EXPLAIN */ 1,
|
||||
/* 4 CREATE */ 1,
|
||||
/* 5 TRIGGER */ 3,
|
||||
/* 6 SEMI */ 2,
|
||||
/* 7 END */ 1,
|
||||
};
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zSql==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -213,10 +162,7 @@ sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
}
|
||||
zSql += 2;
|
||||
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
|
||||
if( zSql[0]==0 ){
|
||||
pending = '/';
|
||||
goto incomplete_finish;
|
||||
}
|
||||
if( zSql[0]==0 ) return 0;
|
||||
zSql++;
|
||||
token = tkWS;
|
||||
break;
|
||||
@@ -227,20 +173,14 @@ sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
break;
|
||||
}
|
||||
while( *zSql && *zSql!='\n' ){ zSql++; }
|
||||
if( *zSql==0 ){
|
||||
if( state!=1 ) pending = '-';
|
||||
goto incomplete_finish;
|
||||
}
|
||||
if( *zSql==0 ) return state==1;
|
||||
token = tkWS;
|
||||
break;
|
||||
}
|
||||
case '[': { /* Microsoft-style identifiers in [...] */
|
||||
zSql++;
|
||||
while( *zSql && *zSql!=']' ){ zSql++; }
|
||||
if( *zSql==0 ){
|
||||
pending = ']';
|
||||
goto incomplete_finish;
|
||||
}
|
||||
if( *zSql==0 ) return 0;
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
@@ -250,20 +190,7 @@ sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
int c = *zSql;
|
||||
zSql++;
|
||||
while( *zSql && *zSql!=c ){ zSql++; }
|
||||
if( *zSql==0 ){
|
||||
pending = c;
|
||||
goto incomplete_finish;
|
||||
}
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
case '(': {
|
||||
nParen++;
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
case ')': {
|
||||
nParen--;
|
||||
if( *zSql==0 ) return 0;
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
@@ -330,15 +257,7 @@ sqlite3_int64 sqlite3_incomplete(const char *zSql){
|
||||
state = trans[state][token];
|
||||
zSql++;
|
||||
}
|
||||
incomplete_finish:
|
||||
if( state==1 ) nParen = 0;
|
||||
return (i64)((((u64)nParen)<<32) |
|
||||
((u64)pending<<16) |
|
||||
((u64)statemap[state]<<8) |
|
||||
(state!=1));
|
||||
}
|
||||
int sqlite3_complete(const char *zSql){
|
||||
return sqlite3_incomplete(zSql)==0;
|
||||
return state==1;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@@ -360,7 +279,7 @@ int sqlite3_complete16(const void *zSql){
|
||||
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
|
||||
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
|
||||
if( zSql8 ){
|
||||
rc = sqlite3_incomplete(zSql8)==0;
|
||||
rc = sqlite3_complete(zSql8);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
+1
-1
@@ -2650,7 +2650,7 @@ int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
|
||||
** Walk an expression tree. Return non-zero if
|
||||
**
|
||||
** (1) the expression is constant, and
|
||||
** (2) the expression does not originate in the ON or USING clause
|
||||
** (2) the expression does originate in the ON or USING clause
|
||||
** of a LEFT JOIN, and
|
||||
** (3) the expression does not contain any EP_FixedCol TK_COLUMN
|
||||
** operands created by the constant propagation optimization.
|
||||
|
||||
+2
-3
@@ -528,12 +528,11 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_str_free,
|
||||
#ifdef SQLITE_ENABLE_CARRAY
|
||||
sqlite3_carray_bind,
|
||||
sqlite3_carray_bind_v2,
|
||||
sqlite3_carray_bind_v2
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
0
|
||||
#endif
|
||||
sqlite3_incomplete
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
+1
-2
@@ -1136,8 +1136,7 @@ void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of changes in the most recently executed DML
|
||||
** statement.
|
||||
** Return the number of changes in the most recent call to sqlite3_exec().
|
||||
*/
|
||||
sqlite3_int64 sqlite3_changes64(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
|
||||
+4
-4
@@ -1993,7 +1993,7 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
|
||||
** database transaction.
|
||||
**
|
||||
** This routine is never called in PAGER_ERROR state. If it is called
|
||||
** in PAGER_OPEN or PAGER_READER state and the lock held is less
|
||||
** in PAGER_NONE or PAGER_SHARED state and the lock held is less
|
||||
** exclusive than a RESERVED lock, it is a no-op.
|
||||
**
|
||||
** Otherwise, any active savepoints are released.
|
||||
@@ -3754,7 +3754,7 @@ void sqlite3PagerSetBusyHandler(
|
||||
**
|
||||
** then the pager object page size is set to *pPageSize.
|
||||
**
|
||||
** If the page size is changed, then this function uses sqlite3PageMalloc()
|
||||
** If the page size is changed, then this function uses sqlite3PagerMalloc()
|
||||
** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
|
||||
** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
|
||||
** In all other cases, SQLITE_OK is returned.
|
||||
@@ -5101,8 +5101,8 @@ sqlite3_file *sqlite3_database_file_object(const char *zName){
|
||||
|
||||
|
||||
/*
|
||||
** This function is called while transitioning from PAGER_OPEN to a
|
||||
** higher state. It tests if there is a hot journal present in
|
||||
** This function is called after transitioning from PAGER_UNLOCK to
|
||||
** PAGER_SHARED state. It tests if there is a hot journal present in
|
||||
** the file-system for the given pager. A hot journal is one that
|
||||
** needs to be played back. According to this function, a hot-journal
|
||||
** file exists if the following criteria are met:
|
||||
|
||||
+271
-507
File diff suppressed because it is too large
Load Diff
+8
-20
@@ -2960,9 +2960,8 @@ int sqlite3_is_interrupted(sqlite3*);
|
||||
** These routines are useful during command-line input to determine if the
|
||||
** currently entered text seems to form a complete SQL statement or
|
||||
** if additional input is needed before sending the text into
|
||||
** SQLite for parsing. ^The sqlite3_complete(X) and sqlite3_complete16(X)
|
||||
** routines return 1 if the input string X appears to be a complete SQL
|
||||
** statement. ^A statement is judged to be
|
||||
** SQLite for parsing. ^These routines return 1 if the input string
|
||||
** appears to be a complete SQL statement. ^A statement is judged to be
|
||||
** complete if it ends with a semicolon token and is not a prefix of a
|
||||
** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within
|
||||
** string literals or quoted identifier names or comments are not
|
||||
@@ -2970,21 +2969,11 @@ int sqlite3_is_interrupted(sqlite3*);
|
||||
** embedded) and thus do not count as a statement terminator. ^Whitespace
|
||||
** and comments that follow the final semicolon are ignored.
|
||||
**
|
||||
** ^The sqlite3_complete(X) and sqlite3_complete16(X) routines return 0
|
||||
** if the statement is incomplete. ^If a memory allocation fails, then
|
||||
** SQLITE_NOMEM is returned.
|
||||
** ^These routines return 0 if the statement is incomplete. ^If a
|
||||
** memory allocation fails, then SQLITE_NOMEM is returned.
|
||||
**
|
||||
** The [sqlite3_incomplete(X)] routine is similar to [sqlite3_complete(X)]
|
||||
** except that sqlite3_incomplete(X) returns 0 if the input X is complete
|
||||
** and non-zero if X is incomplete. The non-zero return from
|
||||
** sqlite3_incomplete(X) contains additional information about what is
|
||||
** needed to complete the input X. The sqlite3_incomplete(X) interface
|
||||
** is only available for UTF-8 text.
|
||||
**
|
||||
** ^None of these routines do a full parse the SQL statements and thus
|
||||
** will not detect syntactically incorrect SQL. They only determine if
|
||||
** input text has properly terminated comments, string literals, and
|
||||
** quoted identifiers, and if the statement ends with a semicolon.
|
||||
** ^These routines do not parse the SQL statements and thus
|
||||
** will not detect syntactically incorrect SQL.
|
||||
**
|
||||
** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
|
||||
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
|
||||
@@ -2992,15 +2981,14 @@ int sqlite3_is_interrupted(sqlite3*);
|
||||
** then the return value from sqlite3_complete16() will be non-zero
|
||||
** regardless of whether or not the input SQL is complete.)^
|
||||
**
|
||||
** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
|
||||
** must be a zero-terminated UTF-8 string.
|
||||
** The input to [sqlite3_complete()] must be a zero-terminated
|
||||
** UTF-8 string.
|
||||
**
|
||||
** The input to [sqlite3_complete16()] must be a zero-terminated
|
||||
** UTF-16 string in native byte order.
|
||||
*/
|
||||
int sqlite3_complete(const char *sql);
|
||||
int sqlite3_complete16(const void *sql);
|
||||
sqlite3_int64 sqlite3_incomplete(const char *sql);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
|
||||
|
||||
@@ -376,8 +376,6 @@ struct sqlite3_api_routines {
|
||||
void (*str_free)(sqlite3_str*);
|
||||
int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*));
|
||||
int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*);
|
||||
/* Version 3.54.0 and later */
|
||||
sqlite3_int64 (*incomplete)(const char*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -721,8 +719,6 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_str_free sqlite3_api->str_free
|
||||
#define sqlite3_carray_bind sqlite3_api->carray_bind
|
||||
#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2
|
||||
/* Version 3.54.0 and later */
|
||||
#define sqlite3_incomplete sqlite3_api->incomplete
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
@@ -1900,6 +1900,7 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
|
||||
#if VDBE_DISPLAY_P4
|
||||
/*
|
||||
** Compute a string that describes the P4 parameter for an opcode.
|
||||
** Use zTemp for any required temporary buffer space.
|
||||
*/
|
||||
char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
|
||||
char *zP4 = 0;
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
|
||||
** If the ONEPASS optimization is used (if this routine returns true)
|
||||
** then also write the indices of open cursors used by ONEPASS
|
||||
** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
|
||||
** table and aiCur[1] gets the cursor used by an auxiliary index.
|
||||
** table and iaCur[1] gets the cursor used by an auxiliary index.
|
||||
** Either value may be -1, indicating that cursor is not used.
|
||||
** Any cursors returned will have been opened for writing.
|
||||
**
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
void *p = 0;
|
||||
#ifdef SQLITE_OMIT_AUTOINIT
|
||||
sqlite3_initialize();
|
||||
#endif
|
||||
p = sqlite3_malloc(32);
|
||||
if( !p ) return 1;
|
||||
sqlite3_free(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "sqlite3.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
const char *zExpect = "2023.000";
|
||||
char szBuffer[32];
|
||||
double val = 2023.0;
|
||||
#ifdef SQLITE_OMIT_AUTOINIT
|
||||
sqlite3_initialize();
|
||||
#endif
|
||||
sqlite3_snprintf(17, szBuffer, "%.3f", val);
|
||||
printf("size 17: '%s'\n", szBuffer);
|
||||
if( sqlite3_stricmp(zExpect, szBuffer) ) return 1;
|
||||
sqlite3_snprintf(16, szBuffer, "%.3f", val);
|
||||
printf("size 16: '%s'\n", szBuffer);
|
||||
if( sqlite3_stricmp(zExpect, szBuffer) ) return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -882,6 +882,10 @@ int main(int argc, char **argv){
|
||||
int nChgset;
|
||||
int bVerbose = 0;
|
||||
|
||||
#ifdef SQLITE_OMIT_AUTOINIT
|
||||
sqlite3_initialize();
|
||||
#endif
|
||||
|
||||
if( argc<2 ){
|
||||
fprintf(stderr, "%s", zHelp);
|
||||
exit(1);
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
#!sqlite3
|
||||
#
|
||||
# 2026-04-11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests for the .prompt command and prompt rendering.
|
||||
#
|
||||
# ./sqlite3 test/shell-prompt.sql
|
||||
#
|
||||
|
||||
.testcase setup
|
||||
.open -new test.db
|
||||
.mode list -quote off -escape ascii
|
||||
.prompt --hard-reset
|
||||
.check ''
|
||||
|
||||
.testcase 100
|
||||
.prompt
|
||||
.check ''
|
||||
|
||||
.testcase 110
|
||||
.prompt --show
|
||||
.check <<END
|
||||
Main prompt: 'SQLite /f> '
|
||||
Continuation: '/B.../H> '
|
||||
END
|
||||
.testcase 111
|
||||
.prompt 'abc> ' '123> ' -show
|
||||
.check <<END
|
||||
Main prompt: 'abc> '
|
||||
Continuation: '123> '
|
||||
END
|
||||
.testcase 112
|
||||
.prompt -- --first --second
|
||||
.prompt --show
|
||||
.check <<END
|
||||
Main prompt: '--first'
|
||||
Continuation: '--second'
|
||||
END
|
||||
.testcase 113
|
||||
.prompt --reset --show
|
||||
.check <<END
|
||||
Main prompt: 'SQLite /f> '
|
||||
Continuation: '/B.../H> '
|
||||
END
|
||||
|
||||
.testcase 120 --error-prefix ERROR:
|
||||
.prompt show
|
||||
.check <<END
|
||||
ERROR: .prompt show
|
||||
ERROR: ^--- use quotes around the prompt string
|
||||
END
|
||||
|
||||
.testcase 121
|
||||
.prompt 'show'
|
||||
.check ''
|
||||
.testcase 122
|
||||
.prompt --show
|
||||
.check <<END
|
||||
Main prompt: 'show'
|
||||
Continuation: '/B.../H> '
|
||||
END
|
||||
|
||||
.testcase 130
|
||||
.prompt --reset
|
||||
.help prompt
|
||||
.check <<END
|
||||
.prompt MAIN CONTINUE Replace the standard prompts
|
||||
--hard-reset Unset SQLITE_PS1/2 and then --reset
|
||||
--reset Revert to default prompts
|
||||
--show Show the current prompt strings
|
||||
-- No more options. Subsequent args are prompts
|
||||
END
|
||||
|
||||
.testcase 140 --error-prefix ERROR:
|
||||
.prompt --xyz
|
||||
.check <<END
|
||||
ERROR: .prompt --xyz
|
||||
ERROR: ^--- unknown option
|
||||
END
|
||||
|
||||
|
||||
.testcase 1000
|
||||
SELECT shell_prompt_test(NULL);
|
||||
.check 'SQLite test.db> ';
|
||||
.testcase 1001
|
||||
SELECT shell_prompt_test(NULL,'SELECT');
|
||||
.check ' ...;> ';
|
||||
.testcase 1002
|
||||
SELECT shell_prompt_test(NULL,'SELECT ((("');
|
||||
.check ' ...")));> ';
|
||||
.testcase 1003
|
||||
SELECT shell_prompt_test(NULL,'SELECT ((()[');
|
||||
.check ' ...]));> ';
|
||||
.testcase 1004
|
||||
SELECT shell_prompt_test(NULL,'SELECT ''');
|
||||
.check " ...';> ";
|
||||
.testcase 1005
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN');
|
||||
.check " ...;END;> ";
|
||||
.testcase 1006
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((([');
|
||||
.check " ...])));END;> ";
|
||||
.testcase 1007
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((/*a(((''bc');
|
||||
.check " ...*/));END;> ";
|
||||
.testcase 1008
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;');
|
||||
.check " ...END;> ";
|
||||
|
||||
.testcase 2000
|
||||
.prompt 'SQLite/x-txn$/:>/; '
|
||||
SELECT shell_prompt_test(NULL);
|
||||
.check 'SQLite> ';
|
||||
.testcase 2001
|
||||
BEGIN;
|
||||
SELECT shell_prompt_test(NULL);
|
||||
.check 'SQLite-txn$ ';
|
||||
.testcase 2002
|
||||
ROLLBACK;
|
||||
SELECT shell_prompt_test(NULL);
|
||||
.check 'SQLite> ';
|
||||
.testcase 2003
|
||||
.prompt -- '--show '
|
||||
SELECT shell_prompt_test(NULL);
|
||||
.check '--show ';
|
||||
.testcase 2004
|
||||
.prompt --reset
|
||||
SELECT shell_prompt_test(NULL);
|
||||
.check 'SQLite test.db> ';
|
||||
|
||||
.testcase
|
||||
+1
-2
@@ -548,8 +548,7 @@ do_test shell1-3.17.3 {
|
||||
do_test shell1-3.17.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".prompt FOO BAR BAD"
|
||||
} {1 {line 1: .prompt FOO BAR BAD
|
||||
line 1: ^--- extra argument}}
|
||||
} {0 {}}
|
||||
|
||||
# .quit Exit this program
|
||||
do_test shell1-3.18.1 {
|
||||
|
||||
@@ -49,8 +49,5 @@ ifcapable vtab {
|
||||
do_clitest intck01.sql
|
||||
}
|
||||
do_clitest fptest01.sql
|
||||
unset -nocomplain ::env(SQLITE_PS1)
|
||||
unset -nocomplain ::env(SQLITE_PS2)
|
||||
do_clitest shell-prompt.sql
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1298,6 +1298,57 @@ proc add_build_job {buildname target {postcmd ""} {depid ""}} {
|
||||
list $id [file normalize $dirname] $buildname
|
||||
}
|
||||
|
||||
# Add jobs to build and run all the *.c files in $testdir/c/ for build
|
||||
# configuration $buildname.
|
||||
#
|
||||
proc add_c_jobs {buildname} {
|
||||
global TRG
|
||||
|
||||
set dir [file join $::testdir c]
|
||||
|
||||
# One job to build the sqlite3.o file for this configuration. Each
|
||||
# individual "c" job will copy this sqlite3.o into its working directory
|
||||
# so that it doesn't have to build it separately every time.
|
||||
#
|
||||
set obj sqlite3.o
|
||||
if {$TRG(platform)=="win"} { set obj sqlite3.lo }
|
||||
set B [add_build_job $buildname $obj]
|
||||
foreach {bldid blddir dummy} $B {}
|
||||
|
||||
# One job for each C file.
|
||||
#
|
||||
foreach f [glob -nocomplain $dir/*.c] {
|
||||
set prg [string range [file tail $f] 0 end-2]
|
||||
|
||||
set cmd ""
|
||||
if {$TRG(platform)=="win"} {
|
||||
foreach cp {sqlite3.lo *.h *.c} {
|
||||
append cmd "copy [file nativename [file join $blddir $cp]] .\n"
|
||||
}
|
||||
append cmd "SET AUXTEST=$prg\n"
|
||||
set prg "${prg}.exe"
|
||||
append cmd "$TRG(makecmd) $prg\n"
|
||||
append cmd ".\\$prg\n"
|
||||
} else {
|
||||
set cmd "set -e\n"
|
||||
foreach cp {sqlite3.c sqlite3.h sqlite3.o .target_source src-verify} {
|
||||
append cmd "cp [file join $blddir $cp] .\n"
|
||||
}
|
||||
append cmd "AUXTEST=$prg $TRG(makecmd) $prg\n"
|
||||
append cmd "./$prg\n"
|
||||
}
|
||||
|
||||
set id [add_job \
|
||||
-displaytype tcl \
|
||||
-displayname "$prg ($buildname)" \
|
||||
-build $buildname \
|
||||
-cmd $cmd \
|
||||
-depid $bldid \
|
||||
-priority 3
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
proc add_shell_build_job {buildname dirname depid} {
|
||||
global TRG
|
||||
|
||||
@@ -1545,6 +1596,8 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
|
||||
}
|
||||
}
|
||||
|
||||
add_c_jobs $b
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ namespace eval trd {
|
||||
-DSQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
-DSQLITE_THREADSAFE
|
||||
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
|
||||
-DSQLITE_OMIT_AUTOINIT=1
|
||||
}
|
||||
set build(Secure-Delete) {
|
||||
-O2
|
||||
|
||||
Reference in New Issue
Block a user