Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b4d42c6702 | |||
| 3ed7926e2f | |||
| 8923a68c5f | |||
| c94c21d0a6 | |||
| fb7c642990 | |||
| 2bc658c387 | |||
| f02745088c | |||
| 596008f078 | |||
| 1c9e8ca88b | |||
| c70fbd39f9 | |||
| 9db9f18985 | |||
| f107c52d4c | |||
| 7509c6351e | |||
| 57e46429fe | |||
| a9c2e08087 | |||
| 7f1f4c803d | |||
| bd13573a96 | |||
| 0cadeecf6f | |||
| ad52288e0d | |||
| d5f0e01593 | |||
| 3e663bd8c7 | |||
| 97901bbd69 | |||
| c549e28c67 | |||
| 90dae0d01d | |||
| 0a0a52ae93 | |||
| e1d4680fdd | |||
| 532e506d18 | |||
| c9bed48c3c | |||
| 6b4eb6725f | |||
| 6176034151 | |||
| 7471b5d6c0 | |||
| 1fc7341ad2 | |||
| 6af10b0efd | |||
| 70d1e3e75e | |||
| 74006fdcdb | |||
| 4b9f9d6794 | |||
| 39b2fe7e5b | |||
| 01ec60bb87 | |||
| e2dbd0a578 | |||
| df7b22790e | |||
| 50811f74e0 | |||
| d7bf8233ff | |||
| 455486bbc4 | |||
| ba9092e228 | |||
| 67d4e0226f | |||
| 323b3fc121 | |||
| 78279e2550 | |||
| 4e4962f6b3 | |||
| ed95a9d103 | |||
| e791e7c7a0 | |||
| 2545d9c201 | |||
| 2a07c6de2c | |||
| 68b07ddd41 | |||
| 4b69e7704b | |||
| e17ab401f0 | |||
| 57ee077c5e | |||
| c7edd22456 | |||
| 8606a52934 | |||
| 5c6404aa77 | |||
| 429369f4aa | |||
| 9529894a29 | |||
| c4c47a49a8 | |||
| ee7f6f29fc | |||
| c3b52dff53 | |||
| 30af54043e | |||
| 4ebed2a4e5 | |||
| 532ed30ab2 | |||
| 5e99eeb3d8 | |||
| d3abfd77f5 | |||
| 63984b6ab7 | |||
| 93082e5589 | |||
| f6b807a022 | |||
| 8c6a6b85db | |||
| 9f76fb019e | |||
| 29997b4731 | |||
| f0c8e27670 | |||
| d6c985ad0b | |||
| 1696740fdc | |||
| 2cefd5954a | |||
| 8895c50403 | |||
| a2116f86b0 | |||
| 1e472f2d32 | |||
| e3dbf75160 | |||
| ade9289540 | |||
| dfba4eb34a | |||
| b57d2a5a51 | |||
| 84c1079220 | |||
| c8d866294b | |||
| f0baddb205 | |||
| ec2ea68d1f | |||
| c71e6dd054 | |||
| 9efde40a5d | |||
| afef1f2923 | |||
| 09f37099a7 | |||
| 846fbd6653 | |||
| 1b14a925dc | |||
| 526acc1834 | |||
| d962afef2d | |||
| 839433d457 | |||
| 395ac6c1bc | |||
| e9d0bc6b68 | |||
| 483f0ef13c | |||
| ab6a63ec67 | |||
| 57ed7f322f | |||
| 34c2c8dc47 | |||
| 3f9df1f5fb | |||
| 2eeac123c8 | |||
| 64a123a216 | |||
| a10e79d91a | |||
| 6e93d28950 | |||
| 008395614a | |||
| d20673a95f | |||
| f02d100e08 | |||
| 4c8f0621fd | |||
| dd1e2c39bc | |||
| 6abc21cfb8 | |||
| 20079bb358 | |||
| 3d6fa49c54 | |||
| 4df365e5a7 | |||
| 9d8bf6f04a | |||
| c0026ff7a6 | |||
| 1e3f888acf | |||
| 2d4dfbccdc | |||
| 6142310e08 | |||
| 42ae7e7f34 | |||
| 57cf5c2dfc | |||
| a212476ad2 | |||
| 0523cfda5a | |||
| d08caad3a5 | |||
| bc68ec78de | |||
| 28456958ca | |||
| 3b27ffa534 | |||
| fc2c730c87 | |||
| cd28797117 | |||
| c8b130f255 | |||
| 7a0a0a22e7 | |||
| 504cfd5ec7 | |||
| 9d950aa13b | |||
| b709ba8108 | |||
| 01e1be854b | |||
| 70868a5ae3 | |||
| d0065c8118 | |||
| bd574dbaee | |||
| 7632922625 | |||
| 49998a6d25 | |||
| 92c435cda7 | |||
| 35f8abcfd0 | |||
| 1a315c0d51 | |||
| 3a8d38ffc0 | |||
| 693b15ac83 | |||
| 8cdc2abf07 | |||
| 931fa90d74 | |||
| eb9a6a95ca | |||
| b37bf0b8b4 | |||
| 850104bbad | |||
| 6a6ebb0d06 | |||
| 30b824e432 | |||
| 3944e70677 | |||
| df0e915ad2 | |||
| b0d9039c8c | |||
| f1cc3c4be5 | |||
| 9a8732e44b | |||
| 939930db1e |
@@ -1766,6 +1766,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\analyze.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base64.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\base85.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\completion.c
|
||||
@@ -2342,6 +2343,7 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\intck\sqlite3intck.c \
|
||||
$(TOP)\ext\intck\sqlite3intck.h \
|
||||
$(TOP)\ext\misc\analyze.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\base64.c \
|
||||
$(TOP)\ext\misc\base85.c \
|
||||
@@ -2741,6 +2743,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 \
|
||||
@@ -2937,4 +2942,5 @@ clean:
|
||||
del /Q fts5.* fts5parse.* 2>NUL
|
||||
del /q src-verify.exe 2>NUL
|
||||
del /q jimsh.exe jimsh0.exe 2>NUL
|
||||
-$(TCLSH_CMD) test/testrunner.tcl clean
|
||||
# <</mark>>
|
||||
|
||||
@@ -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 the whatever versions
|
||||
of SQLite you like. Some examples:
|
||||
you can do fast, bandwidth-efficient updates to whatever versions of SQLite you
|
||||
like. Some examples:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
|
||||
+1657
-972
File diff suppressed because it is too large
Load Diff
@@ -2042,7 +2042,7 @@ proc sqlite-check-tcl {} {
|
||||
}
|
||||
}
|
||||
if {![file-isexec $with_tclsh]} {
|
||||
proj-warn "Cannot find a usable tclsh (tried: $tryThese)
|
||||
proj-warn "Cannot find a usable tclsh (tried: $tryThese)"
|
||||
}
|
||||
}
|
||||
define TCLSH_CMD $with_tclsh
|
||||
|
||||
+6
-1
@@ -33,7 +33,7 @@
|
||||
The testrunner.tcl program is a Tcl script used to run multiple SQLite
|
||||
tests in parallel, thus reducing testing time on multi-core machines.
|
||||
The testrunner.tcl supports running tests that based on `testfixture`,
|
||||
`sqlite3`, and `fuzzcheck`.
|
||||
`sqlite3`, `fuzzcheck`, and C programs found in test/c.
|
||||
|
||||
<a name="runtr"></a>
|
||||
## 1.1 Running testrunner.tcl
|
||||
@@ -59,11 +59,16 @@ up front.
|
||||
The standard Makefiles for SQLite include targets that invoke
|
||||
testrunner.tcl. So the following commands also run testrunner.tcl:
|
||||
|
||||
* `make test`
|
||||
* `make devtest`
|
||||
* `make releasetest`
|
||||
* `make sdevtest`
|
||||
* `make testrunner`
|
||||
|
||||
Since SQLite 3.53.0, there is a "<tt>make.bat</tt>" script in the root
|
||||
of the source tree that causes the "make" command to work on Windows.
|
||||
There is no need to do something different using "nmake" on Windows.
|
||||
|
||||
<a name="outputs"></a>
|
||||
## 1.3 Outputs from testrunner.tcl
|
||||
|
||||
|
||||
@@ -712,9 +712,9 @@ static int fts5Porter_Ostar(char *zStem, int nStem){
|
||||
for(i=0; i<nStem; i++){
|
||||
bCons = !fts5PorterIsVowel(zStem[i], bCons);
|
||||
assert( bCons==0 || bCons==1 );
|
||||
mask = (mask << 1) + bCons;
|
||||
mask = ((mask << 1) + bCons) & 0x0007;
|
||||
}
|
||||
return ((mask & 0x0007)==0x0005);
|
||||
return (mask==0x0005);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,5 +65,13 @@ foreach {in out} $test_vocab {
|
||||
incr i
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE tbl USING fts5(t, tokenize='porter unicode61');
|
||||
INSERT INTO tbl VALUES(' andeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,836 @@
|
||||
/*
|
||||
** 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 ii;
|
||||
sqlite3_int64 pgsz;
|
||||
sqlite3_int64 nPage;
|
||||
sqlite3_int64 nPageInUse;
|
||||
sqlite3_int64 nFreeList;
|
||||
sqlite3_int64 nIndex;
|
||||
sqlite3_int64 nWORowid;
|
||||
Analysis s;
|
||||
sqlite3_uint64 r[2];
|
||||
|
||||
(void)argc;
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.db = sqlite3_context_db_handle(context);
|
||||
s.context = context;
|
||||
s.pOut = sqlite3_str_new(0);
|
||||
if( sqlite3_str_errcode(s.pOut) ){
|
||||
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 ){
|
||||
analysisReset(&s);
|
||||
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
|
||||
return;
|
||||
}
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
|
||||
" WHERE name=%Q COLLATE nocase",s.zSchema);
|
||||
if( rc || ii==0 ){
|
||||
analysisReset(&s);
|
||||
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
|
||||
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;
|
||||
|
||||
nPage = 0;
|
||||
rc = analysisSqlInt(&s, &nPage, "PRAGMA \"%w\".page_count", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( nPage<=0 ){
|
||||
/* Very brief reply for an empty database */
|
||||
analysisReset(&s);
|
||||
sqlite3_result_text(context, "empty database", -1, SQLITE_STATIC);
|
||||
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);
|
||||
analysisLine(&s, "Pages in the database", "%lld\n", nPage);
|
||||
|
||||
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);
|
||||
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
|
||||
if( rc ) return;
|
||||
if( ii==0 || nPage<=1 ){
|
||||
ii = 0;
|
||||
}else{
|
||||
double rPtrsPerPage = pgsz/5;
|
||||
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
|
||||
ii = (sqlite3_int64)ceil(rAvPage);
|
||||
}
|
||||
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
|
||||
analysisPercent(&s, (ii*100.0)/(double)nPage);
|
||||
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
|
||||
s.zSchema);
|
||||
if( rc ) return;
|
||||
analysisLine(&s, "Number of tables", "%lld\n", ii);
|
||||
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", ii - 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);
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
"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 - ii);
|
||||
analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
|
||||
analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
|
||||
ii = 0;
|
||||
rc = analysisSqlInt(&s, &ii,
|
||||
"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 ", ii);
|
||||
analysisPercent(&s, ii*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 nn = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
analysisPercent(&s, (nn*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 nn = sqlite3_column_int64(pStmt,1);
|
||||
analysisLine(&s, (const char*)sqlite3_column_text(pStmt,0), "%-11lld ", nn);
|
||||
analysisPercent(&s, (nn*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;
|
||||
}
|
||||
+1
-1
@@ -261,7 +261,7 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
|
||||
sqlite3_result_null(pCtx);
|
||||
return;
|
||||
}
|
||||
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+4 );
|
||||
z = sqlite3_malloc64( (sqlite3_int64)p->nDigit+8 );
|
||||
if( z==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return;
|
||||
|
||||
+62
-9
@@ -97,8 +97,6 @@ SQLITE_EXTENSION_INIT1
|
||||
# define STRUCT_STAT struct _stat
|
||||
# define chmod(path,mode) fileio_chmod(path,mode)
|
||||
# define mkdir(path,mode) fileio_mkdir(path)
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
@@ -125,13 +123,69 @@ SQLITE_EXTENSION_INIT1
|
||||
#define FSDIR_COLUMN_PATH 5 /* Path to top of search */
|
||||
#define FSDIR_COLUMN_DIR 6 /* Path is relative to this directory */
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
** Convert a UTF-8 string to Microsoft Unicode.
|
||||
**
|
||||
** Space to hold the returned string is obtained from sqlite3_malloc().
|
||||
*/
|
||||
static wchar_t *winUtf8To16(const char *zText){
|
||||
int nChar;
|
||||
wchar_t *zWideText;
|
||||
|
||||
nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
|
||||
if( nChar==0 ){
|
||||
return 0;
|
||||
}
|
||||
zWideText = sqlite3_malloc64(nChar*sizeof(WCHAR) );
|
||||
if( zWideText==0 ){
|
||||
return 0;
|
||||
}
|
||||
nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
|
||||
nChar);
|
||||
if( nChar==0 ){
|
||||
sqlite3_free(zWideText);
|
||||
zWideText = 0;
|
||||
}
|
||||
return zWideText;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
** Convert a Microsoft Unicode string to UTF-8.
|
||||
**
|
||||
** Space to hold the returned string is obtained from sqlite3_malloc().
|
||||
*/
|
||||
static char *winUtf16To8(wchar_t *zWideText){
|
||||
int nByte;
|
||||
char *zText;
|
||||
|
||||
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
|
||||
if( nByte == 0 ){
|
||||
return 0;
|
||||
}
|
||||
zText = sqlite3_malloc64( nByte );
|
||||
if( zText==0 ){
|
||||
return 0;
|
||||
}
|
||||
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
|
||||
0, 0);
|
||||
if( nByte == 0 ){
|
||||
sqlite3_free(zText);
|
||||
zText = 0;
|
||||
}
|
||||
return zText;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
** UTF8 chmod() function for Windows
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
static int fileio_chmod(const char *zPath, int pmode){
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
wchar_t *b1 = winUtf8To16(zPath);
|
||||
if( b1==0 ) return -1;
|
||||
rc = _wchmod(b1, pmode);
|
||||
sqlite3_free(b1);
|
||||
@@ -145,7 +199,7 @@ static int fileio_chmod(const char *zPath, int pmode){
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
static int fileio_mkdir(const char *zPath){
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
wchar_t *b1 = winUtf8To16(zPath);
|
||||
if( b1==0 ) return -1;
|
||||
rc = _wmkdir(b1);
|
||||
sqlite3_free(b1);
|
||||
@@ -272,7 +326,7 @@ static int fileStat(
|
||||
){
|
||||
#if defined(_WIN32)
|
||||
int rc;
|
||||
wchar_t *b1 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
wchar_t *b1 = winUtf8To16(zPath);
|
||||
if( b1==0 ) return 1;
|
||||
rc = _wstat(b1, pStatBuf);
|
||||
if( rc==0 ){
|
||||
@@ -425,14 +479,13 @@ static int writeFile(
|
||||
LONGLONG intervals;
|
||||
HANDLE hFile;
|
||||
LPWSTR zUnicodeName;
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
||||
|
||||
GetSystemTime(¤tTime);
|
||||
SystemTimeToFileTime(¤tTime, &lastAccess);
|
||||
intervals = (mtime*10000000) + 116444736000000000;
|
||||
lastWrite.dwLowDateTime = (DWORD)intervals;
|
||||
lastWrite.dwHighDateTime = intervals >> 32;
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
|
||||
zUnicodeName = winUtf8To16(zFile);
|
||||
if( zUnicodeName==0 ){
|
||||
return 1;
|
||||
}
|
||||
@@ -1090,12 +1143,12 @@ static char *portable_realpath(const char *zPath){
|
||||
|
||||
if( zPath==0 ) return 0;
|
||||
|
||||
zPath16 = sqlite3_win32_utf8_to_unicode(zPath);
|
||||
zPath16 = winUtf8To16(zPath);
|
||||
if( zPath16==0 ) return 0;
|
||||
z = _wfullpath(NULL, zPath16, 0);
|
||||
sqlite3_free(zPath16);
|
||||
if( z ){
|
||||
zOut = sqlite3_win32_unicode_to_utf8(z);
|
||||
zOut = winUtf16To8(z);
|
||||
free(z);
|
||||
}
|
||||
return zOut;
|
||||
|
||||
+36
-21
@@ -428,7 +428,6 @@ static void qrfEqpStats(Qrf *p){
|
||||
if( nRow>=0 ){
|
||||
if( nSp ) sqlite3_str_appendchar(pStats, nSp, ' ');
|
||||
qrfApproxInt64(pStats, nRow);
|
||||
nSp = 2;
|
||||
if( p->spec.eStyle==QRF_STYLE_StatsEst ){
|
||||
sqlite3_str_appendf(pStats, " ");
|
||||
qrfApproxInt64(pStats, (i64)rEstCum);
|
||||
@@ -718,19 +717,16 @@ static int qrfDisplayWidth(const char *zIn, sqlite3_int64 nByte, int *pnNL){
|
||||
}
|
||||
|
||||
/*
|
||||
** Escape the input string if it is needed and in accordance with
|
||||
** eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
|
||||
** Escape the text starting at byte iStart of pStr, if needed, using the
|
||||
** escape encoding of eEsc, which is either QRF_ESC_Ascii or QRF_ESC_Symbol.
|
||||
** The pStr string is modified appropriately.
|
||||
**
|
||||
** Escaping is needed if the string contains any control characters
|
||||
** other than \t, \n, and \r\n
|
||||
**
|
||||
** If no escaping is needed (the common case) then set *ppOut to NULL
|
||||
** and return 0. If escaping is needed, write the escaped string into
|
||||
** memory obtained from sqlite3_malloc64() and make *ppOut point to that
|
||||
** memory and return 0. If an error occurs, return non-zero.
|
||||
**
|
||||
** The caller is responsible for freeing *ppFree if it is non-NULL in order
|
||||
** to reclaim memory.
|
||||
** If no escaping is needed (the common case) then pStr is unchanged.
|
||||
** If escaping is required, then pStr is expanded and modified to hold
|
||||
** an escaped representation of the text.
|
||||
*/
|
||||
static void qrfEscape(
|
||||
int eEsc, /* QRF_ESC_Ascii or QRF_ESC_Symbol */
|
||||
@@ -738,20 +734,22 @@ static void qrfEscape(
|
||||
int iStart /* Begin escapding on this byte of pStr */
|
||||
){
|
||||
sqlite3_int64 i, j; /* Loop counters */
|
||||
sqlite3_int64 sz; /* Size of the string prior to escaping */
|
||||
sqlite3_int64 nCtrl = 0;/* Number of control characters to escape */
|
||||
unsigned char *zIn; /* Text to be escaped */
|
||||
unsigned int nIn; /* Bytes of text to be escaped */
|
||||
unsigned char c; /* A single character of the text */
|
||||
unsigned char *zOut; /* Where to write the results */
|
||||
|
||||
/* Find the text to be escaped */
|
||||
zIn = (unsigned char*)sqlite3_str_value(pStr);
|
||||
nIn = sqlite3_str_length(pStr);
|
||||
if( zIn==0 ) return;
|
||||
zIn += iStart;
|
||||
nIn -= iStart;
|
||||
|
||||
/* Count the control characters */
|
||||
for(i=0; (c = zIn[i])!=0; i++){
|
||||
if( c<=0x1f
|
||||
for(i=0; i<nIn; i++){
|
||||
if( (c = zIn[i])<=0x1f
|
||||
&& c!='\t'
|
||||
&& c!='\n'
|
||||
&& (c!='\r' || zIn[i+1]!='\n')
|
||||
@@ -763,18 +761,17 @@ static void qrfEscape(
|
||||
|
||||
/* Make space to hold the escapes. Copy the original text to the end
|
||||
** of the available space. */
|
||||
sz = sqlite3_str_length(pStr) - iStart;
|
||||
if( eEsc==QRF_ESC_Symbol ) nCtrl *= 2;
|
||||
sqlite3_str_appendchar(pStr, nCtrl, ' ');
|
||||
zOut = (unsigned char*)sqlite3_str_value(pStr);
|
||||
if( zOut==0 ) return;
|
||||
zOut += iStart;
|
||||
zIn = zOut + nCtrl;
|
||||
memmove(zIn,zOut,sz);
|
||||
memmove(zIn,zOut,nIn);
|
||||
|
||||
/* Convert the control characters */
|
||||
for(i=j=0; (c = zIn[i])!=0; i++){
|
||||
if( c>0x1f
|
||||
for(i=j=0; i<nIn; i++){
|
||||
if( (c = zIn[i])>0x1f
|
||||
|| c=='\t'
|
||||
|| c=='\n'
|
||||
|| (c=='\r' && zIn[i+1]=='\n')
|
||||
@@ -786,6 +783,7 @@ static void qrfEscape(
|
||||
j += i;
|
||||
}
|
||||
zIn += i+1;
|
||||
nIn -= i+1;
|
||||
i = -1;
|
||||
if( eEsc==QRF_ESC_Symbol ){
|
||||
zOut[j++] = 0xe2;
|
||||
@@ -1188,8 +1186,22 @@ static void qrfRenderValue(Qrf *p, sqlite3_str *pOut, int iCol){
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const char *zTxt = (const char*)sqlite3_column_text(p->pStmt,iCol);
|
||||
qrfEncodeText(p, pOut, zTxt);
|
||||
const void *pBlob = sqlite3_column_blob(p->pStmt,iCol);
|
||||
int nBlob = sqlite3_column_bytes(p->pStmt,iCol);
|
||||
int rc;
|
||||
qrfWrite(p);
|
||||
if( nBlob==0 ){
|
||||
/* no-op */
|
||||
}else if( p->spec.eEsc==QRF_ESC_Off ){
|
||||
rc = p->spec.xWrite(p->spec.pWriteArg,pBlob,nBlob);
|
||||
if( rc ){
|
||||
qrfError(p, rc, "Failed to write %d bytes of BLOB output", nBlob);
|
||||
}
|
||||
}else{
|
||||
sqlite3_str_append(pOut, pBlob, nBlob);
|
||||
qrfEscape(p->spec.eEsc, pOut, 0);
|
||||
qrfWrite(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2801,7 +2813,8 @@ qrf_reinit:
|
||||
case QRF_STYLE_Eqp: {
|
||||
int expMode = sqlite3_stmt_isexplain(p->pStmt);
|
||||
if( expMode!=2 ){
|
||||
sqlite3_stmt_explain(p->pStmt, 2);
|
||||
int rc = sqlite3_stmt_explain(p->pStmt, 2);
|
||||
if( rc ){ qrfError(p, SQLITE_ERROR, sqlite3_errstr(rc)); }
|
||||
p->expMode = expMode+1;
|
||||
}
|
||||
break;
|
||||
@@ -2809,7 +2822,8 @@ qrf_reinit:
|
||||
case QRF_STYLE_Explain: {
|
||||
int expMode = sqlite3_stmt_isexplain(p->pStmt);
|
||||
if( expMode!=1 ){
|
||||
sqlite3_stmt_explain(p->pStmt, 1);
|
||||
int rc = sqlite3_stmt_explain(p->pStmt, 1);
|
||||
if( rc ){ qrfError(p, SQLITE_ERROR, sqlite3_errstr(rc)); }
|
||||
p->expMode = expMode+1;
|
||||
}
|
||||
break;
|
||||
@@ -2968,6 +2982,7 @@ int sqlite3_format_query_result(
|
||||
|
||||
if( pStmt==0 ) return SQLITE_OK; /* No-op */
|
||||
if( pSpec==0 ) return SQLITE_MISUSE;
|
||||
if( sqlite3_stmt_busy(pStmt) ) return SQLITE_BUSY;
|
||||
qrfInitialize(&qrf, pStmt, pSpec, pzErr);
|
||||
switch( qrf.spec.eStyle ){
|
||||
case QRF_STYLE_Box:
|
||||
|
||||
@@ -397,4 +397,65 @@ 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,7 +3655,12 @@ 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);
|
||||
p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg);
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, zSql);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
sqlite3_step(pStmt);
|
||||
rbuFinalize(p, pStmt);
|
||||
}
|
||||
}
|
||||
rbuFinalize(p, pSql);
|
||||
if( p->rc!=SQLITE_OK ) return;
|
||||
|
||||
@@ -532,18 +532,39 @@ static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Run a single SQL statement in zSql. If zSql contains two or more
|
||||
** SQL statements separated by ';', only the first is run.
|
||||
**
|
||||
** Return the sqlite3_finalizer() or sqlite3_prepare() result code
|
||||
** from running the zSql statement.
|
||||
*/
|
||||
static int recoverOneStmt(sqlite3 *db, const char *zSql){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc;
|
||||
if( zSql==0 ) return SQLITE_OK;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is a no-op if recover handle p already contains an error
|
||||
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this
|
||||
** case.
|
||||
**
|
||||
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
|
||||
** Or, if an error occurs, leave an error code and message in the recover
|
||||
** handle and return a copy of the error code.
|
||||
** Otherwise, execute a single SQL statment in zSql. Even if zSql contains
|
||||
** two or more SQL statements separated by ';', only execute the first one.
|
||||
** If successful, return SQLITE_OK. Or, if an error occurs, leave an error
|
||||
** code and message in the recover handle and return a copy of the error code.
|
||||
*/
|
||||
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
int rc = sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
int rc = recoverOneStmt(db, zSql);
|
||||
if( rc ){
|
||||
recoverDbError(p, db);
|
||||
}
|
||||
@@ -943,7 +964,8 @@ static void recoverTransferSettings(sqlite3_recover *p){
|
||||
}
|
||||
recoverFinalize(p, p1);
|
||||
}
|
||||
recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
|
||||
recoverExec(p, db2, "CREATE TABLE t1(a)");
|
||||
recoverExec(p, db2, "DROP TABLE t1");
|
||||
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
sqlite3 *db = p->dbOut;
|
||||
@@ -1025,12 +1047,12 @@ static int recoverOpenOutput(sqlite3_recover *p){
|
||||
static void recoverOpenRecovery(sqlite3_recover *p){
|
||||
char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
|
||||
recoverExec(p, p->dbOut, zSql);
|
||||
recoverExec(p, p->dbOut,
|
||||
"PRAGMA writable_schema = 1;"
|
||||
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);"
|
||||
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
|
||||
);
|
||||
sqlite3_free(zSql);
|
||||
recoverExec(p, p->dbOut, "PRAGMA writable_schema = 1");
|
||||
recoverExec(p, p->dbOut,
|
||||
"CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT)");
|
||||
recoverExec(p, p->dbOut,
|
||||
"CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql)");
|
||||
}
|
||||
|
||||
|
||||
@@ -1170,7 +1192,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
")"
|
||||
"SELECT rootpage, tbl, isVirtual, name, sql"
|
||||
" FROM dbschema "
|
||||
" WHERE tbl OR isIndex"
|
||||
" WHERE (tbl OR isIndex) AND sql GLOB 'CREATE *'"
|
||||
" ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
|
||||
);
|
||||
|
||||
@@ -1196,7 +1218,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
|
||||
zName, zName, zSql
|
||||
));
|
||||
}
|
||||
rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbOut, zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
recoverSqlCallback(p, zSql);
|
||||
if( bTable && !bVirtual ){
|
||||
@@ -1238,15 +1260,17 @@ static int recoverWriteSchema2(sqlite3_recover *p){
|
||||
p->bSlowIndexes ?
|
||||
"SELECT rootpage, sql FROM recovery.schema "
|
||||
" WHERE type!='table' AND type!='index'"
|
||||
" AND sql GLOB 'CREATE *'"
|
||||
:
|
||||
"SELECT rootpage, sql FROM recovery.schema "
|
||||
" WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
|
||||
" AND sql GLOB 'CREATE *'"
|
||||
);
|
||||
|
||||
if( pSelect ){
|
||||
while( sqlite3_step(pSelect)==SQLITE_ROW ){
|
||||
const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
|
||||
int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
|
||||
int rc = recoverOneStmt(p->dbOut, zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
recoverSqlCallback(p, zSql);
|
||||
}else if( rc!=SQLITE_ERROR ){
|
||||
@@ -2624,7 +2648,7 @@ static void recoverStep(sqlite3_recover *p){
|
||||
if( bUseWrapper ) recoverUninstallWrapper(p);
|
||||
}while( p->errCode==SQLITE_NOTADB
|
||||
&& (bUseWrapper--)
|
||||
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
|
||||
&& SQLITE_OK==recoverOneStmt(p->dbIn, "ROLLBACK")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2689,7 +2713,7 @@ static void recoverStep(sqlite3_recover *p){
|
||||
** database. Regardless of whether or not an error has occurred, make
|
||||
** an attempt to end the read transaction on the input database. */
|
||||
recoverExec(p, p->dbOut, "COMMIT");
|
||||
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbIn, "END");
|
||||
if( p->errCode==SQLITE_OK ) p->errCode = rc;
|
||||
|
||||
recoverSqlCallback(p, "PRAGMA writable_schema = off");
|
||||
@@ -2885,7 +2909,7 @@ int sqlite3_recover_finish(sqlite3_recover *p){
|
||||
}else{
|
||||
recoverFinalCleanup(p);
|
||||
if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
|
||||
rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
|
||||
rc = recoverOneStmt(p->dbIn, "END");
|
||||
if( p->errCode==SQLITE_OK ) p->errCode = rc;
|
||||
}
|
||||
rc = p->errCode;
|
||||
|
||||
@@ -259,6 +259,18 @@ foreach {tn type C2hex C3hex} {
|
||||
} {1 SQLITE_CORRUPT}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
set CSD 5402010074000900010000000000000001030441414141
|
||||
set CSI 5402010074001200010000000000000001063258585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858
|
||||
|
||||
do_test 7.0 {
|
||||
sqlite3changegroup grp
|
||||
grp add [db one {SELECT unhex($CSD)}]
|
||||
list [catch { grp add [db one {SELECT unhex($CSI)}] } msg] $msg
|
||||
} {1 SQLITE_CORRUPT}
|
||||
grp delete
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -638,10 +638,11 @@ static int sessionSerialLen(const u8 *a){
|
||||
int n;
|
||||
assert( a!=0 );
|
||||
e = *a;
|
||||
if( e==0 || e==0xFF ) return 1;
|
||||
if( e==SQLITE_NULL ) return 1;
|
||||
if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9;
|
||||
return sessionVarintGet(&a[1], &n) + 1 + n;
|
||||
if( e==SQLITE_TEXT || e==SQLITE_BLOB ){
|
||||
return sessionVarintGet(&a[1], &n) + 1 + n;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -664,17 +665,17 @@ static unsigned int sessionChangeHash(
|
||||
u8 *a = aRecord; /* Used to iterate through change record */
|
||||
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
int eType = *a;
|
||||
int isPK = pTab->abPK[i];
|
||||
if( bPkOnly && isPK==0 ) continue;
|
||||
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|
||||
|| eType==SQLITE_NULL || eType==0
|
||||
);
|
||||
|
||||
if( isPK ){
|
||||
a++;
|
||||
int eType = *a++;
|
||||
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_TEXT || eType==SQLITE_BLOB
|
||||
|| eType==SQLITE_NULL || eType==0
|
||||
);
|
||||
|
||||
h = sessionHashAppendType(h, eType);
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
h = sessionHashAppendI64(h, sessionGetI64(a));
|
||||
@@ -3702,9 +3703,11 @@ static int sessionChangesetBufferRecord(
|
||||
rc = sessionInputBuffer(pIn, nByte);
|
||||
}else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
nByte += 8;
|
||||
}else if( eType!=0 && eType!=SQLITE_NULL ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
if( (pIn->iNext+nByte)>pIn->nData ){
|
||||
if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
@@ -7050,7 +7053,7 @@ int sqlite3changegroup_change_text(
|
||||
const char *pVal,
|
||||
int nVal
|
||||
){
|
||||
int nText = nVal>=0 ? nVal : strlen(pVal);
|
||||
sqlite3_int64 nText = nVal>=0 ? nVal : strlen(pVal);
|
||||
sqlite3_int64 nByte = 1 + sessionVarintLen(nText) + nText;
|
||||
int rc = SQLITE_OK;
|
||||
SessionBuffer *pBuf = 0;
|
||||
|
||||
@@ -245,4 +245,5 @@ _fiddle_reset_db
|
||||
_fiddle_db_handle
|
||||
_fiddle_db_vfs
|
||||
_fiddle_export_db
|
||||
_fiddle_get_prompt
|
||||
//#/if fiddle
|
||||
|
||||
@@ -1099,20 +1099,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
return promiseResolve_(sqlite3);
|
||||
};
|
||||
const options = opfsUtil.options;
|
||||
let proxyUri = options.proxyUri +(
|
||||
//#if not target:es6-bundler-friendly
|
||||
const proxyUri = options.proxyUri +(
|
||||
(options.proxyUri.indexOf('?')<0) ? '?' : '&'
|
||||
)+'vfs='+vfsName;
|
||||
//sqlite3.config.error("proxyUri",options.proxyUri, (new Error()));
|
||||
//#/if
|
||||
const W = opfsVfs.worker =
|
||||
//#if target:es6-bundler-friendly
|
||||
(()=>{
|
||||
/* _Sigh_... */
|
||||
switch(vfsName){
|
||||
case 'opfs':
|
||||
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs", import.meta.url));
|
||||
case 'opfs-wl':
|
||||
return new Worker(new URL("sqlite3-opfs-async-proxy.js?vfs=opfs-wl", import.meta.url));
|
||||
}
|
||||
/* Discussion explaining this formulation:
|
||||
https://github.com/sqlite/sqlite-wasm/pull/159 */
|
||||
const url = new URL('sqlite3-opfs-async-proxy.js', import.meta.url);
|
||||
url.searchParams.set('vfs', vfsName);
|
||||
return new Worker(url.toString());
|
||||
})();
|
||||
//#elif target:es6-module
|
||||
new Worker(new URL(proxyUri, import.meta.url));
|
||||
|
||||
@@ -1559,18 +1559,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
only argument. On success, returns the result of the
|
||||
callback. Throws on error.
|
||||
|
||||
Note that transactions may not be nested, so this will throw if
|
||||
it is called recursively. For nested transactions, use the
|
||||
Transactions may not be nested, so this will throw if it is
|
||||
called recursively. For nested transactions, use the
|
||||
savepoint() method or manually manage SAVEPOINTs using exec().
|
||||
|
||||
If called with 2 arguments, the first must be a keyword which
|
||||
is legal immediately after a BEGIN statement, e.g. one of
|
||||
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE". Though the exact list
|
||||
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE", though the exact list
|
||||
of supported keywords is not hard-coded here, in order to be
|
||||
future-compatible, if the argument does not look like a single
|
||||
keyword then an exception is triggered with a description of
|
||||
the problem.
|
||||
*/
|
||||
*/
|
||||
transaction: function(/* [beginQualifier,] */callback){
|
||||
let opener = 'BEGIN';
|
||||
if(arguments.length>1){
|
||||
|
||||
@@ -1949,8 +1949,6 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
}/*changeset/preupdate additions*/
|
||||
|
||||
/**
|
||||
EXPERIMENTAL. For tentative addition in 3.53.0.
|
||||
|
||||
sqlite3_js_retry_busy(maxTimes,callback[,beforeRetry])
|
||||
|
||||
Calls the given _synchronous_ callback function. If that function
|
||||
@@ -1971,11 +1969,14 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap(
|
||||
(so it starts with 2, not 1). If it throws, the exception is
|
||||
handled as described above. Its result value is ignored.
|
||||
|
||||
To effectively retry "forever", pass a negative maxTimes value,
|
||||
with the caveat that there is no recovery from that unless the
|
||||
beforeRetry() can figure out when to throw.
|
||||
To effectively retry "forever", pass a huge maxTimes value such
|
||||
as Number.MAX_SAFE_INTEGER, with the caveat that there is no
|
||||
recovery from that unless the beforeRetry() can figure out when
|
||||
to throw.
|
||||
|
||||
TODO: an async variant of this.
|
||||
Added in 3.53.0.
|
||||
|
||||
TODO?: an async variant of this.
|
||||
*/
|
||||
capi.sqlite3_js_retry_busy = function(maxTimes, callback, beforeRetry){
|
||||
for(let n = 1; n <= maxTimes; ++n){
|
||||
|
||||
@@ -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 yet work with OPFS.");
|
||||
"features (e.g. upload) do not work with OPFS.");
|
||||
}
|
||||
stdout('\nEnter ".help" for usage hints.');
|
||||
return true;
|
||||
@@ -186,6 +186,7 @@
|
||||
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.");
|
||||
@@ -207,7 +208,8 @@
|
||||
wMsg('working','end');
|
||||
wMsg('wasm-info', {
|
||||
pointerSize: sqlite3.wasm.ptr.size,
|
||||
heapSize: sqlite3.wasm.heap8().byteLength
|
||||
heapSize: sqlite3.wasm.heap8().byteLength,
|
||||
prompt: f.getPrompt()
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -349,9 +349,10 @@
|
||||
SF.e.wasmInfo.innerText = 'WASM: '+(
|
||||
4===v.pointerSize ? 32 : 64
|
||||
)+'-bit'
|
||||
//+' heap size: '+Number(v.heapSize)
|
||||
+' heap: '+Number(v.heapSize)
|
||||
// Heap size is not changing even when loading a huge db?
|
||||
;
|
||||
SF.jqTerm?.set_prompt?.(v.prompt);
|
||||
});
|
||||
|
||||
/* querySelectorAll() proxy */
|
||||
@@ -865,8 +866,14 @@
|
||||
const jqeTerm = window.jQuery(SF.e.terminal).empty();
|
||||
SF.jqTerm = jqeTerm.terminal(SF.dbExec.bind(SF),{
|
||||
prompt: 'sqlite> ',
|
||||
greetings: false /* note that the docs incorrectly call this 'greeting' */
|
||||
greetings: false /* 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');
|
||||
});
|
||||
@@ -890,5 +897,6 @@
|
||||
SF.dbExec(urlParams.get('sql') || null);
|
||||
delete SF.ForceResizeKludge.$disabled;
|
||||
SF.ForceResizeKludge();
|
||||
globalThis.fiddle = SF;
|
||||
}/*onSFLoaded()*/;
|
||||
})();
|
||||
|
||||
@@ -322,8 +322,9 @@
|
||||
<h1>Usage Summary</h1>
|
||||
|
||||
<ul>
|
||||
<li class='hidden unhide-if-terminal-available'>In "terminal
|
||||
mode" it accepts input just like the CLI shell does.</li>
|
||||
<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>In split-view mode:
|
||||
<ul>
|
||||
<li>Input can be executed with either the Run
|
||||
|
||||
@@ -1021,11 +1021,15 @@ static void mk_fiddle(void){
|
||||
pf("\t@$(call b.call.wasm-strip,%s)\n", zBuildName);
|
||||
pf("\t@$(call b.strip-js-emcc-bindings,$(logtag.%s))\n",
|
||||
zBuildName);
|
||||
pf("\t@$(call b.cp,%s,$(dir.dout)/sqlite3-opfs-async-proxy.js,"
|
||||
"$(dir $@)"
|
||||
")\n", zBuildName);
|
||||
if( isDebug ){
|
||||
pf("\t@$(call b.cp,%s,"
|
||||
"$(dir.fiddle)/index.html "
|
||||
"$(dir.fiddle)/fiddle.js "
|
||||
"$(dir.fiddle)/fiddle-worker.js,"
|
||||
"$(dir.fiddle)/fiddle-worker.js "
|
||||
"$(dir.fiddle)/sqlite3-opfs-async-proxy.js,"
|
||||
"$(dir $@)"
|
||||
")\n",
|
||||
zBuildName);
|
||||
|
||||
@@ -982,6 +982,7 @@ FUZZCHECK_SRC = sqlite3.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
$(TOP)/test/vt02.c \
|
||||
$(TOP)/ext/misc/analyze.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
$(TOP)/ext/misc/completion.c \
|
||||
@@ -1678,7 +1679,8 @@ tclsqlite3.c: sqlite3.c tclsqlite-ex.c
|
||||
#
|
||||
# $(CFLAGS.tclextension) = CFLAGS for the tclextension* targets.
|
||||
#
|
||||
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAGS) $(OPTS)
|
||||
CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) \
|
||||
$(OPT_FEATURE_FLAGS) $(OPTS) $(CFLAGS.icu)
|
||||
#
|
||||
# Build the SQLite TCL extension in a way that make it compatible
|
||||
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
|
||||
@@ -1686,7 +1688,8 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
|
||||
#
|
||||
tclextension: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
|
||||
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
|
||||
|
||||
#
|
||||
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
|
||||
@@ -1694,7 +1697,8 @@ tclextension: tclsqlite3.c
|
||||
#
|
||||
tclextension-install: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
|
||||
--tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" \
|
||||
--extlibs "$(LDFLAGS.icu)" $(CFLAGS.tclextension)
|
||||
|
||||
#
|
||||
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
|
||||
@@ -2341,6 +2345,7 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
$(TOP)/ext/intck/sqlite3intck.h \
|
||||
$(TOP)/ext/misc/analyze.c \
|
||||
$(TOP)/ext/misc/appendvfs.c \
|
||||
$(TOP)/ext/misc/base64.c \
|
||||
$(TOP)/ext/misc/base85.c \
|
||||
@@ -2422,6 +2427,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
|
||||
#
|
||||
@@ -2505,7 +2514,7 @@ tidy:
|
||||
# Removes build products and test logs. Retains ./configure outputs.
|
||||
#
|
||||
clean: tidy
|
||||
rm -rf omittest* testrunner* testdir*
|
||||
rm -rf omittest* testrunner* testrun_* testdir*
|
||||
|
||||
#
|
||||
# Clean up everything. No exceptions. From an out-of-tree build which
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
C Make\suse\sof\sO_TMPFILE\sfor\smore\ssecure\stemporary\sfile\screation,\swhen\sthat\noption\sis\savailable.
|
||||
D 2026-04-09T14:12:09.859
|
||||
C When\susing\sthe\sOR-optimization\son\sa\sloop\screated\sby\sexists-to-join,\sdo\sthe\searly-exit\slogic\sfor\sthe\swhole\sloop,\snot\sfor\seach\sindividual\sOR\sbranch.\sPossible\sfix\sfor\sforum\spost\s[forum:c8b205720c\s|\sc8b205720c].
|
||||
D 2026-05-04T17:16:43.654
|
||||
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 92391304cf70f4c178b127aa83b88637abd28d1b83ede451616144037ea1d3dd
|
||||
F README.md f49fbd826941842e348242f3ab62f240c985ceafdf8fbe576abf4eb75317468c
|
||||
F VERSION 31435e19ded2aae3c1c67dacf06a995a37fd1b253baec5899b78d64cd29db4f7
|
||||
F Makefile.msc 6f4294982758b5eeeac740c1a263186c3fcb9ba51d1b48261e321bcb37a41dbb
|
||||
F README.md e4f1a030f813c2fafc898c66d4f10bff2c75eb1a8f504eb9ad9a5ef80e3ff814
|
||||
F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -44,10 +44,10 @@ 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 916bbdf8023fbda9937afae57d81a853d8c2ea00f2320aa27becbc33574f963d
|
||||
F autosetup/jimsh0.c 740dc8cbfaedaff1f27b54b32e0015b22fa6c1a439492b9795968d61e56bab75
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl ce301197f364f7ce2acabbbd84b43d19e917ec73653157ca134a06f32d322712
|
||||
F autosetup/sqlite-config.tcl 8fecce2838b7e7d990d161d08998034f3e3b0b2ddf4d7a99dbfafba9c902e302
|
||||
F autosetup/sqlite-config.tcl f67b868a320ff9f24af0fa74ba446a9735312dd5e69f8023a529600b08711421
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
|
||||
F autosetup/teaish/core.tcl e014dd95900c7f9a34e8e0f460f47e94841059827bce8b4c49668b0c7ae3f1a0
|
||||
@@ -63,7 +63,7 @@ F doc/jsonb.md acd77fc3a709f51242655ad7803510c886aa8304202fa9cf2abc5f5c4e9d7ae5
|
||||
F doc/lemon.html 2085fda0a90a94fe92159a79dccc5c30d5a2313524887a31659cd66162f17233
|
||||
F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
|
||||
F doc/tcl-extension-testing.md b88861804fc1eaf83249f8e206334189b61e150c360e1b80d0dcf91af82354f5
|
||||
F doc/testrunner.md daffa0ebbbe397a73537ae1b19b3124d489ce5f89dfe570781d1f1ef1809597c
|
||||
F doc/testrunner.md 3589f7914d36adaff6d108566e09b2c6166887bea00580e5343f8b43615ffe12
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
|
||||
F doc/vfs-shm.txt 1a55f3f0e7b6745931b117ba5c9df3640d7a0536f532ef0052563100f4416f86
|
||||
@@ -119,7 +119,7 @@ F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e0
|
||||
F ext/fts5/fts5_tcl.c 2be6cc14f9448f720fd4418339cd202961a0801ea9424cb3d9de946f8f5a051c
|
||||
F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
|
||||
F ext/fts5/fts5_test_tok.c 6021033bd4f4feffe8579efb6e1f58156ed462256bf99a2acdbd629246529204
|
||||
F ext/fts5/fts5_tokenize.c cfc16dde905552fe238c0403670852e75c0330ba508a9fb4836c1f596618561d
|
||||
F ext/fts5/fts5_tokenize.c 03fa928dffcf1445f973f0994c4d2732812e32b264f45c303732aa0e8bb8dea7
|
||||
F ext/fts5/fts5_unicode2.c 536a6dae41d16edadd6a6b58c56e2ebbb133f0dfe757562a2edbcdc9b8362e50
|
||||
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
|
||||
F ext/fts5/fts5_vocab.c bebee4aabcd056a44b3731166433cfdecf17ece750c08cb58733216222bd39e2
|
||||
@@ -227,7 +227,7 @@ F ext/fts5/test/fts5origintext6.test 09eb1347cb0dceaebbebf3d3e6bd5d24c7c1006efdd
|
||||
F ext/fts5/test/fts5phrase.test bb2554bb61d15f859678c96dc89a7de415cd5fc3b7b54c29b82a0d0ad138091c
|
||||
F ext/fts5/test/fts5plan.test f8b0d752a818059a934cdc96c0f77de058a67a0a57bb3a8181d28307ab5b1626
|
||||
F ext/fts5/test/fts5porter.test 15b514fac8690b58e99c330efe5bf5615bc43f2fae4a3cca3f923dbaff55a0c0
|
||||
F ext/fts5/test/fts5porter2.test 94f0e4351e2c99b4e74f1fae05a4ddf1cb5b926620a8c14554160d075ddc7a59
|
||||
F ext/fts5/test/fts5porter2.test 1dab0fe41342ebed32ca36a145de3e50be9093cb71e9f5250f6ebc589207982a
|
||||
F ext/fts5/test/fts5prefix.test c0b7842f1a2d830c0b146cd438a95ea4c5a25635719ed0d973ffe41907338b83
|
||||
F ext/fts5/test/fts5prefix2.test a5bb43b8a2687efafa7ac4e5ccff6812015cf8cf18e3086bb0eb3126f30fbbf6
|
||||
F ext/fts5/test/fts5query.test 0320a7a4b58a6e3e50ec8910b301649da90ace675001f9e0bf6392750ad4591d
|
||||
@@ -358,6 +358,7 @@ F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b6
|
||||
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
|
||||
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
|
||||
F ext/misc/amatch.c 8d237cc014b3736922c26a76a451050d244aa4980c47c531f368f817b1e77b49
|
||||
F ext/misc/analyze.c 77e0f45a44c13d66f30922db553072305521c0fb3a448b920e641fccd2498527
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
|
||||
@@ -371,10 +372,10 @@ F ext/misc/completion.c 3f5db28e88c3313103b2dd86d910a2944fd500c46754e473493968ce
|
||||
F ext/misc/compress.c 8191118b9b73e7796c961790db62d35d9b0fb724b045e005a5713dc9e0795565
|
||||
F ext/misc/csv.c 5e9d4dd749e762c144104c0f01db5bf4458735b19081ebe481a64e589a66687a
|
||||
F ext/misc/dbdump.c 678f1b9ae2317b4473f65d03132a2482c3f4b08920799ed80feedd2941a06680
|
||||
F ext/misc/decimal.c 23698283d9365ce66d54b5bb97c01e69b4aa7ac804f226f9117a0d42efd15a65
|
||||
F ext/misc/decimal.c 432e5b03a0e2a68a1846a9852a565a1b546ca9b295deda834e4653f0f5577daa
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 9670c8ff7b255eea7845abc5123a4958e74016c16990b10497e56380f91704b9
|
||||
F ext/misc/fileio.c e72033f987894ed821bf324a426ed462743399c274f1290dcb646349b6d7548f
|
||||
F ext/misc/fileio.c 936c0a7b3382a047d833ad33f62ba59a3847b79ea745bf529797cd344966fbb0
|
||||
F ext/misc/fossildelta.c 40add35db7f355d29ae856fe09043e66802fceff6f2551baccb28d794cadbc77
|
||||
F ext/misc/fuzzer.c decaca5a3479dfba69576cd41d4e17161eaf154a5438e12d316bbc5853571802
|
||||
F ext/misc/ieee754.c 2901d08a586d00a1d3c0fd89e03c57ee9e2b5f013b0daab9e49c7a48a9d5946b
|
||||
@@ -421,7 +422,7 @@ F ext/misc/zipfile.c 5a583b5e72b4d777dc9f845529e6bd185d58024b633aafc93588679c787
|
||||
F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee
|
||||
F ext/qrf/README.md 9e644615d7d7b77ef7e9db798765679e50c5ed12eda48bce21c9ef9eb4715e9d
|
||||
F ext/qrf/dev-notes.md e68a6d91ce4c7eb296ef2daadc2bb79c95c317ad15b9fafe40850c67b29c2430
|
||||
F ext/qrf/qrf.c 9bef1f01e0c33a8693a9a7c1b666b8dee1aa60b8bc880d562eb4dfff551a6009
|
||||
F ext/qrf/qrf.c 9bd4ad396e75a7905b1eb956ac53fd93f77942963c5ffac176ae39880368553b
|
||||
F ext/qrf/qrf.h fbb223ff5789b324b3e9c22e787e4c1f53e217cff7cc5a243164d4b2e8410f4b
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255
|
||||
@@ -463,11 +464,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 542561741ff2b262e3694bc6012b44694ee62c545845319a06f323783b15311e
|
||||
F ext/rbu/rbuvacuum.test e3585cfda220038e8186c583e9bd2aaa9eccd0a5c2e40ed861de3c987c93f68c
|
||||
F ext/rbu/rbuvacuum2.test 1a9bd41f127be2826de2a65204df9118525a8af8d16e61e6bc63ba3ac0010a23
|
||||
F ext/rbu/rbuvacuum3.test 3ce42695fdf21aaa3499e857d7d4253bc499ad759bcd6c9362042c13cd37d8de
|
||||
F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69eefaebb205
|
||||
F ext/rbu/sqlite3rbu.c e99400d29d029936075e27495b269a2dcdceae3cf8c86b1d0869b4af487be3ab
|
||||
F ext/rbu/sqlite3rbu.c 28246b647831409e84dfb8286fbeda55f1de89e934571509a23a67ada572d0c0
|
||||
F ext/rbu/sqlite3rbu.h e3a5bf21e09ca93ce4e8740e00d6a853e90a697968ec0ea98f40826938bdb68e
|
||||
F ext/rbu/test_rbu.c 8b6e64e486c28c41ef29f6f4ea6be7b3091958987812784904f5e903f6b56418
|
||||
F ext/recover/dbdata.c 10d3c56968a9af6853722a47280805ad1564714d79ea45ac6f7da14bb57fd137
|
||||
@@ -486,7 +487,7 @@ F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52
|
||||
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
|
||||
F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
|
||||
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
|
||||
F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
|
||||
F ext/recover/sqlite3recover.c dfbfca5a8e4909333e5aa3749bcffb5dd7e396de9541c338f8cc843b2e20217e
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
|
||||
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
|
||||
@@ -540,7 +541,7 @@ F ext/session/session8.test 326f3273abf9d5d2d7d559eee8f5994c4ea74a5d935562454605
|
||||
F ext/session/session9.test 0c4a8fbe7a5031f50855f020f3408e1f07fd7859f1daa1629eadcec3422072d6
|
||||
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
|
||||
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
|
||||
F ext/session/sessionC.test 2bd42225efdf5f5b1a20f75b672665bcd4f67e2a6d7ddf7420fe7bf523ba41f8
|
||||
F ext/session/sessionC.test de98b5e173fd86c79af0d0541534398d2ea75dc0d5d74a00103eb26151b76959
|
||||
F ext/session/sessionD.test 470ff917dc849e2eb78142ade63aaabd729d773833cff0ff01bca0eda68a21ce
|
||||
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
|
||||
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
|
||||
@@ -571,7 +572,7 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
|
||||
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
|
||||
F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
|
||||
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
|
||||
F ext/session/sqlite3session.c d5c91d5b07d2b8e860f2782ae23f7b44ce929280e00645418ee84a0fd14525b2
|
||||
F ext/session/sqlite3session.c a75ef1e361ad857518d75184366936beb752f3c2522895dc529c368642eab5a6
|
||||
F ext/session/sqlite3session.h 063e7bf7be2fff874456f452a224b5b3013b25682d108933b0351c93a1279b9c
|
||||
F ext/session/test_session.c 2a02a68b522e2f3d4a64b2a4733af54b0f3e500769aeccd5bcbdd440103db069
|
||||
F ext/wasm/GNUmakefile 68c750f173106d9d63f12c1edf1256c6f4bad9894b155da5db64322f4912de4b
|
||||
@@ -582,18 +583,18 @@ 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 de2ce128aebeff9ef4161cff7a0ff0089be866121bcb8941ad44a38a65f1d436
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.c-pp 189935d0106bca86661efc991ab13e1d5d6e1f55ec34dc7b5055a99321397edd
|
||||
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
|
||||
F ext/wasm/api/opfs-common-inline.c-pp.js 496ca858af09b7fef2efaece467960611d35f57254078424bcdeac42ded9e85d
|
||||
F ext/wasm/api/opfs-common-shared.c-pp.js d0bff21d34fa05a7eb975c4ee608165f96387332101cb05e976953c77434374d
|
||||
F ext/wasm/api/opfs-common-shared.c-pp.js 5b5880ced26977931a4fb33aafc6c71206fbee519e82abf9614898d8fa5ec241
|
||||
F ext/wasm/api/post-js-footer.js a50c1a2c4d008aede7b2aa1f18891a7ee71437c2f415b8aeb3db237ddce2935b
|
||||
F ext/wasm/api/post-js-header.js f35d2dcf1ab7f22a93d565f8e0b622a2934fc4e743edf3b708e4dd8140eeff55
|
||||
F ext/wasm/api/pre-js.c-pp.js d6bf82f83f60caa2904bddb95a29cb738b310f672d2796cdc5fe54463ab0d6cd
|
||||
F ext/wasm/api/sqlite3-api-glue.c-pp.js 31a721ada7225838a61310a9f3f797fa5275353f8e9b0ae769d85b437be061f5
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 5f203f5bb5d48a9e43ec51e791dc411c24dca825842bfb6a2d979d871bf8cfaf
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 4336f02ac24ba58e68e355adb9da2804a1eef15a4aee961fa813c7d812a56b54
|
||||
F ext/wasm/api/sqlite3-api-oo1.c-pp.js 35e4727010f15fd72ead0dd1eb4e3c2c9bb1cc60e51544cbdff1f7c14f209de2
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 29ca376ff5d5f189714cf10b2b93b136e91b06ec8616579b53b2af9dfb4796bf
|
||||
F ext/wasm/api/sqlite3-api-worker1.c-pp.js 1fa34e9b0e3b90a8898e4f700d7125e44c81877f182627bb8564b97989bc6e78
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 98d90255a12d02214db634e041c8e7f2f133d9361a8ebf000ba9c9af4c6761cc
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.c-pp.js 25e31482b04293a33d7599f1459eb552b3eb36ca10c02c816122d3308bf80cb2
|
||||
@@ -621,16 +622,16 @@ 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 6c72acac2d381480bc9f5eb538e3f2faf2c1f72dd4fcbd05d3b409818a9a8fd5
|
||||
F ext/wasm/fiddle/fiddle.js 84fd75967e0af8b69d3dd849818342227d0f81d13db92e0dcbc63649b31a4893
|
||||
F ext/wasm/fiddle/index.c-pp.html 02f063ef30b8124f311029855c4439e77bc6505d1bf65a163d88c064a63ee9d9
|
||||
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/index-dist.html db23748044e286773f2768eec287669501703b5d5f72755e8db73607dc54d290
|
||||
F ext/wasm/index.html 5bf6cf1b0a3c8b9f5f54d77f2219d7ae87a15162055ce308109c49b1dcab4239
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 4e2b797dc170851c9c530c3567679f4aa509eec0fab73b466d945b00b356574b
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 6aa90fa1a973d0ad10d077088bea163b241d8470c75eafdef87620a1de1dea41
|
||||
F ext/wasm/libcmpp.c 0e2cec7de7c9cbe7941e6a4dc0c123cec736578a3eeae7828ac18706acd3cea6
|
||||
F ext/wasm/mkdist.sh f8883b077a2ca47cf92e6f0ce305fbf72ca648c3501810125056c4b09c2d5554 x
|
||||
F ext/wasm/mkwasmbuilds.c d4479af2774a43104b819d9286961b7c09793ca39440e20191e693ceff21f911
|
||||
F ext/wasm/mkwasmbuilds.c 60706fb66db7f1e24d876e3cb2493484cfb27e7b103c7741c384505dd678769c
|
||||
F ext/wasm/module-symbols.html e54f42112e0aac2a31f850ab33e7f2630a2ea4f63496f484a12469a2501e07e2
|
||||
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
|
||||
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
|
||||
@@ -656,7 +657,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 bf77c630aeef4ed4b9270e1fd52c35147b529412c00b74ed6eb8aca3466763f6
|
||||
F main.mk d9cbbee974a8cd3999430130378878bd87b8c5754397a69ec322f4c9cc3e4e41
|
||||
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -667,52 +668,52 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
|
||||
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
|
||||
F src/alter.c fc36b19273ffe364aeb4d00ba04bda8798ad7a67fec7a035ee8ee56272e1bdbe
|
||||
F src/alter.c 7d7ddbdc189f0e0c686e32ee170abdddc95c11f2089e40df4ffcee88f5334826
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/attach.c 7cf07d4fa42b9fc8662237c60c40b730326c30aa90ae5fffc0b18b2d726ebf61
|
||||
F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
|
||||
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
|
||||
F src/backup.c 6ebe22ccbedfcb92423833992130e8d65824be4e6599c3a03f540ab38fc7d13c
|
||||
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
|
||||
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c fb350c445316c1cc0529703c0b76450770a1de0ab0440641a56b19f05d6fefbe
|
||||
F src/btree.c 216ffbe197e330118a2999adc7d3f09b0e2eeb163df8746ba9a2b27fed3d4335
|
||||
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 a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
|
||||
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
|
||||
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
|
||||
F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930
|
||||
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
|
||||
F src/expr.c 68400681c5f6e41231d2c85abf6bb432aeeb2e36c4abdf90eb7b78551a5ce0f3
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
|
||||
F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7
|
||||
F src/func.c e6a68dccc9c3c2f638bbf5d29ee84cadd48ded246fbd6c4cc56ddc957e99305f
|
||||
F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
|
||||
F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
|
||||
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
|
||||
F src/insert.c 77aa90e7ddbebf131c5de504854b5a61c25b11d53580649fb375b23752793651
|
||||
F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
|
||||
F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
|
||||
F src/loadext.c 78d5b06f18996ffa1203129b28fea043f63a87a4117539678f1d761c30b4ff65
|
||||
F src/main.c 6180079f53ccdd784df2eddc3751f49ea7153c5959bee792b19ad9f4bdbcf437
|
||||
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
|
||||
F src/memdb.c a3feb427cdd4036ea2db0ba56d152f14c8212ca760ccb05fb7aa49ff6b897df3
|
||||
F src/memdb.c 0a0e827311cec57fdea2ed3142d6684704a1b90e7995b286f74fd7d1a6c5a62c
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
|
||||
F src/mutex.c 00b8cee206a67fd764d001f3a148494331d8d0b3b9c3974ecd69ff29bb444462
|
||||
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
|
||||
F src/mutex_w32.c e1d317d29cb623667d43de94714264d1e1871cc4bb39fa67dd17048e8138c739
|
||||
F src/mutex_unix.c caec9862aeebad01f6c8997cf709a239abeb0715fcce1895720b87fe7e2ef42f
|
||||
F src/mutex_w32.c d44e94c064f8ab39e0318fb6fa00171cf7e5645bd4241129b07d655a8ddbd44b
|
||||
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
|
||||
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
|
||||
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
@@ -720,26 +721,26 @@ F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e
|
||||
F src/os_kv.c e7d96727db5b67e39d590a68cc61c86daf4c093c36c011a09ebfb521182ec28d
|
||||
F src/os_setup.h 8efc64eda6a6c2f221387eefc2e7e45fd5a3d5c8337a7a83519ba4fbd2957ae2
|
||||
F src/os_unix.c a07dce662f6c4e18098f6faa9f7ec7cf311f56ee9151bed2aad4dcd55852c9e2
|
||||
F src/os_win.c 0d553b6e8b92c8eb85e7f1b4a8036fe8638c8b32c9ad8d9d72a861c10f81b4c5
|
||||
F src/os_win.h 5e168adf482484327195d10f9c3bce3520f598e04e07ffe62c9c5a8067c1037b
|
||||
F src/pager.c fe34fd22ec251436985d7b6ebdd05bf238a17901c2cb23d3d28974dd2361a912
|
||||
F src/os_win.c 4786b1123beea22a9cd8f8e9d781cc1b4bf4679c56103edbf60a519ce23a2781
|
||||
F src/os_win.h c06ccc3a090cf54202ea58981c298817f3309d4c9e4d52ad0a02927346493721
|
||||
F src/pager.c fbec9063ea139dfa5d94ce540671752b89f8e8dc38f8a1f614bab1aa04a2dd40
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 3b784d6083380a950e3b1b32ce5ddd303e8c7c209d8ab788df2c62aaf9ee8eb3
|
||||
F src/parse.y 8c8003a932f6f98ac612fd239d3cdc7ca64480f61ca5f4f680c4fe69b1bc68c9
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
|
||||
F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
|
||||
F src/printf.c 41fb76fcb5ed7e16aaddc659d3b23891abebea45549fe125fc2e6ec380cc7175
|
||||
F src/printf.c 50be92de0725e88c8b38978775ab46f9b42d74e21f65045c3423503173eb0566
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
|
||||
F src/resolve.c fcc406bfb055bee9954ee77c023f4a2a66a24bcdf1573516a72280811a269c20
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
|
||||
F src/shell.c.in a3288615aba1b375f7dca9801874c806e8d0d047dfe4e9253a944f4b47c7459e
|
||||
F src/sqlite.h.in e2915e4a86d5e0783afb5cb72411df38d987c7f3c5aa2d5441b8e74d30b649d8
|
||||
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
|
||||
F src/shell.c.in 51167ca344ac180efcf6339353c11800981bed97f37c9b8d9e940e659b7d181f
|
||||
F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
|
||||
F src/sqliteInt.h bc1cbc0c23dba35b324ae85a7dbb5fb182321bbd30857fb21f3d0cba049001a5
|
||||
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
|
||||
F src/sqliteInt.h 5071d64ad787d9922e524d834c3fe7b7a11989d29dc6ea25f7944892a43266f4
|
||||
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -799,13 +800,13 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
|
||||
F src/util.c 4f0abc15f63829e12cdfeeb490faf25ac65894b0bcc20d660e3f3757b8e2360b
|
||||
F src/util.c 98cf12c8ba65623a76c1eb6e6afa98ff40107c9919bf79af42f4bfc70e654232
|
||||
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
|
||||
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
|
||||
F src/vdbe.c 1cd55e8171e4e87054de196c3c4747d44b69041b5ec910cf547ae82a85beb3e4
|
||||
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
|
||||
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
|
||||
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
|
||||
F src/vdbeaux.c 81687c55682b9f4d942186695f4f7fa4743c564a985e0889def52eded9076d61
|
||||
F src/vdbeaux.c 8749b5f4f6d65e048ba78143d2dfc6898f65010ecef213891094e8166d1557da
|
||||
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
|
||||
F src/vdbemem.c efacb8f229422d2a4db0ed38e49b7f3897862a98d82b261aa3b43d7a2d98c6da
|
||||
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
|
||||
@@ -816,9 +817,9 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
|
||||
F src/wal.c 7340d4f9bb827bd349127cac6b2cf0cb7f76b9fda645f7b9b0bf7a6e0b1e2e7c
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c bffca5e4ef20d0bfbdc24f1dc13fd3f955284225a8ad25a4454635f6be39aad0
|
||||
F src/where.c 7241a71725d8c193ddd9e69a299820fcd755943f3b5ac376a84b2716e2848401
|
||||
F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
|
||||
F src/wherecode.c 676cb6cb02878643e817d9917a2d3522b83a3736b2cedd3dc8a01d7bb92af6c2
|
||||
F src/wherecode.c 4d573077652f79780d6b50840ab8cbb72053dbb4eb230780dd2a146ab034475d
|
||||
F src/whereexpr.c e9f7185fba366d9365aa7a97329609e4cf00b3dd0400d069fbaa5187350c17c6
|
||||
F src/window.c c0a38cd32473e8e8e7bc435039f914a36ca42465506dc491c65870c01ddac9fb
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
@@ -838,7 +839,7 @@ F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256b
|
||||
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
|
||||
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
|
||||
F test/altercons.test ea18def4a0f26b9066da56095c9c480df705df4d02e4ae151708fae76f7e3884
|
||||
F test/altercons2.test 3c1f58312817df43aeada3b1827fdc3ce3fc50c6f49a95ef62cf4cbbae8583a0
|
||||
F test/altercons2.test 4933eadb035fc0ccfc34ed879f69a09051c53907f9dae9c3d36d25f93519ccc7
|
||||
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
|
||||
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
|
||||
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
||||
@@ -899,7 +900,7 @@ F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
|
||||
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf.test cff75b714866a4ffa0cdda252eb8fe8765483f5872c0076223c92d52b4fffd1b
|
||||
F test/badutf2.test f310fd3b24a491b6b77bccdf14923b85d6ebcce751068c180d93a6b8ff854399
|
||||
F test/basexx1.test 4ae6ddbd92a7ebcabb5d844664c3e755d29fb69c8ddcf0c8d59bbe4e07c23919
|
||||
F test/bc_common.tcl c70b896d1d4ce72f769d2c7c1fc15b2cb07559eb2093f2736c8ca51664b29ff5
|
||||
@@ -943,6 +944,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
|
||||
@@ -1097,14 +1100,15 @@ F test/exclusive.test 7ff63be7503990921838d5c9f77f6e33e68e48ed1a9d48cd28745bf650
|
||||
F test/exclusive2.test cd70b1d9c6fffd336f9795b711dcc5d9ceba133ad3f7001da3fda63615bdc91e
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/existsexpr.test 75c1c13cda18b53f68c135fe644afc034d72a6de5b0774b0219ca4a6dc4b96b0
|
||||
F test/existsexpr.test 1ce70ac41fb6d52525774388aa23e982428e883a850f9d56d49776d234865552
|
||||
F test/existsexpr2.test dc23e76389eff3d29f6488ff733012a3560cd67ec8cfaecbecd52cced5d5af11
|
||||
F test/existsfault.test ff41c11f3052c1bbd4f8dd557802310026253d67d7c4e3a180c16d2f0862973e
|
||||
F test/expr.test db981f8a85520e99ae20aab7ad2e9b5b0437ed09159b57ced434c672075d2e61
|
||||
F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
|
||||
F test/exprfault.test da33606d799718e2f8e34efd0e5858884a1ad87f608774c552a7f5517cc27181
|
||||
F test/exprfault.test 7475e363c7221847855722e9dd2459cf60088f6b172c0c808dba75f89e1704b8
|
||||
F test/exprfault2.test c49e84273898969af5dbc4fe6a3f4335f14639799f343590336c9ddf84425965
|
||||
F test/expridx1.test b464520126e1d781a7800f8540621c82e8bbc526f089ff8b0b57ffc51feea6b7
|
||||
F test/expridx2.test 13348ed208a5d18d9cef7d0a70f8e17948d3c0b5b46508c0573b7e983456165f
|
||||
F test/extension01.test 5de412c66276105901c370770175003381fdcb0c4da7054fa43cf4a31e0bfa3a
|
||||
F test/external_reader.test 6fdec43eeca23eb32faad1e95a4d1abc402bc8b3db70df12d6fc08a637f4a2b5
|
||||
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
@@ -1245,7 +1249,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 207d3d1c1d578928f16dec20df781c5d13c2fd4694b4d70e72242f4dcb799830
|
||||
F test/fuzzcheck.c 5048a2426bd6968a1b9a00cef7f3aa37442a261df3b532c9e44a1f829bddbede
|
||||
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1316,7 +1320,7 @@ F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd
|
||||
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
|
||||
F test/intck01.sql f2d88bf41cdd64f2ed8c3d4f357cf520f017aa2986999ab9a62eb6506ef18106
|
||||
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
|
||||
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
|
||||
F test/interrupt2.test 7eaa40a975d950826cd56e6c37f0f0629adfa2d1a8d3333aff0ff7cf86069963
|
||||
F test/intpkey.test 7d54711acf553cdd641a40e9c6cfc2bf1a76070074940c1b126442517054320f
|
||||
F test/intreal.test 68829a8bb073ee1610ca3f8f9e0f99b0371fb36e0fa64862dd5ced4ef03c2343
|
||||
F test/io.test d267fdc8915444a45e19841489033ebe70bb69f6db605b00df70be16b2a80f59
|
||||
@@ -1420,7 +1424,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
F test/memdb1.test c737ac9aa5895092332b1dde24fae7ae494b7fcbcd346d22d600891096a3836d
|
||||
F test/memdb1.test 413f845c0c2d20dc9808d4084de9e57d55759070eed2a4cf23cd30335a96c295
|
||||
F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4
|
||||
F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c
|
||||
F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e
|
||||
@@ -1489,6 +1493,7 @@ F test/orderbyB.test 32576c7b138105bc72f7fbf33bd320ca3a7d303641fc939e0e56af6cba8
|
||||
F test/oserror.test ee3fad06ec8671c4d047c2c92a567fc2e0e8161caaec7edd6d48325c5ac97f30
|
||||
F test/ossfuzz.c b5d232d9717fc999a121c82c4880ae5b9d7fb3ae55d2d87a8da906bc80020906
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/output-redirect-test.txt aeebac99f766f1e54bb2628b13c2d89a3d77de942138a01210c8a814b54c2bc8
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test b083c2d5d89df8e979658d9320bfc0b9d50b4ef8ae1d9e115a692ff0b9768393
|
||||
F test/pager2.test c0ede15952b607f9a38f653acdfa73c19e657958e9104aab1a71950ea7b71831
|
||||
@@ -1606,7 +1611,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
|
||||
@@ -1619,17 +1624,18 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
|
||||
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test eda2e527435f139224dda67db6bbd2466597408d4fe5883d647d67fa32d88f7c
|
||||
F test/shell-prompt.sql b062f7778cf5529ccac2e0c07364b8a050c87397706d28ea2240dc5c43e920ac
|
||||
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
|
||||
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
|
||||
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
|
||||
F test/shell4.test e25580a792b7b54560c3a76b6968bd8189261f38979fe28e6bc6312c5db280db
|
||||
F test/shell5.test a9cd2c8b62e125049ef500937674f47dd6787f0157ac0515aa554044a4dc3ea9
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell5.test a0c43d82a811a463a5d07d6418c5a045ab01a072544db8aa31ae394e93845d8d
|
||||
F test/shell6.test 596f2eb385a1097d4e9130b4d4f663a24cba294b35f13b774b8f13553dec307d
|
||||
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
|
||||
F test/shell8.test 38c9e4d7e85d2a3ecfacaa9f6cda4f7a81bf4fffb5f3f37f9cd76827c6883192
|
||||
F test/shell9.test c0e8871061a92151450b3332279a893b516fa73a6c46d4f51a0998407cbf8c89
|
||||
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
|
||||
F test/shellB.test 31df04230f6062069bb7c5d0e5c5439ca44448fa9da1a55aa461a4b872fe6bd9
|
||||
F test/shellB.test 82622da7783c32ce931138bec3d5016e802d70361b9f9364b5d49c1dfc2f5af9
|
||||
F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
@@ -1665,7 +1671,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest.md ea0c85ebe0ecff8b45ba6cdb26e694871f469009a5a29dcfe634b055f05ab241
|
||||
F test/speedtest.tcl b06f6321ef90bb68f18f7b0e430e25203d9da79b80f8926986a0d5f21ac485fb x
|
||||
F test/speedtest1.c 6c01252e66f46de0b6b8d5316e03521e2151782104f3608c10262aa5dce85721
|
||||
F test/speedtest1.c f9f30f35431bfc1d3ee9acc561624e0c0b4614071044bc302169dd27206a0fca
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1714,8 +1720,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 6b232f0d4825dec8b967754503080fc9609fad077f582d02f86bd2d95bec4110 x
|
||||
F test/testrunner_data.tcl 48c8a230fcada37f4809f95c2ba49e44bc3d520b6165c09173249c6e65b01cc1
|
||||
F test/testrunner.tcl 6d13732185c13aef87540ebf9daafb8d9657e66f0ac00eb082d93f4749311d4e x
|
||||
F test/testrunner_data.tcl dfcf192d274e965845189cc014ac89fff91dde92b6e2ac9e1262897fc21ee2e0
|
||||
F test/testrunner_estwork.tcl 81e2ae10238f50540f42fbf2d94913052a99bfb494b69e546506323f195dcff9
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
@@ -1922,7 +1928,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test d2366ef2d3d95249314307861d748924d9ab4f24305541159a08be61ccd4a9ee
|
||||
F test/unordered.test 0edaf3411d300693bca595897c5201421c6c5ec787990a1dfe2f7f60ae93f1e2
|
||||
F test/update.test 258dcf26d401177d3cb7fdf0beab14d671dbe72e8ff6e0435fd85a08fcd57bd9
|
||||
F test/update.test 93fba5f7505f7a7b25d66135d98d9b055b7f1bd627a7e514dbba1ea6213f0c41
|
||||
F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
|
||||
F test/upfrom1.tcl 8859d9d437f03b44174c4524a7a734a391fd4526fcff65be08285dafc9dc9041
|
||||
F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
|
||||
@@ -2108,7 +2114,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
F tool/build-all-msvc.bat 1ee9dbadcc07fc23268025854e97b392bcbad72376b47aee7b22f3797a4f2c87 x
|
||||
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
|
||||
F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
|
||||
F tool/buildtclext.tcl b58df93e772fec8b2ae44ee1a82d13378e13edb1e94c4ab2f7ee3440a9523bff
|
||||
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
|
||||
@@ -2129,7 +2135,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/lemon.c 3fdc16b23f1ea0c91c049b518fc3f75c71843dbfe2b447fcb3cd92d9e4f219f8
|
||||
F tool/lempar.c b57e1780bf8098dd4a9a5bba537f994276ea825a420f6165153e5894dc2dfb07
|
||||
F tool/lempar.c a8de510526f9cbfb45ff0aca9d16f1c828600246f198c1c7d49c8d5492142ffa
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c 63412f9790e5e8538fbde0b4f6db154aaaf80f7a10a01e3c94d14b773a8dd5a6
|
||||
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
|
||||
@@ -2176,7 +2182,7 @@ F tool/soak1.tcl a3892082ed1079671565c044e93b55c3c7f38829aedf53cc597c65d23ffdadd
|
||||
F tool/spaceanal.tcl 1f83962090a6b60e1d7bf92495d643e622bef9fe82ea3f2d22350dcbce9a12d0
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 4969fd642dad0ea483e4e104163021d92baf98f6a8eac981fe48525f9b873430
|
||||
F tool/sqldiff.c 847edc1e0d1e1feb652d3d6128e504456deaf254ab9ad3e7cebd4317d2037182
|
||||
F tool/sqldiff.c de59a4eecbc802db8ad053889c10e6f8b8427b6f349199ee79938c92c20860dd
|
||||
F tool/sqlite3_analyzer.c.in 14f02cb5ec3c264cd6107d1f1dad77092b1cf440fc196c30b69ae87b56a1a43b
|
||||
F tool/sqlite3_rsync.c f510a8b230e1c5b0f62842acd0e94ff15d2f77a00ae782f7d20f9e39919fa19b
|
||||
F tool/sqltclsh.c.in c103c6fc7d42bce611f9d4596774d60b7ef3d0b291a1f58c9e6184e458b89296
|
||||
@@ -2197,11 +2203,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P 4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b
|
||||
R 8620cf4411d3ee800e21795293030726
|
||||
T *branch * o_tmpfile
|
||||
T *sym-o_tmpfile *
|
||||
P 9380be51c76392eca9544f1fd56373406d2ce001e77a8d476deb772968f2aacc
|
||||
R b0c5fee1261e3ede23c06abcb314461f
|
||||
T *branch * exists-or-expr-fix
|
||||
T *sym-exists-or-expr-fix *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z c35d74d8270d74b882ed210a9b661389
|
||||
U dan
|
||||
Z 9ca98967ce2f5b33bad22608c4948005
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
branch o_tmpfile
|
||||
tag o_tmpfile
|
||||
branch exists-or-expr-fix
|
||||
tag exists-or-expr-fix
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
094fc6da0768ea0ec4b4d3dc020cd6025aab341550d6cea6be7487ac570f9171
|
||||
3d197dd03c47a0fb687064131dbf519b8c587a47f9c2bccfdb83d7eae8418336
|
||||
|
||||
+3
-1
@@ -2798,7 +2798,9 @@ void sqlite3AlterDropConstraint(
|
||||
if( !pTab ) return;
|
||||
|
||||
if( pCons ){
|
||||
zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
|
||||
char *z = sqlite3NameFromToken(db, pCons);
|
||||
zArg = sqlite3MPrintf(db, "%Q", z);
|
||||
sqlite3DbFree(db, z);
|
||||
}else{
|
||||
int iCol;
|
||||
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
|
||||
|
||||
+11
-2
@@ -106,6 +106,16 @@ static void attachFunc(
|
||||
** from sqlite3_deserialize() to close database db->init.iDb and
|
||||
** reopen it as a MemDB */
|
||||
Btree *pNewBt = 0;
|
||||
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
assert( pNew->pBt!=0 );
|
||||
if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE
|
||||
|| sqlite3BtreeIsInBackup(pNew->pBt)
|
||||
){
|
||||
rc = SQLITE_BUSY;
|
||||
goto attach_error;
|
||||
}
|
||||
|
||||
pVfs = sqlite3_vfs_find("memdb");
|
||||
if( pVfs==0 ) return;
|
||||
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
|
||||
@@ -115,8 +125,7 @@ static void attachFunc(
|
||||
/* Both the Btree and the new Schema were allocated successfully.
|
||||
** Close the old db and update the aDb[] slot with the new memdb
|
||||
** values. */
|
||||
pNew = &db->aDb[db->init.iDb];
|
||||
if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt);
|
||||
sqlite3BtreeClose(pNew->pBt);
|
||||
pNew->pBt = pNewBt;
|
||||
pNew->pSchema = pNewSchema;
|
||||
}else{
|
||||
|
||||
+21
-2
@@ -189,8 +189,14 @@ void sqlite3AuthRead(
|
||||
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
|
||||
** is returned, then the error count and error message in pParse are
|
||||
** modified appropriately.
|
||||
**
|
||||
** Divided into two routines. realAuthCheck() does the work. The
|
||||
** sqlite3AuthCheck() routine is usually a fast no-op but invokes
|
||||
** realAuthCheck() (and spends time doing some stack pushes and pops
|
||||
** as a result) in the uncommon case where an authorization check is
|
||||
** actually needed.
|
||||
*/
|
||||
int sqlite3AuthCheck(
|
||||
static int SQLITE_NOINLINE realAuthCheck(
|
||||
Parse *pParse,
|
||||
int code,
|
||||
const char *zArg1,
|
||||
@@ -204,7 +210,7 @@ int sqlite3AuthCheck(
|
||||
** or if the parser is being invoked from within sqlite3_declare_vtab.
|
||||
*/
|
||||
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
|
||||
if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
|
||||
if( IN_SPECIAL_PARSE ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -229,6 +235,19 @@ int sqlite3AuthCheck(
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3AuthCheck(
|
||||
Parse *pParse,
|
||||
int code,
|
||||
const char *zArg1,
|
||||
const char *zArg2,
|
||||
const char *zArg3
|
||||
){
|
||||
if( pParse->db->xAuth!=0 && pParse->db->init.busy==0 ){
|
||||
return realAuthCheck(pParse,code,zArg1,zArg2,zArg3);
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Push an authorization context. After this routine is called, the
|
||||
|
||||
+66
-54
@@ -20,13 +20,13 @@
|
||||
*/
|
||||
struct sqlite3_backup {
|
||||
sqlite3* pDestDb; /* Destination database handle */
|
||||
Btree *pDest; /* Destination b-tree file */
|
||||
Db *pDest; /* Destination db file */
|
||||
u32 iDestSchema; /* Original schema cookie in destination */
|
||||
int bDestLocked; /* True once a write-transaction is open on pDest */
|
||||
|
||||
Pgno iNext; /* Page number of the next source page to copy */
|
||||
sqlite3* pSrcDb; /* Source database handle */
|
||||
Btree *pSrc; /* Source b-tree file */
|
||||
Db *pSrc; /* Source db file */
|
||||
|
||||
int rc; /* Backup process error code */
|
||||
|
||||
@@ -79,7 +79,7 @@ struct sqlite3_backup {
|
||||
** function. If an error occurs while doing so, return 0 and write an
|
||||
** error message to pErrorDb.
|
||||
*/
|
||||
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
static Db *findDatabase(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
int i = sqlite3FindDbName(pDb, zDb);
|
||||
|
||||
if( i==1 ){
|
||||
@@ -102,7 +102,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDb->aDb[i].pBt;
|
||||
return &pDb->aDb[i];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -110,9 +110,9 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
** of the source.
|
||||
*/
|
||||
static int setDestPgsz(sqlite3_backup *p){
|
||||
int rc;
|
||||
rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
|
||||
return rc;
|
||||
return sqlite3BtreeSetPageSize(p->pDest->pBt,
|
||||
sqlite3BtreeGetPageSize(p->pSrc->pBt), 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -181,15 +181,15 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
|
||||
/* If the allocation succeeded, populate the new object. */
|
||||
if( p ){
|
||||
p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
|
||||
p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
|
||||
p->pSrc = findDatabase(pDestDb, pSrcDb, zSrcDb);
|
||||
p->pDest = findDatabase(pDestDb, pDestDb, zDestDb);
|
||||
p->pDestDb = pDestDb;
|
||||
p->pSrcDb = pSrcDb;
|
||||
p->iNext = 1;
|
||||
p->isAttached = 0;
|
||||
|
||||
if( 0==p->pSrc || 0==p->pDest
|
||||
|| checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
|
||||
|| checkReadTransaction(pDestDb, p->pDest->pBt)!=SQLITE_OK
|
||||
){
|
||||
/* One (or both) of the named databases did not exist or an OOM
|
||||
** error was hit. Or there is a transaction open on the destination
|
||||
@@ -201,7 +201,7 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
}
|
||||
}
|
||||
if( p ){
|
||||
p->pSrc->nBackup++;
|
||||
p->pSrc->pBt->nBackup++;
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(pDestDb->mutex);
|
||||
@@ -229,18 +229,18 @@ static int backupOnePage(
|
||||
const u8 *zSrcData, /* Source database page data */
|
||||
int bUpdate /* True for an update, false otherwise */
|
||||
){
|
||||
Pager * const pDestPager = sqlite3BtreePager(p->pDest);
|
||||
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
|
||||
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
|
||||
Pager * const pDestPager = sqlite3BtreePager(p->pDest->pBt);
|
||||
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc->pBt);
|
||||
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest->pBt);
|
||||
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
|
||||
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
|
||||
int rc = SQLITE_OK;
|
||||
i64 iOff;
|
||||
|
||||
assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
|
||||
assert( sqlite3BtreeGetReserveNoMutex(p->pSrc->pBt)>=0 );
|
||||
assert( p->bDestLocked );
|
||||
assert( !isFatalError(p->rc) );
|
||||
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
|
||||
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt->pBt) );
|
||||
assert( zSrcData );
|
||||
assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 );
|
||||
|
||||
@@ -251,7 +251,7 @@ static int backupOnePage(
|
||||
for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
|
||||
DbPage *pDestPg = 0;
|
||||
Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
|
||||
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
|
||||
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt->pBt) ) continue;
|
||||
if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
|
||||
&& SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
|
||||
){
|
||||
@@ -269,7 +269,7 @@ static int backupOnePage(
|
||||
memcpy(zOut, zIn, nCopy);
|
||||
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
|
||||
if( iOff==0 && bUpdate==0 ){
|
||||
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
|
||||
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc->pBt));
|
||||
}
|
||||
}
|
||||
sqlite3PagerUnref(pDestPg);
|
||||
@@ -301,8 +301,8 @@ static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
|
||||
*/
|
||||
static void attachBackupObject(sqlite3_backup *p){
|
||||
sqlite3_backup **pp;
|
||||
assert( sqlite3BtreeHoldsMutex(p->pSrc) );
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
|
||||
assert( sqlite3BtreeHoldsMutex(p->pSrc->pBt) );
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt));
|
||||
p->pNext = *pp;
|
||||
*pp = p;
|
||||
p->isAttached = 1;
|
||||
@@ -316,20 +316,26 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
int destMode; /* Destination journal mode */
|
||||
int pgszSrc = 0; /* Source page size */
|
||||
int pgszDest = 0; /* Destination page size */
|
||||
Btree *pDest;
|
||||
Btree *pSrc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
assert( p->pDest );
|
||||
assert( p->pSrc );
|
||||
pDest = p->pDest->pBt;
|
||||
pSrc = p->pSrc->pBt;
|
||||
sqlite3_mutex_enter(p->pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
sqlite3BtreeEnter(pSrc);
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_enter(p->pDestDb->mutex);
|
||||
}
|
||||
|
||||
rc = p->rc;
|
||||
if( !isFatalError(rc) ){
|
||||
Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
|
||||
Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
|
||||
Pager * const pSrcPager = sqlite3BtreePager(pSrc); /* Source pager */
|
||||
Pager * const pDestPager = sqlite3BtreePager(pDest); /* Dest pager */
|
||||
int ii; /* Iterator variable */
|
||||
int nSrcPage = -1; /* Size of source db in pages */
|
||||
int bCloseTrans = 0; /* True if src db requires unlocking */
|
||||
@@ -337,7 +343,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
/* If the source pager is currently in a write-transaction, return
|
||||
** SQLITE_BUSY immediately.
|
||||
*/
|
||||
if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
|
||||
if( p->pDestDb && pSrc->pBt->inTransaction==TRANS_WRITE ){
|
||||
rc = SQLITE_BUSY;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
@@ -347,8 +353,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** one now. If a transaction is opened here, then it will be closed
|
||||
** before this function exits.
|
||||
*/
|
||||
if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
|
||||
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
|
||||
if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(pSrc) ){
|
||||
rc = sqlite3BtreeBeginTrans(pSrc, 0, 0);
|
||||
bCloseTrans = 1;
|
||||
}
|
||||
|
||||
@@ -364,7 +370,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Lock the destination database, if it is not locked already. */
|
||||
if( SQLITE_OK==rc && p->bDestLocked==0
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(pDest, 2,
|
||||
(int*)&p->iDestSchema))
|
||||
){
|
||||
p->bDestLocked = 1;
|
||||
@@ -372,9 +378,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Do not allow backup if the destination database is in WAL mode
|
||||
** and the page sizes are different between source and destination */
|
||||
pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
|
||||
pgszDest = sqlite3BtreeGetPageSize(p->pDest);
|
||||
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
|
||||
pgszSrc = sqlite3BtreeGetPageSize(pSrc);
|
||||
pgszDest = sqlite3BtreeGetPageSize(pDest);
|
||||
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(pDest));
|
||||
if( SQLITE_OK==rc
|
||||
&& (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
|
||||
&& pgszSrc!=pgszDest
|
||||
@@ -385,11 +391,11 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
/* Now that there is a read-lock on the source database, query the
|
||||
** source pager for the number of pages in the database.
|
||||
*/
|
||||
nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
|
||||
nSrcPage = (int)sqlite3BtreeLastPage(pSrc);
|
||||
assert( nSrcPage>=0 );
|
||||
for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
|
||||
const Pgno iSrcPg = p->iNext; /* Source page number */
|
||||
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
|
||||
if( iSrcPg!=PENDING_BYTE_PAGE(pSrc->pBt) ){
|
||||
DbPage *pSrcPg; /* Source page object */
|
||||
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -416,18 +422,18 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
*/
|
||||
if( rc==SQLITE_DONE ){
|
||||
if( nSrcPage==0 ){
|
||||
rc = sqlite3BtreeNewDb(p->pDest);
|
||||
rc = sqlite3BtreeNewDb(pDest);
|
||||
nSrcPage = 1;
|
||||
}
|
||||
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
|
||||
rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
|
||||
rc = sqlite3BtreeUpdateMeta(pDest,1,p->iDestSchema+1);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( p->pDestDb ){
|
||||
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
|
||||
}
|
||||
if( destMode==PAGER_JOURNALMODE_WAL ){
|
||||
rc = sqlite3BtreeSetVersion(p->pDest, 2);
|
||||
rc = sqlite3BtreeSetVersion(pDest, 2);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -444,12 +450,12 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** journalled by PagerCommitPhaseOne() before they are destroyed
|
||||
** by the file truncation.
|
||||
*/
|
||||
assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
|
||||
assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
|
||||
assert( pgszSrc==sqlite3BtreeGetPageSize(pSrc) );
|
||||
assert( pgszDest==sqlite3BtreeGetPageSize(pDest) );
|
||||
if( pgszSrc<pgszDest ){
|
||||
int ratio = pgszDest/pgszSrc;
|
||||
nDestTruncate = (nSrcPage+ratio-1)/ratio;
|
||||
if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
|
||||
if( nDestTruncate==(int)PENDING_BYTE_PAGE(pDest->pBt) ){
|
||||
nDestTruncate--;
|
||||
}
|
||||
}else{
|
||||
@@ -477,7 +483,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
assert( pFile );
|
||||
assert( nDestTruncate==0
|
||||
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
|
||||
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
|
||||
nDestTruncate==(int)(PENDING_BYTE_PAGE(pDest->pBt)-1)
|
||||
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
|
||||
));
|
||||
|
||||
@@ -489,7 +495,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
** journal file. */
|
||||
sqlite3PagerPagecount(pDestPager, &nDstPage);
|
||||
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
|
||||
if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
|
||||
if( iPg!=PENDING_BYTE_PAGE(pDest->pBt) ){
|
||||
DbPage *pPg;
|
||||
rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -533,7 +539,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Finish committing the transaction to the destination database. */
|
||||
if( SQLITE_OK==rc
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
|
||||
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(pDest, 0))
|
||||
){
|
||||
rc = SQLITE_DONE;
|
||||
}
|
||||
@@ -547,8 +553,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
*/
|
||||
if( bCloseTrans ){
|
||||
TESTONLY( int rc2 );
|
||||
TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
|
||||
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
|
||||
TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(pSrc, 0);
|
||||
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(pSrc, 0);
|
||||
assert( rc2==SQLITE_OK );
|
||||
}
|
||||
|
||||
@@ -560,7 +566,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_leave(p->pDestDb->mutex);
|
||||
}
|
||||
sqlite3BtreeLeave(p->pSrc);
|
||||
sqlite3BtreeLeave(pSrc);
|
||||
sqlite3_mutex_leave(p->pSrcDb->mutex);
|
||||
return rc;
|
||||
}
|
||||
@@ -577,17 +583,17 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
pSrcDb = p->pSrcDb;
|
||||
sqlite3_mutex_enter(pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
sqlite3BtreeEnter(p->pSrc->pBt);
|
||||
if( p->pDestDb ){
|
||||
sqlite3_mutex_enter(p->pDestDb->mutex);
|
||||
}
|
||||
|
||||
/* Detach this backup from the source pager. */
|
||||
if( p->pDestDb ){
|
||||
p->pSrc->nBackup--;
|
||||
p->pSrc->pBt->nBackup--;
|
||||
}
|
||||
if( p->isAttached ){
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
|
||||
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc->pBt));
|
||||
assert( pp!=0 );
|
||||
while( *pp!=p ){
|
||||
pp = &(*pp)->pNext;
|
||||
@@ -597,7 +603,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
}
|
||||
|
||||
/* If a transaction is still open on the Btree, roll it back. */
|
||||
sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
|
||||
sqlite3BtreeRollback(p->pDest->pBt, SQLITE_OK, 0);
|
||||
|
||||
/* Set the error code of the destination database handle. */
|
||||
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
|
||||
@@ -607,7 +613,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
/* Exit the mutexes and free the backup context structure. */
|
||||
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
|
||||
}
|
||||
sqlite3BtreeLeave(p->pSrc);
|
||||
sqlite3BtreeLeave(p->pSrc->pBt);
|
||||
if( p->pDestDb ){
|
||||
/* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
|
||||
** call to sqlite3_backup_init() and is destroyed by a call to
|
||||
@@ -665,7 +671,7 @@ static SQLITE_NOINLINE void backupUpdate(
|
||||
){
|
||||
assert( p!=0 );
|
||||
do{
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) );
|
||||
if( !isFatalError(p->rc) && iPage<p->iNext ){
|
||||
/* The backup process p has already copied page iPage. But now it
|
||||
** has been modified by a transaction on the source pager. Copy
|
||||
@@ -701,7 +707,7 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
|
||||
void sqlite3BackupRestart(sqlite3_backup *pBackup){
|
||||
sqlite3_backup *p; /* Iterator variable */
|
||||
for(p=pBackup; p; p=p->pNext){
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
|
||||
assert( sqlite3_mutex_held(p->pSrc->pBt->pBt->mutex) );
|
||||
p->iNext = 1;
|
||||
}
|
||||
}
|
||||
@@ -719,6 +725,8 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
int rc;
|
||||
sqlite3_file *pFd; /* File descriptor for database pTo */
|
||||
sqlite3_backup b;
|
||||
Db dbDest;
|
||||
Db dbSrc;
|
||||
sqlite3BtreeEnter(pTo);
|
||||
sqlite3BtreeEnter(pFrom);
|
||||
|
||||
@@ -737,9 +745,13 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
** from this function, not directly by the user.
|
||||
*/
|
||||
memset(&b, 0, sizeof(b));
|
||||
memset(&dbDest, 0, sizeof(dbDest));
|
||||
memset(&dbSrc, 0, sizeof(dbSrc));
|
||||
dbDest.pBt = pTo;
|
||||
dbSrc.pBt = pFrom;
|
||||
b.pSrcDb = pFrom->db;
|
||||
b.pSrc = pFrom;
|
||||
b.pDest = pTo;
|
||||
b.pSrc = &dbSrc;
|
||||
b.pDest = &dbDest;
|
||||
b.iNext = 1;
|
||||
|
||||
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
|
||||
@@ -755,7 +767,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
if( rc==SQLITE_OK ){
|
||||
pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
|
||||
}else{
|
||||
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
|
||||
sqlite3PagerClearCache(sqlite3BtreePager(pTo));
|
||||
}
|
||||
|
||||
assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
|
||||
|
||||
+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 pCur[idx] less than pIdxKey
|
||||
** Return value negative: Cell at pPage[idx] less than pIdxKey
|
||||
**
|
||||
** Return value is zero: Cell at pCur[idx] equals pIdxKey
|
||||
** Return value is zero: Cell at pPage[idx] equals pIdxKey
|
||||
**
|
||||
** Return value positive: Nothing is known about the relationship
|
||||
** of the cell at pCur[idx] and pIdxKey.
|
||||
** of the cell at pPage[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.
|
||||
|
||||
+91
-10
@@ -49,12 +49,51 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return TRUE if the given SQL string ends in a semicolon.
|
||||
** 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.
|
||||
**
|
||||
** 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.
|
||||
@@ -101,9 +140,11 @@ 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.
|
||||
*/
|
||||
int sqlite3_complete(const char *zSql){
|
||||
sqlite3_int64 sqlite3_incomplete(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
|
||||
@@ -133,11 +174,21 @@ int sqlite3_complete(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 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -162,7 +213,10 @@ int sqlite3_complete(const char *zSql){
|
||||
}
|
||||
zSql += 2;
|
||||
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
|
||||
if( zSql[0]==0 ) return 0;
|
||||
if( zSql[0]==0 ){
|
||||
pending = '/';
|
||||
goto incomplete_finish;
|
||||
}
|
||||
zSql++;
|
||||
token = tkWS;
|
||||
break;
|
||||
@@ -173,14 +227,20 @@ int sqlite3_complete(const char *zSql){
|
||||
break;
|
||||
}
|
||||
while( *zSql && *zSql!='\n' ){ zSql++; }
|
||||
if( *zSql==0 ) return state==1;
|
||||
if( *zSql==0 ){
|
||||
if( state!=1 ) pending = '-';
|
||||
goto incomplete_finish;
|
||||
}
|
||||
token = tkWS;
|
||||
break;
|
||||
}
|
||||
case '[': { /* Microsoft-style identifiers in [...] */
|
||||
zSql++;
|
||||
while( *zSql && *zSql!=']' ){ zSql++; }
|
||||
if( *zSql==0 ) return 0;
|
||||
if( *zSql==0 ){
|
||||
pending = ']';
|
||||
goto incomplete_finish;
|
||||
}
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
@@ -190,7 +250,20 @@ int sqlite3_complete(const char *zSql){
|
||||
int c = *zSql;
|
||||
zSql++;
|
||||
while( *zSql && *zSql!=c ){ zSql++; }
|
||||
if( *zSql==0 ) return 0;
|
||||
if( *zSql==0 ){
|
||||
pending = c;
|
||||
goto incomplete_finish;
|
||||
}
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
case '(': {
|
||||
nParen++;
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
case ')': {
|
||||
nParen--;
|
||||
token = tkOTHER;
|
||||
break;
|
||||
}
|
||||
@@ -257,7 +330,15 @@ int sqlite3_complete(const char *zSql){
|
||||
state = trans[state][token];
|
||||
zSql++;
|
||||
}
|
||||
return state==1;
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@@ -279,7 +360,7 @@ int sqlite3_complete16(const void *zSql){
|
||||
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
|
||||
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
|
||||
if( zSql8 ){
|
||||
rc = sqlite3_complete(zSql8);
|
||||
rc = sqlite3_incomplete(zSql8)==0;
|
||||
}else{
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
+6
-3
@@ -915,6 +915,7 @@ void sqlite3GenerateRowIndexDelete(
|
||||
v = pParse->pVdbe;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||
int p3 = 0;
|
||||
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
|
||||
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
|
||||
if( pIdx==pPk ) continue;
|
||||
@@ -922,10 +923,12 @@ void sqlite3GenerateRowIndexDelete(
|
||||
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
|
||||
&iPartIdxLabel, pPrior, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
|
||||
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn
|
||||
);
|
||||
if( pIdx->bHasExpr && aRegIdx ){
|
||||
p3 = aRegIdx[i];
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, p3);
|
||||
sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
|
||||
sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
||||
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
|
||||
pPrior = pIdx;
|
||||
}
|
||||
|
||||
+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 originate in the ON or USING clause
|
||||
** (2) the expression does not 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.
|
||||
|
||||
+29
-12
@@ -130,13 +130,17 @@ static void lengthFunc(
|
||||
case SQLITE_TEXT: {
|
||||
const unsigned char *z = sqlite3_value_text(argv[0]);
|
||||
const unsigned char *z0;
|
||||
unsigned char c;
|
||||
if( z==0 ) return;
|
||||
z0 = z;
|
||||
while( (c = *z)!=0 ){
|
||||
z++;
|
||||
if( c>=0xc0 ){
|
||||
while( (*z & 0xc0)==0x80 ){ z++; z0++; }
|
||||
while( 1 /*exit-by-break*/ ){
|
||||
/* vvvvvv---- See tag-20260418-01 */
|
||||
if( (u8)(z[0]-1)<(0x80-1) ){
|
||||
z++;
|
||||
}else if( z[0]==0 ){
|
||||
break;
|
||||
}else{
|
||||
z++;
|
||||
while( (z[0]&0xc0)==0x80 ){ z++; z0++; }
|
||||
}
|
||||
}
|
||||
sqlite3_result_int(context, (int)(z-z0));
|
||||
@@ -415,12 +419,25 @@ static void substrFunc(
|
||||
}
|
||||
assert( p1>=0 && p2>=0 );
|
||||
if( p0type!=SQLITE_BLOB ){
|
||||
while( *z && p1 ){
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
p1--;
|
||||
for( ; p1>0; p1--){
|
||||
/* vvvvvv---- See tag-20260418-01 */
|
||||
if( (u8)(z[0]-1)<(0x80-1) ){
|
||||
z++;
|
||||
}else if( z[0]==0 ){
|
||||
break;
|
||||
}else{
|
||||
do{ z++; }while( (z[0]&0xc0)==0x80 );
|
||||
}
|
||||
}
|
||||
for(z2=z; *z2 && p2; p2--){
|
||||
SQLITE_SKIP_UTF8(z2);
|
||||
for(z2=z; p2>0; p2--){
|
||||
/* vvvvvv---- See tag-20260418-01 */
|
||||
if( (u8)(z2[0]-1)<(0x80-1) ){
|
||||
z2++;
|
||||
}else if( z2[0]==0 ){
|
||||
break;
|
||||
}else{
|
||||
do{ z2++; }while( (z2[0]&0xc0)==0x80 );
|
||||
}
|
||||
}
|
||||
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
|
||||
SQLITE_UTF8);
|
||||
@@ -3106,7 +3123,7 @@ static void filestatFunc(
|
||||
assert( pPager!=0 );
|
||||
fd = sqlite3PagerFile(pPager);
|
||||
pStr = sqlite3_str_new(db);
|
||||
if( pStr==0 ){
|
||||
if( sqlite3_str_errcode(pStr) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_str_append(pStr, "{\"db\":", 6);
|
||||
@@ -3209,7 +3226,7 @@ static void parseuriFunc(
|
||||
flgs = (unsigned int)sqlite3_value_int(argv[1]);
|
||||
rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
|
||||
pResult = sqlite3_str_new(0);
|
||||
if( pResult ){
|
||||
if( !sqlite3_str_errcode(pResult) ){
|
||||
int i;
|
||||
sqlite3_str_appendf(pResult, "rc=%d", rc);
|
||||
sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
|
||||
|
||||
+4
-1
@@ -2809,7 +2809,10 @@ void sqlite3CompleteInsertion(
|
||||
|| pIdx->pNext==0
|
||||
|| pIdx->pNext->onError==OE_Replace );
|
||||
if( aRegIdx[i]==0 ) continue;
|
||||
if( pIdx->pPartIdxWhere ){
|
||||
if( pIdx->pPartIdxWhere || (update_flags && pIdx->bHasExpr) ){
|
||||
/* If this is a partial index, or an UPDATE of an index on an
|
||||
** expression, then the record register may be set to NULL to indicate
|
||||
** that no record should be inserted into this index. */
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
||||
+3
-2
@@ -528,11 +528,12 @@ 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
|
||||
|
||||
+2
-1
@@ -1136,7 +1136,8 @@ void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of changes in the most recent call to sqlite3_exec().
|
||||
** Return the number of changes in the most recently executed DML
|
||||
** statement.
|
||||
*/
|
||||
sqlite3_int64 sqlite3_changes64(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
|
||||
+3
-4
@@ -876,10 +876,10 @@ int sqlite3_deserialize(
|
||||
if( rc ) goto end_deserialize;
|
||||
db->init.iDb = (u8)iDb;
|
||||
db->init.reopenMemdb = 1;
|
||||
rc = sqlite3_step(pStmt);
|
||||
sqlite3_step(pStmt);
|
||||
db->init.reopenMemdb = 0;
|
||||
if( rc!=SQLITE_DONE ){
|
||||
rc = SQLITE_ERROR;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_deserialize;
|
||||
}
|
||||
p = memdbFromDbSchema(db, zSchema);
|
||||
@@ -900,7 +900,6 @@ int sqlite3_deserialize(
|
||||
}
|
||||
|
||||
end_deserialize:
|
||||
sqlite3_finalize(pStmt);
|
||||
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
|
||||
+35
-16
@@ -35,8 +35,15 @@
|
||||
# define SQLITE_MUTEX_NREF 0
|
||||
#endif
|
||||
|
||||
#if GCC_VERSION>0
|
||||
# define ALIGN128 __attribute__((aligned(128)))
|
||||
#else
|
||||
# define ALIGN128
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Each recursive mutex is an instance of the following structure.
|
||||
** Each SQLite mutex is an instance of the following structure.
|
||||
**
|
||||
*/
|
||||
struct sqlite3_mutex {
|
||||
pthread_mutex_t mutex; /* Mutex controlling the lock */
|
||||
@@ -151,19 +158,31 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
|
||||
** the same type number.
|
||||
*/
|
||||
static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
static sqlite3_mutex staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER(2),
|
||||
SQLITE3_MUTEX_INITIALIZER(3),
|
||||
SQLITE3_MUTEX_INITIALIZER(4),
|
||||
SQLITE3_MUTEX_INITIALIZER(5),
|
||||
SQLITE3_MUTEX_INITIALIZER(6),
|
||||
SQLITE3_MUTEX_INITIALIZER(7),
|
||||
SQLITE3_MUTEX_INITIALIZER(8),
|
||||
SQLITE3_MUTEX_INITIALIZER(9),
|
||||
SQLITE3_MUTEX_INITIALIZER(10),
|
||||
SQLITE3_MUTEX_INITIALIZER(11),
|
||||
SQLITE3_MUTEX_INITIALIZER(12),
|
||||
SQLITE3_MUTEX_INITIALIZER(13)
|
||||
/* Static mutexes - those with IDs of 2 or more...
|
||||
**
|
||||
** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
|
||||
** so that adjacent mutex objects are always on different cache lines
|
||||
** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
|
||||
** seems to work well for all contemporary processors. Experiments show
|
||||
** that 64 works just as well most of the time, but the internet says
|
||||
** that 128-byte alignment works better.
|
||||
*/
|
||||
static ALIGN128 union staticMutex {
|
||||
sqlite3_mutex m;
|
||||
char aSpacer[128];
|
||||
} aMutex[] = {
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(2) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(3) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(4) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(5) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(6) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(7) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(8) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(9) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(10) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(11) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(12) },
|
||||
{ .m = SQLITE3_MUTEX_INITIALIZER(13) },
|
||||
};
|
||||
sqlite3_mutex *p;
|
||||
switch( iType ){
|
||||
@@ -200,12 +219,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
}
|
||||
default: {
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
|
||||
if( iType-2<0 || iType-2>=ArraySize(aMutex) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = &staticMutexes[iType-2];
|
||||
p = &aMutex[iType-2].m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+87
-94
@@ -31,11 +31,29 @@
|
||||
*/
|
||||
#ifdef SQLITE_MUTEX_W32
|
||||
|
||||
#if MSVC_VERSION>0
|
||||
# define ALIGN128 __declspec(align(128))
|
||||
#else
|
||||
# define ALIGN128
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4324)
|
||||
/*
|
||||
** Each recursive mutex is an instance of the following structure.
|
||||
** Each SQLite mutex is an instance of the following structure.
|
||||
**
|
||||
** The ALIGN128 macro attempts to force 128-byte alignment on mutexes,
|
||||
** so that adjacent mutex objects are always on different cache lines
|
||||
** in the CPU. This is CPU-dependent, of course, but 128-byte alignment
|
||||
** seems to work well for all contemporary processors. Experiments show
|
||||
** that 64 works just as well most of the time, but the internet says
|
||||
** that 128-byte alignment works better.
|
||||
*/
|
||||
struct sqlite3_mutex {
|
||||
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
|
||||
struct sqlite3_mutex {
|
||||
union {
|
||||
CRITICAL_SECTION cs; /* The CRITICAL_SECTION mutex. id==1 */
|
||||
SRWLOCK srwl; /* The Slim reader/writer lock. id!=1 */
|
||||
} u;
|
||||
int id; /* Mutex type */
|
||||
#ifdef SQLITE_DEBUG
|
||||
volatile int nRef; /* Number of entrances */
|
||||
@@ -43,20 +61,7 @@ struct sqlite3_mutex {
|
||||
volatile LONG trace; /* True to trace changes */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** These are the initializer values used when declaring a "static" mutex
|
||||
** on Win32. It should be noted that all mutexes require initialization
|
||||
** on the Win32 platform.
|
||||
*/
|
||||
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
|
||||
0L, (DWORD)0, 0 }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
|
||||
#endif
|
||||
#pragma warning(pop)
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
@@ -67,13 +72,8 @@ static int winMutexHeld(sqlite3_mutex *p){
|
||||
return p->nRef!=0 && p->owner==GetCurrentThreadId();
|
||||
}
|
||||
|
||||
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
|
||||
return p->nRef==0 || p->owner!=tid;
|
||||
}
|
||||
|
||||
static int winMutexNotheld(sqlite3_mutex *p){
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
return winMutexNotheld2(p, tid);
|
||||
return p->nRef==0 || p->owner!=GetCurrentThreadId();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -95,41 +95,42 @@ void sqlite3MemoryBarrier(void){
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
** Static mutexes.
|
||||
**
|
||||
** The ALIGN128 macro on the static mutex array forces 128-byte alignment
|
||||
** on the mutexes so that adjacent mutex objects are always on different
|
||||
** cache lines in the CPU. This is CPU-dependent, of course, but 128-byte
|
||||
** alignment seems to work well for all contemporary processors.
|
||||
** Experiments show that 64 works just as well most of the time, but
|
||||
** the internet says that 128-byte alignment works better.
|
||||
*/
|
||||
static sqlite3_mutex winMutex_staticMutexes[] = {
|
||||
SQLITE3_MUTEX_INITIALIZER(2),
|
||||
SQLITE3_MUTEX_INITIALIZER(3),
|
||||
SQLITE3_MUTEX_INITIALIZER(4),
|
||||
SQLITE3_MUTEX_INITIALIZER(5),
|
||||
SQLITE3_MUTEX_INITIALIZER(6),
|
||||
SQLITE3_MUTEX_INITIALIZER(7),
|
||||
SQLITE3_MUTEX_INITIALIZER(8),
|
||||
SQLITE3_MUTEX_INITIALIZER(9),
|
||||
SQLITE3_MUTEX_INITIALIZER(10),
|
||||
SQLITE3_MUTEX_INITIALIZER(11),
|
||||
SQLITE3_MUTEX_INITIALIZER(12),
|
||||
SQLITE3_MUTEX_INITIALIZER(13)
|
||||
};
|
||||
|
||||
static ALIGN128 union staticMutexes {
|
||||
sqlite3_mutex m;
|
||||
char spacer[128];
|
||||
} aWindowsMutex[12];
|
||||
static int winMutex_isInit = 0;
|
||||
static int winMutex_isNt = -1; /* <0 means "need to query" */
|
||||
|
||||
/* As the winMutexInit() and winMutexEnd() functions are called as part
|
||||
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
|
||||
** "interlocked" magic used here is probably not strictly necessary.
|
||||
*/
|
||||
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
|
||||
static LONG volatile winMutex_lock = 0;
|
||||
|
||||
int sqlite3_win32_is_nt(void); /* os_win.c */
|
||||
void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
||||
|
||||
static int winMutexInit(void){
|
||||
/* The first to increment to 1 does actual initialization */
|
||||
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
|
||||
int i;
|
||||
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
||||
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
|
||||
for(i=0; i<ArraySize(aWindowsMutex); i++){
|
||||
sqlite3_mutex *p = &aWindowsMutex[i].m;
|
||||
p->id = i+2;
|
||||
InitializeSRWLock(&p->u.srwl);
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->nRef = 0;
|
||||
p->owner = 0;
|
||||
p->trace = 0;
|
||||
#endif
|
||||
}
|
||||
winMutex_isInit = 1;
|
||||
}else{
|
||||
@@ -147,10 +148,6 @@ static int winMutexEnd(void){
|
||||
** (which should be the last to shutdown.) */
|
||||
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
|
||||
if( winMutex_isInit==1 ){
|
||||
int i;
|
||||
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
||||
DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
|
||||
}
|
||||
winMutex_isInit = 0;
|
||||
}
|
||||
}
|
||||
@@ -219,18 +216,22 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
||||
p->trace = 1;
|
||||
#endif
|
||||
#endif
|
||||
InitializeCriticalSection(&p->mutex);
|
||||
if( iType==SQLITE_MUTEX_RECURSIVE ){
|
||||
InitializeCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
InitializeSRWLock(&p->u.srwl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
|
||||
if( iType-2<0 || iType-2>=ArraySize(aWindowsMutex) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = &winMutex_staticMutexes[iType-2];
|
||||
p = &aWindowsMutex[iType-2].m;
|
||||
#ifdef SQLITE_DEBUG
|
||||
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
|
||||
InterlockedCompareExchange(&p->trace, 1, 0);
|
||||
@@ -252,8 +253,10 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
||||
static void winMutexFree(sqlite3_mutex *p){
|
||||
assert( p );
|
||||
assert( p->nRef==0 && p->owner==0 );
|
||||
if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
DeleteCriticalSection(&p->mutex);
|
||||
if( p->id==SQLITE_MUTEX_FAST ){
|
||||
sqlite3_free(p);
|
||||
}else if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
DeleteCriticalSection(&p->u.cs);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
@@ -274,67 +277,56 @@ static void winMutexFree(sqlite3_mutex *p){
|
||||
** more than once, the behavior is undefined.
|
||||
*/
|
||||
static void winMutexEnter(sqlite3_mutex *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
assert( p );
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( p );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
||||
#else
|
||||
assert( p );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
|
||||
#endif
|
||||
assert( winMutex_isInit==1 );
|
||||
EnterCriticalSection(&p->mutex);
|
||||
if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
EnterCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
AcquireSRWLockExclusive(&p->u.srwl);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( p->nRef>0 || p->owner==0 );
|
||||
p->owner = tid;
|
||||
p->owner = GetCurrentThreadId();
|
||||
p->nRef++;
|
||||
if( p->trace ){
|
||||
OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
|
||||
tid, p->id, p, p->trace, p->nRef));
|
||||
GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int winMutexTry(sqlite3_mutex *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
int rc = SQLITE_BUSY;
|
||||
assert( p );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
|
||||
/*
|
||||
** The sqlite3_mutex_try() routine is very rarely used, and when it
|
||||
** is used it is merely an optimization. So it is OK for it to always
|
||||
** The sqlite3_mutex_try() routine is seldom used, and when it is
|
||||
** used it is merely an optimization. So it is OK for it to always
|
||||
** fail.
|
||||
**
|
||||
** The TryEnterCriticalSection() interface is only available on WinNT.
|
||||
** And some windows compilers complain if you try to use it without
|
||||
** first doing some #defines that prevent SQLite from building on Win98.
|
||||
** For that reason, we will omit this optimization for now. See
|
||||
** ticket #2685.
|
||||
*/
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
|
||||
assert( winMutex_isInit==1 );
|
||||
assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
|
||||
if( winMutex_isNt<0 ){
|
||||
winMutex_isNt = sqlite3_win32_is_nt();
|
||||
if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
rc = TryEnterCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
rc = TryAcquireSRWLockExclusive(&p->u.srwl);
|
||||
}
|
||||
assert( winMutex_isNt==0 || winMutex_isNt==1 );
|
||||
if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
|
||||
if( rc ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->owner = tid;
|
||||
p->owner = GetCurrentThreadId();
|
||||
p->nRef++;
|
||||
#endif
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = SQLITE_BUSY;
|
||||
}
|
||||
#else
|
||||
UNUSED_PARAMETER(p);
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
|
||||
tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
|
||||
OSTRACE((
|
||||
"TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
|
||||
GetCurrentThreadId(), p->id, p, p->trace, p->owner, p->nRef,
|
||||
sqlite3ErrName(rc)));
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
@@ -347,23 +339,24 @@ static int winMutexTry(sqlite3_mutex *p){
|
||||
** is not currently allocated. SQLite will never do either.
|
||||
*/
|
||||
static void winMutexLeave(sqlite3_mutex *p){
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
assert( p );
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( p->nRef>0 );
|
||||
assert( p->owner==tid );
|
||||
assert( p->owner==GetCurrentThreadId() );
|
||||
p->nRef--;
|
||||
if( p->nRef==0 ) p->owner = 0;
|
||||
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
|
||||
#endif
|
||||
assert( winMutex_isInit==1 );
|
||||
LeaveCriticalSection(&p->mutex);
|
||||
if( p->id==SQLITE_MUTEX_RECURSIVE ){
|
||||
LeaveCriticalSection(&p->u.cs);
|
||||
}else{
|
||||
ReleaseSRWLockExclusive(&p->u.srwl);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
|
||||
tid, p->id, p, p->trace, p->nRef));
|
||||
GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+317
-1553
File diff suppressed because it is too large
Load Diff
+1
-43
@@ -27,53 +27,11 @@
|
||||
# include <errno.h> /* amalgamator: dontcache */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows NT.
|
||||
**
|
||||
** We ought to be able to determine if we are compiling for Windows 9x or
|
||||
** Windows NT using the _WIN32_WINNT macro as follows:
|
||||
**
|
||||
** #if defined(_WIN32_WINNT)
|
||||
** # define SQLITE_OS_WINNT 1
|
||||
** #else
|
||||
** # define SQLITE_OS_WINNT 0
|
||||
** #endif
|
||||
**
|
||||
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
|
||||
** it ought to, so the above test does not work. We'll just assume that
|
||||
** everything is Windows NT unless the programmer explicitly says otherwise
|
||||
** by setting SQLITE_OS_WINNT to 0.
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
|
||||
# define SQLITE_OS_WINNT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with Windows CE - which has a much reduced
|
||||
** API.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
# define SQLITE_OS_WINCE 1
|
||||
#else
|
||||
# define SQLITE_OS_WINCE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For WinCE, some API function parameters do not appear to be declared as
|
||||
** volatile.
|
||||
*/
|
||||
#if SQLITE_OS_WINCE
|
||||
# define SQLITE_WIN32_VOLATILE
|
||||
#else
|
||||
# define SQLITE_WIN32_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
|
||||
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
|
||||
*/
|
||||
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \
|
||||
SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
|
||||
#if SQLITE_OS_WIN && SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
|
||||
# define SQLITE_OS_WIN_THREADS 1
|
||||
#else
|
||||
# define SQLITE_OS_WIN_THREADS 0
|
||||
|
||||
+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_NONE or PAGER_SHARED state and the lock held is less
|
||||
** in PAGER_OPEN or PAGER_READER 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 sqlite3PagerMalloc()
|
||||
** If the page size is changed, then this function uses sqlite3PageMalloc()
|
||||
** 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 after transitioning from PAGER_UNLOCK to
|
||||
** PAGER_SHARED state. It tests if there is a hot journal present in
|
||||
** This function is called while transitioning from PAGER_OPEN to a
|
||||
** higher 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:
|
||||
|
||||
@@ -1476,6 +1476,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
|
||||
if( A ){
|
||||
A->x.pList = pList;
|
||||
sqlite3ExprSetHeightAndFlags(pParse, A);
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
}
|
||||
|
||||
+38
-14
@@ -165,7 +165,7 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
|
||||
return 0;
|
||||
}
|
||||
z = sqlite3DbMallocRaw(pAccum->db, n);
|
||||
z = sqlite3_malloc(n);
|
||||
if( z==0 ){
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
|
||||
}
|
||||
@@ -623,11 +623,27 @@ void sqlite3_str_vappendf(
|
||||
|
||||
szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+10;
|
||||
if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
|
||||
if( sqlite3StrAccumEnlargeIfNeeded(pAccum, szBufNeeded) ){
|
||||
width = length = 0;
|
||||
break;
|
||||
if( szBufNeeded + pAccum->nChar >= pAccum->nAlloc ){
|
||||
if( pAccum->mxAlloc==0 && pAccum->accError==0 ){
|
||||
/* Unable to allocate space in pAccum, perhaps because it
|
||||
** is coming from sqlite3_snprintf() or similar. We'll have
|
||||
** to render into temporary space and the memcpy() it over. */
|
||||
bufpt = sqlite3_malloc(szBufNeeded);
|
||||
if( bufpt==0 ){
|
||||
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
|
||||
return;
|
||||
}
|
||||
zExtra = bufpt;
|
||||
}else if( sqlite3StrAccumEnlarge(pAccum, szBufNeeded)<szBufNeeded ){
|
||||
width = length = 0;
|
||||
break;
|
||||
}else{
|
||||
bufpt = pAccum->zText + pAccum->nChar;
|
||||
}
|
||||
}else{
|
||||
bufpt = pAccum->zText + pAccum->nChar;
|
||||
}
|
||||
bufpt = zOut = pAccum->zText + pAccum->nChar;
|
||||
zOut = bufpt;
|
||||
|
||||
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
|
||||
/* The sign in front of the number */
|
||||
@@ -728,14 +744,22 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
length = width;
|
||||
}
|
||||
pAccum->nChar += length;
|
||||
zOut[length] = 0;
|
||||
|
||||
/* Floating point conversions render directly into the output
|
||||
** buffer. Hence, don't just break out of the switch(). Bypass the
|
||||
** output buffer writing that occurs after the switch() by continuing
|
||||
** to the next character in the format string. */
|
||||
continue;
|
||||
if( zExtra==0 ){
|
||||
/* The result is being rendered directory into pAccum. This
|
||||
** is the command and fast case */
|
||||
pAccum->nChar += length;
|
||||
zOut[length] = 0;
|
||||
continue;
|
||||
}else{
|
||||
/* We were unable to render directly into pAccum because we
|
||||
** couldn't allocate sufficient memory. We need to memcpy()
|
||||
** the rendering (or some prefix thereof) into the output
|
||||
** buffer. */
|
||||
bufpt[0] = 0;
|
||||
bufpt = zExtra;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case etSIZE:
|
||||
if( !bArgList ){
|
||||
@@ -782,7 +806,7 @@ void sqlite3_str_vappendf(
|
||||
if( sqlite3StrAccumEnlargeIfNeeded(pAccum, nCopyBytes) ){
|
||||
break;
|
||||
}
|
||||
sqlite3_str_append(pAccum,
|
||||
sqlite3_str_append(pAccum,
|
||||
&pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
|
||||
precision -= nPrior;
|
||||
nPrior *= 2;
|
||||
@@ -1298,7 +1322,7 @@ void sqlite3_str_reset(StrAccum *p){
|
||||
** of its content, all in one call.
|
||||
*/
|
||||
void sqlite3_str_free(sqlite3_str *p){
|
||||
if( p ){
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
sqlite3_str_reset(p);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
+1
-3
@@ -836,9 +836,7 @@ lookupname_end:
|
||||
if( cnt==1 ){
|
||||
assert( pNC!=0 );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pParse->db->xAuth
|
||||
&& (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
|
||||
){
|
||||
if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){
|
||||
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -7324,6 +7324,7 @@ static SQLITE_NOINLINE void existsToJoin(
|
||||
&& !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
|
||||
&& ALWAYS(p->pSrc!=0)
|
||||
&& p->pSrc->nSrc<BMS
|
||||
&& (p->pLimit==0 || p->pLimit->pRight==0)
|
||||
){
|
||||
if( pWhere->op==TK_AND ){
|
||||
Expr *pRight = pWhere->pRight;
|
||||
@@ -7371,7 +7372,6 @@ static SQLITE_NOINLINE void existsToJoin(
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
existsToJoin(pParse, p, pSubWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1003
-349
File diff suppressed because it is too large
Load Diff
+20
-8
@@ -2960,8 +2960,9 @@ 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. ^These routines return 1 if the input string
|
||||
** appears to be a complete SQL statement. ^A statement is judged to be
|
||||
** 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
|
||||
** 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
|
||||
@@ -2969,11 +2970,21 @@ 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.
|
||||
**
|
||||
** ^These routines return 0 if the statement is incomplete. ^If a
|
||||
** memory allocation fails, then SQLITE_NOMEM is returned.
|
||||
** ^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 do not parse the SQL statements and thus
|
||||
** will not detect syntactically incorrect SQL.
|
||||
** 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.
|
||||
**
|
||||
** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
|
||||
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
|
||||
@@ -2981,14 +2992,15 @@ 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 input to [sqlite3_complete()] must be a zero-terminated
|
||||
** UTF-8 string.
|
||||
** The X input to [sqlite3_complete(X)] and [sqlite3_incomplete(X)]
|
||||
** 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,6 +376,8 @@ 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*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -719,6 +721,8 @@ 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)
|
||||
|
||||
+52
-1
@@ -202,7 +202,7 @@
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
|
||||
** Reuse the STATIC_VFS1 for mutex access to sqlite3_temp_directory.
|
||||
*/
|
||||
#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
|
||||
|
||||
@@ -4612,6 +4612,57 @@ Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
|
||||
/*
|
||||
** Assuming zIn points to the first byte of a UTF-8 character,
|
||||
** advance zIn to point to the first byte of the next UTF-8 character.
|
||||
**
|
||||
** # Dividing malformed UTF-8 into characters (tag-20260418-01)
|
||||
**
|
||||
** If a text input is malformed UTF-8, SQLite does not make any guarantees
|
||||
** about how the bytes are divided up into characters. The system promises
|
||||
** to not overflow an array or cause other memory errors when presented
|
||||
** with malformed UTF-8. And it promises to preserve the specific
|
||||
** sequence of bytes as long as no conversion occur. But beyond that,
|
||||
** there are no guarantees. Results can vary from one version to the
|
||||
** next.
|
||||
**
|
||||
** The SQLITE_SKIP_UTF8 macro below is one technique for dividing UTF-8
|
||||
** into characters. The length() and substr() SQL functions use a
|
||||
** different technique when searching across multiple characters, a
|
||||
** technique that exchanges a subtraction for comparison of z and results
|
||||
** in faster machine code on some compilers and architectures. The code
|
||||
** in substr() to skip over p1 characters goes something like this:
|
||||
**
|
||||
** for( ; p1>0; p1--){
|
||||
** // vvvv--- tag-20260418-01
|
||||
** if( (u8)(z[0]-1)<(0x80-1) ){
|
||||
** z++;
|
||||
** }else if( z[0]==0 ){
|
||||
** break;
|
||||
** }else{
|
||||
** do{ z++; }while( (z[0]&0xc0)==0x80 );
|
||||
** }
|
||||
** }
|
||||
**
|
||||
** In valid UTF-8, multibyte characters always begin with a byte with the
|
||||
** two most significant bits set and that is followed by one or more bytes
|
||||
** for which the two most significant bits are 10. In other words:
|
||||
**
|
||||
** First byte: (BYTE & 0xc0)==0xc0
|
||||
** Following bytes: (BYTE & 0xc0)==0x80
|
||||
**
|
||||
** What to do if the input byte sequence contain a "following byte" that
|
||||
** is not preceded by a "first byte"? How many characters are in the
|
||||
** byte sequence: 0x61 0x81 0x82 0x7a? 3 or 4 or something else?
|
||||
**
|
||||
** If you use the macro below, the answer will be 4. If you use the code
|
||||
** snippet demonstrated at tag-20260418-01, then answer is 3. If you
|
||||
** use a variant of tag-20260418-01 where the constant of comparison is
|
||||
** 0xc0-1 instead of 0x80-1 then the answer is again 4. The key point is
|
||||
** that because the input is malformed UTF-8, so is no "correct" answer.
|
||||
** SQLite is free to use either value.
|
||||
**
|
||||
** It turns out that GCC 13.3.0 is able to generate faster code (at least
|
||||
** on x86-64) if the constant at tag-20260418-01 is (0x80-1). If you make
|
||||
** that constant (0xc0-1) instead, gcc 13.3.0 generates code that runs slower.
|
||||
** So the (0x80-1) constant is used for substr() and length().
|
||||
*/
|
||||
#define SQLITE_SKIP_UTF8(zIn) { \
|
||||
if( (*(zIn++))>=0xc0 ){ \
|
||||
|
||||
+20
-8
@@ -19,8 +19,15 @@
|
||||
#include <stdarg.h>
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
#include <math.h>
|
||||
|
||||
/* Work around a bug in older Microsoft compilers
|
||||
** Forum post 2026-04-10T06:33:11z */
|
||||
#if !defined(INFINITY) && defined(_MSC_VER)
|
||||
# define INFINITY HUGE_VAL
|
||||
#endif
|
||||
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
/*
|
||||
** Calls to sqlite3FaultSim() are used to simulate a failure during testing,
|
||||
** or to bypass normal error detection during testing in order to let
|
||||
@@ -458,15 +465,20 @@ u8 sqlite3StrIHash(const char *z){
|
||||
return h;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_DISABLE_INTRINSIC) \
|
||||
&& (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || \
|
||||
(defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
|
||||
#define SQLITE_USE_UINT128
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Two inputs are multiplied to get a 128-bit result. Write the
|
||||
** lower 64-bits of the result into *pLo, and return the high-order
|
||||
** 64 bits.
|
||||
*/
|
||||
static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
|
||||
#if (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
|
||||
&& !defined(SQLITE_DISABLE_INTRINSIC)
|
||||
#if defined(SQLITE_USE_UINT128)
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
*pLo = (u64)r;
|
||||
return (u64)(r>>64);
|
||||
@@ -500,9 +512,7 @@ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
|
||||
** The lower 64 bits of A*B are discarded.
|
||||
*/
|
||||
static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
|
||||
#if (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \
|
||||
&& !defined(SQLITE_DISABLE_INTRINSIC)
|
||||
#if defined(SQLITE_USE_UINT128)
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
r += ((__uint128_t)aLo * b) >> 32;
|
||||
*pLo = (r>>32)&0xffffffff;
|
||||
@@ -540,6 +550,8 @@ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SQLITE_USE_UINT128
|
||||
|
||||
/*
|
||||
** Return a u64 with the N-th bit set.
|
||||
*/
|
||||
@@ -778,7 +790,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
u64 pwr10h, x, hi, lo, sticky, u, m;
|
||||
double r;
|
||||
if( p<POWERSOF10_FIRST ) return 0.0;
|
||||
if( p>POWERSOF10_LAST ) return INFINITY;
|
||||
if( p>POWERSOF10_LAST ) return (double)INFINITY;
|
||||
b = 64 - countLeadingZeros(d);
|
||||
lp = pwr10to2(p);
|
||||
e = 53 - b - lp;
|
||||
@@ -808,7 +820,7 @@ static double sqlite3Fp10Convert2(u64 d, int p){
|
||||
e -= adj;
|
||||
}
|
||||
m = (u + 1 + ((u>>2)&1)) >> 2;
|
||||
if( e<=(-972) ) return INFINITY;
|
||||
if( e<=(-972) ) return (double)INFINITY;
|
||||
if((m & U64_BIT(52)) != 0){
|
||||
m = (m & ~U64_BIT(52)) | ((u64)(1075-e)<<52);
|
||||
}
|
||||
|
||||
+52
-7
@@ -708,7 +708,6 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** For OP_Column, factor out the case where content is loaded from
|
||||
** overflow pages, so that the code to implement this case is separate
|
||||
@@ -794,6 +793,40 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
|
||||
** open on an index. If the current index entry matches the blob value in
|
||||
** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
|
||||
**
|
||||
** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
|
||||
** case as well.
|
||||
*/
|
||||
static SQLITE_NOINLINE int vdbeIndexKeyCompare(
|
||||
BtCursor *pCsr, /* Cursor to compare key to */
|
||||
Mem *pMem,
|
||||
int *pRc
|
||||
){
|
||||
int ret = 0;
|
||||
u32 nKey = 0;
|
||||
|
||||
assert( pMem->flags & (MEM_Blob|MEM_Null) );
|
||||
nKey = sqlite3BtreePayloadSize(pCsr);
|
||||
if( nKey==(u32)pMem->n && ALWAYS((pMem->flags & MEM_Blob)!=0) ){
|
||||
/* This code could just use sqlite3BtreePayloadFetch(). But calling that
|
||||
** function here apparently prevents compilers from inlining it in other,
|
||||
** more performance critical, places. So this code uses
|
||||
** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
|
||||
** handles the case where the index record uses overflow pages. */
|
||||
Mem m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
*pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
|
||||
ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
|
||||
sqlite3VdbeMemReleaseMalloc(&m);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** Send a "statement aborts" message to the error log.
|
||||
*/
|
||||
@@ -6622,15 +6655,20 @@ case OP_SorterInsert: { /* in2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IdxDelete P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P2@P3]
|
||||
/* Opcode: IdxDelete P1 P2 P3 P4 P5
|
||||
** Synopsis: key=r[P2@P5]
|
||||
**
|
||||
** The content of P3 registers starting at register P2 form
|
||||
** The content of P5 registers starting at register P2 form
|
||||
** an unpacked index key. This opcode removes that entry from the
|
||||
** index opened by cursor P1.
|
||||
**
|
||||
** P4 is a pointer to an Index structure.
|
||||
**
|
||||
** If P3 is non-zero, it is the register number of a register holding
|
||||
** a record that will be inserted into this index. If that record is
|
||||
** identical to the one that would be deleted by this instruction,
|
||||
** skip the delete and set register P3 to NULL.
|
||||
**
|
||||
** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
|
||||
** and not in writable_schema mode.
|
||||
*/
|
||||
@@ -6640,8 +6678,8 @@ case OP_IdxDelete: {
|
||||
int res;
|
||||
UnpackedRecord r;
|
||||
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
|
||||
assert( pOp->p5>0 );
|
||||
assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
@@ -6650,7 +6688,7 @@ case OP_IdxDelete: {
|
||||
pCrsr = pC->uc.pCursor;
|
||||
assert( pCrsr!=0 );
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = (u16)pOp->p3;
|
||||
r.nField = pOp->p5;
|
||||
r.default_rc = 0;
|
||||
r.aMem = &aMem[pOp->p2];
|
||||
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
|
||||
@@ -6669,6 +6707,13 @@ case OP_IdxDelete: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
|
||||
if( rc ) goto abort_due_to_error;
|
||||
sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
assert( pC->deferredMoveto==0 );
|
||||
|
||||
+7
-8
@@ -1900,7 +1900,6 @@ 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;
|
||||
@@ -5450,12 +5449,12 @@ static int vdbeIsMatchingIndexKey(
|
||||
){
|
||||
u8 *aRec = 0;
|
||||
u32 nRec = 0;
|
||||
Mem mem;
|
||||
Mem m;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
memset(&mem, 0, sizeof(mem));
|
||||
mem.enc = p->pKeyInfo->enc;
|
||||
mem.db = p->pKeyInfo->db;
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.enc = p->pKeyInfo->enc;
|
||||
m.db = p->pKeyInfo->db;
|
||||
nRec = sqlite3BtreePayloadSize(pCur);
|
||||
if( nRec>0x7fffffff ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
@@ -5497,9 +5496,9 @@ static int vdbeIsMatchingIndexKey(
|
||||
if( (idxRec+nSerial)>nRec ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
sqlite3VdbeSerialGet(&aRec[idxRec], iSerial, &mem);
|
||||
if( vdbeSkipField(mask, ii, &p->aMem[ii], &mem, bInt)==0 ){
|
||||
res = sqlite3MemCompare(&mem, &p->aMem[ii], p->pKeyInfo->aColl[ii]);
|
||||
sqlite3VdbeSerialGet(&aRec[idxRec], iSerial, &m);
|
||||
if( vdbeSkipField(mask, ii, &p->aMem[ii], &m, bInt)==0 ){
|
||||
res = sqlite3MemCompare(&m, &p->aMem[ii], p->pKeyInfo->aColl[ii]);
|
||||
if( res!=0 ) break;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-22
@@ -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 iaCur[1] gets the cursor used by an auxiliary index.
|
||||
** table and aiCur[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.
|
||||
**
|
||||
@@ -7583,27 +7583,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
|
||||
}
|
||||
if( pTabList->a[pLevel->iFrom].fg.fromExists
|
||||
&& (i==pWInfo->nLevel-1
|
||||
|| pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0)
|
||||
){
|
||||
/* This is an EXISTS-to-JOIN optimization which is either the
|
||||
** inner-most loop, or the inner-most of a group of nested
|
||||
** EXISTS-to-JOIN optimization loops. If this loop sees a successful
|
||||
** row, it should break out of itself as well as other EXISTS-to-JOIN
|
||||
** loops in which is is directly nested. */
|
||||
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
|
||||
while( nOuter<i ){
|
||||
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
|
||||
nOuter++;
|
||||
}
|
||||
testcase( nOuter>0 );
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
|
||||
if( nOuter ){
|
||||
VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i));
|
||||
}else{
|
||||
VdbeComment((v, "EXISTS break %d", i));
|
||||
}
|
||||
if( pTabList->a[pLevel->iFrom].fg.fromExists ){
|
||||
/* This is an EXISTS-to-JOIN optimization loop. If this loop sees a
|
||||
** successful row, it should break out of itself. */
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
||||
VdbeComment((v, "EXISTS break %d", i));
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
||||
if( pLevel->op!=OP_Noop ){
|
||||
|
||||
+9
-2
@@ -2297,7 +2297,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
|
||||
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
|
||||
*/
|
||||
if( pWInfo->nLevel>1 ){
|
||||
if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){
|
||||
int nNotReady; /* The number of notReady tables */
|
||||
SrcItem *origSrc; /* Original list of tables */
|
||||
nNotReady = pWInfo->nLevel - iLevel - 1;
|
||||
@@ -2310,6 +2310,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
for(k=1; k<=nNotReady; k++){
|
||||
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
|
||||
}
|
||||
|
||||
/* Clear the fromExists flag on the OR-optimized table entry so that
|
||||
** the calls to sqlite3WhereEnd() do not code early-exits after the
|
||||
** first row is visited. The early exit applies to this table's
|
||||
** overall loop - including the multiple OR branches and any WHERE
|
||||
** conditions not passed to the sub-loops - not to the sub-loops. */
|
||||
pOrTab->a[0].fg.fromExists = 0;
|
||||
}else{
|
||||
pOrTab = pWInfo->pTabList;
|
||||
}
|
||||
@@ -2553,7 +2560,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
assert( pLevel->op==OP_Return );
|
||||
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
||||
|
||||
if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
|
||||
if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); }
|
||||
if( !untestedTerms ) disableTerm(pLevel, pTerm);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
|
||||
|
||||
@@ -243,5 +243,53 @@ do_execsql_test 11.2.3 {
|
||||
do_execsql_test 11.2.2 {ALTER TABLE t2 ALTER b SET NOT NULL --new cons
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 12.0 {
|
||||
CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER,
|
||||
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
ALTER TABLE Test DROP CONSTRAINT BooleanZeroOrOne
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {
|
||||
{CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER)}
|
||||
}
|
||||
|
||||
do_execsql_test 12.3 {
|
||||
DROP TABLE Test;
|
||||
CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER,
|
||||
CONSTRAINT "BooleanZeroOrOne" CHECK ("IsActive" IN (0, 1))
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 12.4 {
|
||||
ALTER TABLE Test DROP CONSTRAINT "BooleanZeroOrOne"
|
||||
}
|
||||
|
||||
do_execsql_test 12.5 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {
|
||||
{CREATE TABLE "Test" (
|
||||
"IsActive" INTEGER)}
|
||||
}
|
||||
|
||||
do_execsql_test 12.6 {
|
||||
CREATE TABLE t1(a, b CONSTRAINT "a""b" CHECK (b IS NOT NULL));
|
||||
}
|
||||
|
||||
do_execsql_test 12.7 {
|
||||
ALTER TABLE t1 DROP CONSTRAINT "a""b"
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+4
-4
@@ -97,7 +97,7 @@ do_test badutf-3.2 {
|
||||
} {0 {x 3}}
|
||||
do_test badutf-3.3 {
|
||||
sqlite3_exec db {SELECT length('%7f%80%81') AS x}
|
||||
} {0 {x 3}}
|
||||
} {0 {x 2}}
|
||||
do_test badutf-3.4 {
|
||||
sqlite3_exec db {SELECT length('%61%c0') AS x}
|
||||
} {0 {x 2}}
|
||||
@@ -109,13 +109,13 @@ do_test badutf-3.6 {
|
||||
} {0 {x 1}}
|
||||
do_test badutf-3.7 {
|
||||
sqlite3_exec db {SELECT length('%80%80%80%80%80%80%80%80%80%80') AS x}
|
||||
} {0 {x 10}}
|
||||
} {0 {x 1}}
|
||||
do_test badutf-3.8 {
|
||||
sqlite3_exec db {SELECT length('%80%80%80%80%80%f0%80%80%80%80') AS x}
|
||||
} {0 {x 6}}
|
||||
} {0 {x 2}}
|
||||
do_test badutf-3.9 {
|
||||
sqlite3_exec db {SELECT length('%80%80%80%80%80%f0%80%80%80%ff') AS x}
|
||||
} {0 {x 7}}
|
||||
} {0 {x 3}}
|
||||
|
||||
do_test badutf-4.1 {
|
||||
sqlite3_exec db {SELECT hex(trim('%80%80%80%f0%80%80%80%ff','%80%ff')) AS x}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -476,6 +476,29 @@ catch { optimization_control db exists-to-join 0 }
|
||||
db cache flush
|
||||
do_execsql_test 9.6 $Q {{big string value}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Forum post 2026-04-21T10:57:09Z
|
||||
do_execsql_test 9.7.1 {
|
||||
DROP TABLE t3;
|
||||
CREATE TABLE t3(x INT, y INT);
|
||||
CREATE TABLE t4(z INT);
|
||||
INSERT INTO t3 VALUES (1,0),(2,2),(3,3);
|
||||
INSERT INTO t4 VALUES (4),(5);
|
||||
}
|
||||
set Q {
|
||||
SELECT x FROM t3
|
||||
WHERE EXISTS(SELECT 1 FROM t4 WHERE z>y)
|
||||
LIMIT 1 OFFSET 1
|
||||
}
|
||||
catch { optimization_control db all 1 }
|
||||
db cache flush
|
||||
do_execsql_test 9.7.2 $Q {2}
|
||||
catch { optimization_control db exists-to-join 0 }
|
||||
db cache flush
|
||||
do_execsql_test 9.7.3 $Q {2}
|
||||
catch { optimization_control db all 1 }
|
||||
db cache flush
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -514,4 +537,96 @@ do_execsql_test 11.1 {
|
||||
GROUP BY id;
|
||||
} {1 p1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 12.0 {
|
||||
CREATE TABLE t2(id INT, data INT);
|
||||
CREATE TABLE t3(amount INT);
|
||||
|
||||
INSERT INTO t2 VALUES (1,0),(2,0);
|
||||
INSERT INTO t3 VALUES (1),(1);
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
SELECT * FROM t2
|
||||
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
|
||||
} {
|
||||
1 0
|
||||
2 0
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
SELECT * FROM t2
|
||||
WHERE EXISTS (SELECT 1 FROM t3 WHERE t3.amount > t2.data)
|
||||
LIMIT 2 OFFSET 3
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 13.0 {
|
||||
CREATE TABLE t1(b,c);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE TABLE t3(p,q);
|
||||
|
||||
INSERT INTO t1 VALUES(7,10);
|
||||
INSERT INTO t2 VALUES(1,1), (4,7);
|
||||
INSERT INTO t3 VALUES(4,7);
|
||||
|
||||
PRAGMA automatic_index = 0;
|
||||
}
|
||||
|
||||
do_execsql_test 13.1 {
|
||||
SELECT * FROM t1 WHERE EXISTS (
|
||||
SELECT 1 FROM t2
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM t3 WHERE t3.p=t2.x AND t3.q=t1.b
|
||||
)
|
||||
)
|
||||
} {7 10}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Forum post https://sqlite.org/forum/forumpost/c8b205720c
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 14.1.0 {
|
||||
CREATE TABLE t(n INTEGER, parent INTEGER);
|
||||
CREATE INDEX idx ON t(parent);
|
||||
INSERT INTO t VALUES (1, NULL);
|
||||
INSERT INTO t VALUES (10, NULL);
|
||||
}
|
||||
|
||||
do_execsql_test 14.1.1 {
|
||||
SELECT count(*) FROM t b
|
||||
WHERE (b.parent IS NULL OR b.parent = 99)
|
||||
AND 5 <= +b.n
|
||||
} 1
|
||||
|
||||
do_execsql_test 14.1.2 {
|
||||
SELECT 'match' WHERE EXISTS (
|
||||
SELECT 1 FROM t b
|
||||
WHERE (b.parent IS NULL OR b.parent = 99)
|
||||
AND 5 <= +b.n
|
||||
)
|
||||
} {match}
|
||||
|
||||
do_execsql_test 14.2.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(20, 20);
|
||||
|
||||
CREATE TABLE t2(c, d);
|
||||
CREATE INDEX t2c ON t2(c);
|
||||
CREATE INDEX t2d ON t2(d);
|
||||
|
||||
INSERT INTO t2 VALUES(20, -1);
|
||||
INSERT INTO t2 VALUES(20, 0);
|
||||
}
|
||||
|
||||
do_execsql_test 14.2.2 {
|
||||
SELECT * FROM t1 WHERE EXISTS (
|
||||
SELECT 1 FROM t2 WHERE (c=a OR d=a) AND (d+1)>0
|
||||
)
|
||||
} {20 20}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -41,5 +41,26 @@ do_faultsim_test 2 -faults oom* -prep {
|
||||
faultsim_test_result {0 ABCDEF}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
PRAGMA page_size=1024;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE INDEX i1 ON t1( hex(b) );
|
||||
INSERT INTO t1 VALUES(10, randomblob(500));
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 3 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
UPDATE t1 SET b=randomblob(500);
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# 2026-04-23
|
||||
#
|
||||
# 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 omitting the update of an index when the new value is the
|
||||
# same as the old.
|
||||
#
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix expridx2
|
||||
|
||||
# This test requires wal mode, but the journaltest permutation installs
|
||||
# a custom VFS that does not support wal mode.
|
||||
if {[permutation]=="journaltest"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
|
||||
INSERT INTO t1 VALUES(1, '{a: 10, b: 20, c: 30}');
|
||||
INSERT INTO t1 VALUES(2, '{a: 11, b: 21, c: 31}');
|
||||
INSERT INTO t1 VALUES(3, '{a: 12, b: 22, c: 32}');
|
||||
INSERT INTO t1 VALUES(4, '{a: 13, b: 23, c: 33}');
|
||||
|
||||
CREATE INDEX t1a ON t1( (b->>'a') );
|
||||
CREATE INDEX t1b ON t1( (b->>'b') );
|
||||
CREATE INDEX t1c ON t1( (b->>'c') );
|
||||
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE INDEX t2b ON t2( b );
|
||||
INSERT INTO t2 VALUES(1, 1, 1);
|
||||
INSERT INTO t2 VALUES(2, 2, 2);
|
||||
INSERT INTO t2 VALUES(3, 3, 3);
|
||||
INSERT INTO t2 VALUES(4, 4, 4);
|
||||
} {wal}
|
||||
|
||||
proc nWrite {sql} {
|
||||
sqlite3_db_status db CACHE_WRITE 1
|
||||
execsql $sql
|
||||
lindex [sqlite3_db_status db CACHE_WRITE 0] 1
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
nWrite { UPDATE t1 SET b = json_set(b, '$.a', b->>'a' + 1) }
|
||||
} {2}
|
||||
|
||||
do_test 1.2 {
|
||||
nWrite {
|
||||
UPDATE t1 SET b = json_set(
|
||||
json_set(b, '$.a', b->>'a' + 1),
|
||||
'$.b', b->>'b' + 1
|
||||
);
|
||||
}
|
||||
} {3}
|
||||
|
||||
do_test 1.3 {
|
||||
nWrite {
|
||||
UPDATE t1 SET b = '{a:1, b:2, c:3}' WHERE rowid=1;
|
||||
}
|
||||
} {4}
|
||||
|
||||
integrity_check 1.4
|
||||
|
||||
do_test 1.5 {
|
||||
nWrite { UPDATE t2 SET b = b+1, c=c+1 }
|
||||
} {2}
|
||||
|
||||
do_test 1.6 {
|
||||
nWrite { UPDATE t2 SET b = b, c=c+1 }
|
||||
} {2}
|
||||
|
||||
do_test 1.7 {
|
||||
nWrite { UPDATE t2 SET c=c+1 }
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -172,6 +172,7 @@ static struct GlobalVars {
|
||||
extern int sqlite3_vt02_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_randomjson_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_series_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_analyze_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_base64_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_base85_init(sqlite3*,char**,void*);
|
||||
extern int sqlite3_completion_init(sqlite3*,char**,void*);
|
||||
@@ -1393,6 +1394,7 @@ int runCombinedDbSqlInput(
|
||||
/* Activate extensions */
|
||||
sqlite3_randomjson_init(cx.db, 0, 0);
|
||||
sqlite3_series_init(cx.db, 0, 0);
|
||||
sqlite3_analyze_init(cx.db, 0, 0);
|
||||
sqlite3_base64_init(cx.db, 0, 0);
|
||||
sqlite3_base85_init(cx.db, 0, 0);
|
||||
sqlite3_completion_init(cx.db, 0, 0);
|
||||
|
||||
+17
-1
@@ -30,12 +30,19 @@ tvfs filter xWrite
|
||||
tvfs script write_cb
|
||||
|
||||
set ::trigger_interrupt 0
|
||||
set ::dbpointer ""
|
||||
proc write_cb {method args} {
|
||||
set filename [lindex $args 0]
|
||||
if {[file tail $filename]=="test.db" && $::trigger_interrupt} {
|
||||
if {$::trigger_interrupt} {
|
||||
incr ::trigger_interrupt -1
|
||||
if {$::trigger_interrupt==0} { sqlite3_interrupt db }
|
||||
if {$::trigger_interrupt==0} {
|
||||
if {$::dbpointer!=""} {
|
||||
sqlite3_interrupt $::dbpointer
|
||||
} else {
|
||||
sqlite3_interrupt db
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
@@ -110,8 +117,17 @@ db_save_and_close
|
||||
db_restore_and_reopen
|
||||
do_test 3.1.1 {
|
||||
set ::trigger_interrupt 10
|
||||
|
||||
# Set dbpointer here so that the write-callback can use the (sqlite3*)
|
||||
# pointer with sqlite3_interrupt() directly instead of looking up the
|
||||
# command. On at least some versions of Tcl9, looking up a command from
|
||||
# within Tcl_DeleteCommand apparently returns a bad pointer.
|
||||
#
|
||||
set ::dbpointer [sqlite3_connection_pointer db]
|
||||
db eval { SELECT * FROM sqlite_master }
|
||||
db close
|
||||
set ::dbpointer ""
|
||||
|
||||
set {} {}
|
||||
} {}
|
||||
do_test 3.1.2 {
|
||||
|
||||
@@ -280,4 +280,65 @@ do_test 900 {
|
||||
} 1
|
||||
dbempty close
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Make sure a database cannot be overwritten by deserialize() if
|
||||
# there is an open transaction on it.
|
||||
#
|
||||
do_execsql_test 1000 {
|
||||
CREATE TABLE t(x);
|
||||
INSERT INTO t VALUES(1),(2);
|
||||
}
|
||||
|
||||
set blob [db serialize main]
|
||||
|
||||
do_test 1010 {
|
||||
set seen 0
|
||||
list [catch {
|
||||
db eval {SELECT x FROM t} {
|
||||
incr seen
|
||||
if {$seen == 1} {
|
||||
db deserialize main $blob
|
||||
}
|
||||
}
|
||||
} msg] $msg
|
||||
} {1 {unable to set MEMDB content}}
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
do_test 1020 {
|
||||
set seen 0
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 2
|
||||
set res [list [catch {
|
||||
db deserialize main $blob
|
||||
} msg] $msg]
|
||||
B finish
|
||||
set res
|
||||
} {1 {unable to set MEMDB content}}
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that things work if the destination database of a backup is
|
||||
# overwritten using sqlite3_deserialize() between sqlite3_backup_init()
|
||||
# and the first call to sqlite3_backup_step(). Forum post 15d82885e2.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 1100 {
|
||||
CREATE TABLE t(x);
|
||||
INSERT INTO t VALUES(1),(2);
|
||||
}
|
||||
|
||||
set blob [db serialize main]
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
do_test 1110 {
|
||||
set seen 0
|
||||
sqlite3_backup B db2 main db main
|
||||
db2 deserialize main $blob
|
||||
B step 2
|
||||
B finish
|
||||
} {SQLITE_OK}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
# This script is used to test certain output redirection commands
|
||||
# in the CLI, specifically:
|
||||
#
|
||||
# .www
|
||||
# .once -w
|
||||
# .output -w
|
||||
# .once -e
|
||||
# .ooutput -e
|
||||
# .excel
|
||||
# .once -x
|
||||
# .output -x
|
||||
#
|
||||
# Because of system interactions it is difficult to test these
|
||||
# commands automatically. They must be tested manually, with the
|
||||
# aid of this script.
|
||||
#
|
||||
# To run the test:
|
||||
#
|
||||
# 1. Be on a console of the machine under test (not on ssh).
|
||||
# 2. Run "./sqlite3 test/output-redir-test.txt" or similar.
|
||||
# 3. Verify that all the right pop-ups appear. More information
|
||||
# on what popups to expect appears on the console output.
|
||||
#
|
||||
.print "Expect to see 8 output pop-ups:
|
||||
.print " * 3 new tabs in your web-browser"
|
||||
.print " * 2 editor windows"
|
||||
.print " * 3 spreadsheets"
|
||||
.print "There is a 2-second pause between tests. Wait until"
|
||||
.print "prompted to verify results...."
|
||||
.print ""
|
||||
.print "Running web-browser tests first..."
|
||||
.mode box
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES
|
||||
('Web-browser test 1 of 3'),
|
||||
('Test for the ".www" commmand.');
|
||||
.www
|
||||
SELECT * FROM t1;
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Web-browser test 2 of 3'),
|
||||
('Test for the ".once -w" commmand.');
|
||||
.once -w
|
||||
SELECT * FROM t1;
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Web-browser test 3 of 3'),
|
||||
('Test for the ".output -w" commmand.'),
|
||||
('Confirm additional text below.');
|
||||
.output -w
|
||||
SELECT * FROM t1;
|
||||
.print "This test should also appear after the table."
|
||||
.print "in the web-browser output".
|
||||
.output
|
||||
|
||||
.print "Web-browser tests are done. Starting editor tests."
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Editor test 1 of 2'),
|
||||
('Test for the ".once -e" commmand.');
|
||||
.once -e
|
||||
SELECT * FROM t1;
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Editor test 2 of 2'),
|
||||
('Test for the ".output -e" commmand.'),
|
||||
('Confirm additional text below.');
|
||||
.output -e
|
||||
SELECT * FROM t1;
|
||||
.print "This test should also appear after the table."
|
||||
.print "in the pop-up editor window.".
|
||||
.output
|
||||
.print "Pop-up editor tests are done. Starting spreadsheed tests"
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Spreadsheet test 1 of 3'),
|
||||
('Test for the ".excel" commmand.');
|
||||
.excel
|
||||
SELECT * FROM t1;
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Spreadsheet test 2 of 3'),
|
||||
('Test for the ".once -x" commmand.');
|
||||
.once -x
|
||||
SELECT * FROM t1;
|
||||
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES
|
||||
('Spreadsheet test 3 of 3'),
|
||||
('Test for the ".output -x" commmand.'),
|
||||
('Confirm additional text below.');
|
||||
.output -x
|
||||
SELECT * FROM t1;
|
||||
.print "This test should also appear after the table."
|
||||
.print "in the spreadsheet output".
|
||||
.output
|
||||
|
||||
.print "All tests are done. You may now verify the results."
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
#!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 --glob <<END
|
||||
Main prompt: '*/A*/f*-> '
|
||||
Continuation: '/B*/C*-> '
|
||||
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 --glob <<END
|
||||
Main prompt: '*/A*/f*> '
|
||||
Continuation: '/B*/C*> '
|
||||
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 --glob <<END
|
||||
Main prompt: 'show'
|
||||
Continuation: '/B*/C*> '
|
||||
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 --glob '*SQLite-3*test.db*-> ';
|
||||
.testcase 1001
|
||||
SELECT shell_prompt_test(NULL,'SELECT');
|
||||
.check --glob ' *;*-> ';
|
||||
.testcase 1002
|
||||
SELECT shell_prompt_test(NULL,'SELECT ((("',null,2);
|
||||
.check --glob ' *[ m]")));*-> ';
|
||||
.testcase 1003
|
||||
SELECT shell_prompt_test(NULL,'SELECT ((()[',null,2);
|
||||
.check --glob ' *[ m]]));*-> ';
|
||||
.testcase 1004
|
||||
SELECT shell_prompt_test(NULL,'SELECT ''',null,2);
|
||||
.check --glob " *[ m]';*-> ";
|
||||
.testcase 1005
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN',null,2);
|
||||
.check --glob " *[ m];END;*-> ";
|
||||
.testcase 1006
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((([',null,2);
|
||||
.check --glob " *[ m]])));END;*-> ";
|
||||
.testcase 1007
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((/*a(((''bc',
|
||||
null,2);
|
||||
.check --glob " *[ m][*]/));END;*-> ";
|
||||
.testcase 1008
|
||||
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;',null,2);
|
||||
.check --glob " *[ m]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 --glob '*SQLite-3.# *test.db*-> ';
|
||||
|
||||
.testcase 3000
|
||||
SELECT shell_prompt_test('(/A-/V)');
|
||||
.check --glob '(SQLite-3.#.#)'
|
||||
.testcase 3001
|
||||
SELECT shell_prompt_test('(/A-/v)');
|
||||
.check --glob '(SQLite-3.#)'
|
||||
.testcase 3002
|
||||
SELECT shell_prompt_test('(/A-/D%Y-%m-%dT%H:%M:%S/D)');
|
||||
.check --glob '(SQLite-20#-#-#T#:#:#)'
|
||||
|
||||
.testcase 4000
|
||||
.mode list -rowsep '' -escape ascii
|
||||
SELECT shell_prompt_test('</myes/:no/;>',NULL,':memory:');
|
||||
.check <yes>
|
||||
.testcase 4001
|
||||
.mode list -rowsep '' -escape ascii
|
||||
SELECT shell_prompt_test('</myes/:no/;>',NULL,'t1.db');
|
||||
.check <no>
|
||||
|
||||
.testcase 5000
|
||||
SELECT shell_prompt_test('abc/e[0mxyz',NULL,NULL,1);
|
||||
.check abc^A^[[0m^Bxyz
|
||||
.testcase 5001
|
||||
SELECT shell_prompt_test('abc/e[0mxyz',NULL,NULL,2);
|
||||
.check abc^[[0mxyz
|
||||
.testcase 5002
|
||||
SELECT shell_prompt_test('/e[0mxyz',NULL,NULL,1);
|
||||
.check ^A^[[0m^Bxyz
|
||||
.testcase 5003
|
||||
SELECT shell_prompt_test('abc/e[0m',NULL,NULL,1);
|
||||
.check abc^A^[[0m^B
|
||||
.testcase 5004
|
||||
SELECT shell_prompt_test('abc/e[1;32m/e[0m/e[/exyz',NULL,NULL,1);
|
||||
.check abc^A^[[1;32m^[[0m^B^[[^[xyz
|
||||
.testcase 5005
|
||||
SELECT shell_prompt_test('abc/e[1,32m/e[0m/e[/exyz',NULL,NULL,1);
|
||||
.check abc^[[1,32m^A^[[0m^B^[[^[xyz
|
||||
|
||||
# Additional tests for octal escapes
|
||||
#
|
||||
.testcase 6000
|
||||
SELECT shell_prompt_test('/7');
|
||||
.check ^G
|
||||
.testcase 6001
|
||||
SELECT shell_prompt_test('/78');
|
||||
.check ^G8
|
||||
.testcase 6002
|
||||
SELECT shell_prompt_test('/7//');
|
||||
.check ^G/
|
||||
.testcase 6003
|
||||
SELECT shell_prompt_test('/7/');
|
||||
.check ^G
|
||||
.testcase 6004
|
||||
SELECT shell_prompt_test('/57');
|
||||
.check /
|
||||
.testcase 6005
|
||||
SELECT shell_prompt_test('/578');
|
||||
.check /8
|
||||
.testcase 6006
|
||||
SELECT shell_prompt_test('/57//');
|
||||
.check //
|
||||
.testcase 6007
|
||||
SELECT shell_prompt_test('/57/');
|
||||
.check /
|
||||
.testcase 6008
|
||||
SELECT shell_prompt_test('/10');
|
||||
.check ^H
|
||||
.testcase 6009
|
||||
SELECT shell_prompt_test('/101');
|
||||
.check A
|
||||
.testcase 6010
|
||||
SELECT shell_prompt_test('/1011');
|
||||
.check A1
|
||||
.testcase 6011
|
||||
SELECT shell_prompt_test('/33[0');
|
||||
.check ^[[0
|
||||
|
||||
# The UNKNOWN() error is shown regardless of whether or not the
|
||||
# escape is part of an active branch.
|
||||
.testcase 6012
|
||||
SELECT shell_prompt_test('/x/z/:/y/;');
|
||||
.check 'UNKNOWN("/z")UNKNOWN("/y")'
|
||||
|
||||
# Additional tests of \001..\002 escapes
|
||||
#
|
||||
# Two or more disconneted ANSI escapes
|
||||
#
|
||||
.testcase 7000
|
||||
SELECT shell_prompt_test('a-/e[1m-/e[0m-z',null,null,1);
|
||||
.check a-^A^[[1m^B-^A^[[0m^B-z
|
||||
|
||||
# Empty parameter
|
||||
.testcase 7001
|
||||
SELECT shell_prompt_test('a-/e[m-z',null,null,1);
|
||||
.check a-^A^[[m^B-z
|
||||
|
||||
# /e followed by non-[
|
||||
.testcase 7002
|
||||
SELECT shell_prompt_test('a-/eX-z',null,null,1);
|
||||
.check a-^[X-z
|
||||
.testcase 7003
|
||||
SELECT shell_prompt_test('a-/eX/e[m-z',null,null,1);
|
||||
.check a-^[X^A^[[m^B-z
|
||||
.testcase 7004
|
||||
SELECT shell_prompt_test('a-/e[m/eX-z',null,null,1);
|
||||
.check a-^A^[[m^B^[X-z
|
||||
+2
-1
@@ -548,7 +548,8 @@ do_test shell1-3.17.3 {
|
||||
do_test shell1-3.17.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".prompt FOO BAR BAD"
|
||||
} {0 {}}
|
||||
} {1 {line 1: .prompt FOO BAR BAD
|
||||
line 1: ^--- extra argument}}
|
||||
|
||||
# .quit Exit this program
|
||||
do_test shell1-3.18.1 {
|
||||
|
||||
@@ -311,6 +311,7 @@ do_test shell5-1.9 {
|
||||
puts $out {"""",11,121}
|
||||
puts $out {"hello",12,132}
|
||||
close $out
|
||||
catch {db close}
|
||||
forcedelete test.db
|
||||
catchcmd test.db {.mode csv
|
||||
CREATE TABLE t1(a,b,c);
|
||||
|
||||
@@ -103,6 +103,7 @@ foreach {tn schema output} {
|
||||
}
|
||||
|
||||
} {
|
||||
catch {db close}
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
execsql $schema
|
||||
|
||||
@@ -49,5 +49,8 @@ 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
|
||||
|
||||
@@ -550,7 +550,6 @@ char *speedtest1_once(const char *zFormat, ...){
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt;
|
||||
char *zResult = 0;
|
||||
int rc;
|
||||
va_start(ap, zFormat);
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
|
||||
+117
-20
@@ -34,7 +34,15 @@ proc find_interpreter {} {
|
||||
set rc [catch { package require sqlite3 }]
|
||||
if {$rc} {
|
||||
if {[file readable pkgIndex.tcl] && [catch {source pkgIndex.tcl}]==0} {
|
||||
# Since $dir is defined to be the [pwd], if the "source pkgIndex.tcl"
|
||||
# worked, that should have enabled us to use the locally built
|
||||
# copy of the TCL extension.
|
||||
set rc [catch { package require sqlite3 }]
|
||||
if {!$rc} {
|
||||
puts "Using the locally built copy of the \"sqlite3\" tcl extension"
|
||||
} else {
|
||||
puts "The locally built copy of the \"sqlite3\" tcl extension does work..."
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$rc} {
|
||||
@@ -49,7 +57,7 @@ proc find_interpreter {} {
|
||||
}
|
||||
}
|
||||
if {$rc} {
|
||||
puts "Cannot find tcl package sqlite3: Trying to build it now..."
|
||||
puts "Cannot find tcl package \"sqlite3\": Trying to build it now..."
|
||||
if {$::tcl_platform(platform) eq "windows"} {
|
||||
set bat [open make-tcl-extension.bat w]
|
||||
puts $bat "nmake /f Makefile.msc tclextension"
|
||||
@@ -97,15 +105,16 @@ proc usage {} {
|
||||
Usage:
|
||||
$a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS?
|
||||
$a0 PERMUTATION FILE
|
||||
$a0 clean
|
||||
$a0 errors ?-v|--verbose? ?-s|--summary? ?PATTERN?
|
||||
$a0 estwork
|
||||
$a0 halt
|
||||
$a0 help
|
||||
$a0 joblist ?PATTERN?
|
||||
$a0 njob ?NJOB?
|
||||
$a0 retest
|
||||
$a0 script ?-msvc? CONFIG
|
||||
$a0 status ?-d SECS? ?--cls?
|
||||
$a0 halt
|
||||
$a0 estwork
|
||||
|
||||
where SWITCHES are:
|
||||
--buildonly Build test exes but do not run tests
|
||||
@@ -141,25 +150,26 @@ are run. Otherwise, each pattern is interpreted as a glob pattern. Only
|
||||
those tcl tests for which the final component of the filename matches at
|
||||
least one specified pattern are run. The glob wildcard '*' is prepended
|
||||
to the pattern if it does not start with '^' and appended to every
|
||||
pattern that does not end with '$'. If PATTERN begins with "~", then it
|
||||
is an anti-pattern that only matches tests that do not match PATTERN.
|
||||
Tests or only run if they match one or more patterns and match no
|
||||
anti-patterns.
|
||||
|
||||
If no PATTERN arguments are present, then various fuzztest, threadtest
|
||||
and other tests are run as part of the "release" permutation. These are
|
||||
omitted if any PATTERN arguments are specified on the command line.
|
||||
pattern that does not end with '$'. If any PATTERN argument begins with "~",
|
||||
then it is an anti-pattern. When PATTERN arguments are present, tests are
|
||||
only run if they match one or more patterns and match no anti-patterns.
|
||||
|
||||
If a PERMUTATION is specified and is followed by the path to a Tcl script
|
||||
instead of a list of patterns, then that single Tcl test script is run
|
||||
with the specified permutation.
|
||||
|
||||
The "status" and "njob" commands are designed to be run from the same
|
||||
directory as a running testrunner.tcl script that is running tests. The
|
||||
"status" command prints a report describing the current state and progress
|
||||
of the tests. Use the "-d N" option to have the status display clear the
|
||||
screen and repeat every N seconds. The "njob" command may be used to query
|
||||
or modify the number of sub-processes the test script uses to run tests.
|
||||
directory as a running testrunner.tcl script. The "status" command prints
|
||||
a report describing the current state and progress of the tests. Use
|
||||
the "-d N" option to have the status display clear the screen and repeat
|
||||
every N seconds. The "njob" command may be used to query or modify the
|
||||
number of sub-processes the test script uses to run tests.
|
||||
|
||||
The "halt" command modifies the database so that all tasks are marked
|
||||
as complete. Testing will halt when all tests currently running complete.
|
||||
|
||||
The "clean" command removes files and directories created by a prior
|
||||
invocation of testrunner.tcl.
|
||||
|
||||
The "script" command outputs the script used to build a configuration.
|
||||
Add the "-msvc" option for a Windows-compatible script. For a list of
|
||||
@@ -173,7 +183,7 @@ shows the jobs that failed. If PATTERN are provided, the error information
|
||||
is only provided for jobs that match PATTERN.
|
||||
|
||||
The "retest" command reruns tests that failed or were never completed
|
||||
by a prior invocation of testrunner.tcl.
|
||||
by the previous invocation of testrunner.tcl.
|
||||
|
||||
Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md
|
||||
}]]
|
||||
@@ -460,6 +470,32 @@ if {([llength $argv]==2 || [llength $argv]==1)
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check if this is the "clean" command:
|
||||
#
|
||||
if {([llength $argv]==2 || [llength $argv]==1)
|
||||
&& [string compare -nocase clean [lindex $argv 0]]==0
|
||||
} {
|
||||
set pattern {_(fuzzcheck|sessionfuzz|sqlite3|testfixture)}
|
||||
foreach f [glob testrun_*] {
|
||||
if {[file isdir $f] && [regexp $pattern $f]} {
|
||||
file delete -force $f
|
||||
}
|
||||
}
|
||||
foreach f [glob testdir*] {
|
||||
if {[file isdir $f] && [regexp {^testdir[0-9]+$} $f]} {
|
||||
file delete -force $f
|
||||
}
|
||||
}
|
||||
foreach f [glob testrunner.db*] {
|
||||
file delete -force $f
|
||||
}
|
||||
file delete -force testrunner.log
|
||||
exit
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check if this is the "halt" command:
|
||||
#
|
||||
@@ -1177,7 +1213,7 @@ proc job_matches_any_pattern {patternlist jobcmd} {
|
||||
#
|
||||
# e.g
|
||||
#
|
||||
# {1 /home/user/sqlite/test/testrunner_bld_xyz All-Debug}
|
||||
# {1 /home/user/sqlite/test/testrun_xyz All-Debug}
|
||||
#
|
||||
proc add_tcl_jobs {build config patternlist {shelldepid ""}} {
|
||||
global TRG
|
||||
@@ -1243,7 +1279,9 @@ proc add_build_job {buildname target {postcmd ""} {depid ""}} {
|
||||
global TRG
|
||||
|
||||
set dirname "[string tolower [string map {- _} $buildname]]_$target"
|
||||
set dirname "testrunner_bld_$dirname"
|
||||
regsub {\.exe$} $dirname {} dirname
|
||||
regsub {\.l?o$} $dirname {obj} dirname
|
||||
set dirname "testrun_$dirname"
|
||||
|
||||
set cmd "$TRG(makecmd) $target"
|
||||
if {$postcmd!=""} {
|
||||
@@ -1264,6 +1302,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
|
||||
|
||||
@@ -1511,6 +1600,8 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
UPDATE jobs SET depid=$sbldid WHERE depid='SHELL'
|
||||
}
|
||||
}
|
||||
|
||||
add_c_jobs $b
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1878,6 +1969,7 @@ proc run_testset {} {
|
||||
SELECT DISTINCT substr(svers,1,79) as v1 FROM jobs WHERE svers IS NOT NULL
|
||||
} {puts $v1}
|
||||
|
||||
return [expr {$nErr>0}]
|
||||
}
|
||||
|
||||
# If the argument is "retest", simply rerun all tests from the previous
|
||||
@@ -1937,6 +2029,7 @@ proc explain_tests {} {
|
||||
explain_layer "" ""
|
||||
}
|
||||
|
||||
set exit_status 0
|
||||
sqlite3 trdb $TRG(dbname)
|
||||
trdb timeout $TRG(timeout)
|
||||
if {[llength $TRG(patternlist)]==1 && $TRG(patternlist) eq "retest"} {
|
||||
@@ -1955,6 +2048,10 @@ if {$TRG(explain)} {
|
||||
puts "built testset in [expr $tm/1000]ms.."
|
||||
}
|
||||
handle_buildonly
|
||||
run_testset
|
||||
set exit_status [run_testset]
|
||||
}
|
||||
trdb close
|
||||
exit $exit_status
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -787,4 +787,14 @@ do_eqp_test update-21.12 {
|
||||
`--SEARCH t3 USING AUTOMATIC COVERING INDEX (x=?)
|
||||
}
|
||||
|
||||
# /forumpost/2026-04-21T19:10:55Z
|
||||
do_execsql_test update-22.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x INT, y INT);
|
||||
INSERT INTO t1(x) VALUES(1),(2),(3),(4),(5);
|
||||
UPDATE t1 SET x=x+100, y=x<=(SELECT min(x) FROM t1)
|
||||
WHERE x<3 OR (1 BETWEEN 0 AND x<=(SELECT min(x)+2 FROM t1));
|
||||
SELECT x FROM t1 WHERE x<100 ORDER BY x;
|
||||
} {4 5}
|
||||
|
||||
finish_test
|
||||
|
||||
+10
-5
@@ -17,7 +17,8 @@ Options:
|
||||
--uninstall Uninstall the extension
|
||||
--version-check Check extension version against this source tree
|
||||
--destdir DIR Installation root (used by "make install DESTDIR=...")
|
||||
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
|
||||
--tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
|
||||
--extlibs LDFLAGS required for external libs, e.g. ICU.
|
||||
|
||||
Other options are retained and passed through into the compiler.}
|
||||
|
||||
@@ -29,8 +30,9 @@ set infoonly 0
|
||||
set versioncheck 0
|
||||
set CC {}
|
||||
set OPTS {}
|
||||
set DESTDIR ""; # --destdir "$(DESTDIR)"
|
||||
set DESTDIR "" ; # --destdir "$(DESTDIR)"
|
||||
set tclConfigSh ""; # --tclConfig.sh FILE
|
||||
set LIBS {} ; # --extlibs "-lx -ly ..."
|
||||
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
|
||||
set a0 [lindex $argv $ii]
|
||||
if {$a0=="--install-only"} {
|
||||
@@ -61,6 +63,9 @@ for {set ii 0} {$ii<[llength $argv]} {incr ii} {
|
||||
} elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} {
|
||||
incr ii
|
||||
set tclConfigSh [lindex $argv $ii]
|
||||
} elseif {$a0=="--extlibs" && $ii+1<[llength $argv]} {
|
||||
incr ii
|
||||
lappend LIBS [lindex $argv $ii]
|
||||
} elseif {[string match -* $a0]} {
|
||||
append OPTS " $a0"
|
||||
} else {
|
||||
@@ -152,8 +157,8 @@ if {$tcl_platform(platform) eq "windows"} {
|
||||
}
|
||||
set CFLAGS -fPIC
|
||||
regexp {TCL_SHLIB_CFLAGS='([^']+)'} $tclConfig all CFLAGS
|
||||
set LIBS {}
|
||||
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBS
|
||||
regexp {TCL_STUB_LIB_SPEC='([^']+)'} $tclConfig all LIBSTUB
|
||||
lappend LIBS $LIBSTUB
|
||||
set INC "-I$srcdir/src"
|
||||
set inc {}
|
||||
regexp {TCL_INCLUDE_SPEC='([^']+)'} $tclConfig all inc
|
||||
@@ -312,7 +317,7 @@ package ifneeded sqlite3 $VERSION \\
|
||||
|
||||
# Generate and execute the command with which to do the compilation.
|
||||
#
|
||||
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT $LIBS"
|
||||
set cmd "$CMD -DUSE_TCL_STUBS tclsqlite3.c -o $OUT [join $LIBS { }]"
|
||||
puts $cmd
|
||||
file delete -force $OUT
|
||||
catch {exec {*}$cmd} errmsg
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
|
||||
** interstitial "-" characters) contained in this template is changed into
|
||||
** the value of the %name directive from the grammar. Otherwise, the content
|
||||
** of this template is copied straight through into the generate parser
|
||||
** of this template is copied straight through into the generated parser
|
||||
** source file.
|
||||
**
|
||||
** The following is the concatenation of all %include directives from the
|
||||
|
||||
+1
-1
@@ -1900,7 +1900,7 @@ static void showHelp(void){
|
||||
}
|
||||
|
||||
/* work-around the Microsoft "WorstFit" bug */
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(main)
|
||||
#define main utf8_main
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user